diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-19 13:45:56 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-19 13:45:56 +0200 |
| commit | f8223293a211a87c92b1fed80f5ca53660f6b26c (patch) | |
| tree | 02beb40e677389ade10c15d6040b19d67bb2dd93 /packages/meshbay-node/tests | |
| parent | eca01c7f970d2d3ab2298f934da9776fe01179c6 (diff) | |
| download | meshbay-f8223293a211a87c92b1fed80f5ca53660f6b26c.tar.gz | |
fix(node): the node decides which files it will transcode, not the player
`BROWSER_INCOMPATIBLE_AUDIO_EXTS` named the two formats no browser decodes and
was read by nothing. The player asked for `.wma` and `.mpc` and no others, and
`music-player.js` called itself "kept in sync with the node's" constant — so the
entire restriction lived in the caller, and a member's own message is not the
caller.
What that let through: this converts a whole file and holds a transcode slot
shared with video streaming while it runs. One message naming a two-hour film
spends minutes of the operator's CPU and a slot every other viewer is queued
behind. `AUDIO_TRANSCODE_MAX_BYTES` catches the result, after the work is done;
only the extension catches the work.
The client comment now says what it is — an optimisation that saves asking for a
refusal — rather than implying it is the rule.
Two tests: a film is refused before ffmpeg is reached, and a WMA still passes,
because a gate that refuses everything is not a gate.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/tests')
| -rw-r--r-- | packages/meshbay-node/tests/test_audio_transcode.py | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/packages/meshbay-node/tests/test_audio_transcode.py b/packages/meshbay-node/tests/test_audio_transcode.py index 3e6015d..a6557f0 100644 --- a/packages/meshbay-node/tests/test_audio_transcode.py +++ b/packages/meshbay-node/tests/test_audio_transcode.py @@ -191,3 +191,39 @@ async def test_multi_chunk_cached_blob_reassembles_correctly(tmp_path, media_cac assert len(chunk_msgs) == total_chunks reassembled = _reassemble_file_chunks(session.sent, gek, blob_hash) assert reassembled == blob + + +async def test_only_the_two_formats_that_need_it_are_transcoded(tmp_path, media_cache): + """ + The gate that was written down and never applied. + + `BROWSER_INCOMPATIBLE_AUDIO_EXTS` was read by nobody: the player asked only + for `.wma` and `.mpc`, and the node converted whatever file id it was given. + A member's own message is not the player, and this conversion is whole-file + while holding a transcode slot shared with video streaming — so one message + naming a two-hour film spends minutes of the operator's CPU and a slot every + other viewer is queued behind. The size cap catches the result; only this + catches the work. + """ + clip = tmp_path / "feature.mkv" + clip.write_bytes(b"not really a film, and never opened") + session, file_id = _session(tmp_path, clip, generate_gek(), media_cache) + + await session._do_audio_transcode_request({"file_id": file_id}) + + (msg,) = session.sent + assert msg["type"] == "error" + assert msg["code"] == "transcode_not_applicable" + + +@pytest.mark.skipif(not _HAVE_FFMPEG, reason="ffmpeg/ffprobe not installed") +async def test_the_two_formats_that_do_need_it_still_pass(tmp_path, media_cache): + """The gate must admit what it exists for; a refusal of everything is not a gate.""" + clip = tmp_path / "clip.wma" + _make_wma_clip(clip) + session, file_id = _session(tmp_path, clip, generate_gek(), media_cache) + + await session._do_audio_transcode_request({"file_id": file_id}) + + assert [m for m in session.sent if m.get("type") == MNP.AUDIO_TRANSCODE_RESP], ( + f"a WMA file was refused: {session.sent}") |