aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src/meshbay_node/media_probe.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/media_probe.py')
-rw-r--r--packages/meshbay-node/src/meshbay_node/media_probe.py30
1 files changed, 24 insertions, 6 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/media_probe.py b/packages/meshbay-node/src/meshbay_node/media_probe.py
index 8ad883d..6dd3baa 100644
--- a/packages/meshbay-node/src/meshbay_node/media_probe.py
+++ b/packages/meshbay-node/src/meshbay_node/media_probe.py
@@ -11,11 +11,22 @@ import json
_H264_PROFILES = {"Baseline": "42", "Main": "4d", "High": "64", "High 10": "6e"}
+# Source video codecs whose MSE codec string is real but which no mainstream
+# browser can actually decode via MediaSource on most desktop platforms — HEVC
+# has no royalty-free decoder in Chrome/Firefox on Linux (and is spotty even
+# on platforms with one). Found live: a real HEVC/EAC3 WEB-DL reported
+# "Codec not supported for streaming: hev1.1.6.L93.B0,mp4a.40.2" from
+# MediaSource.isTypeSupported, even though ffprobe/VLC play it fine. VP9/AV1
+# are not in this set — those decode natively in every mainstream browser.
+BROWSER_INCOMPATIBLE_VIDEO_CODECS = frozenset({"hevc"})
-async def probe_video(path: str) -> tuple[str | None, float, bool, int | None, int | None]:
+
+async def probe_video(
+ path: str,
+) -> tuple[str | None, float, bool, int | None, int | None, str | None]:
"""
Probe video file with ffprobe, return (MSE codec string, duration,
- has_audio, width, height).
+ has_audio, width, height, raw video codec name).
The audio half of the codec string is always "mp4a.40.2" (AAC-LC) or
absent — never the source's real audio codec — because the streaming
@@ -24,8 +35,13 @@ async def probe_video(path: str) -> tuple[str | None, float, bool, int | None, i
that (AC-3, E-AC-3, DTS, ...) is at best silently unplayable and at
worst, for E-AC-3 at least, makes ffmpeg itself refuse to write the
fragmented MP4 header ("Cannot write moov atom before EAC3 packets
- parsed" — reproduced against a real 5.1 E-AC-3 WEB-DL). Video stays
- whatever it actually is: it is always copied, never transcoded.
+ parsed" — reproduced against a real 5.1 E-AC-3 WEB-DL). Video is copied
+ whenever the browser can decode it directly; the raw codec name is
+ returned alongside the MSE string so the caller can decide whether this
+ source needs a real re-encode instead (BROWSER_INCOMPATIBLE_VIDEO_CODECS
+ above) — the MSE string alone can't drive that decision, since it still
+ faithfully reports "hev1..." for a source this pipeline cannot actually
+ deliver copied.
width/height come from the same ffprobe call (one extra `-show_entries`
field, no second process spawn) — resolution is deliberately never
@@ -43,12 +59,14 @@ async def probe_video(path: str) -> tuple[str | None, float, bool, int | None, i
duration = float(info.get("format", {}).get("duration", 0))
v_codec = ""
+ raw_codec_name: str | None = None
has_audio = False
width: int | None = None
height: int | None = None
for s in info.get("streams", []):
if s.get("codec_type") == "video" and not v_codec:
cn = s.get("codec_name", "")
+ raw_codec_name = cn or None
if cn == "h264":
p = _H264_PROFILES.get(s.get("profile", "High"), "64")
lvl = int(s.get("level", 40))
@@ -65,6 +83,6 @@ async def probe_video(path: str) -> tuple[str | None, float, bool, int | None, i
has_audio = True
if not v_codec:
- return None, duration, has_audio, width, height
+ return None, duration, has_audio, width, height, raw_codec_name
codec = f"{v_codec},mp4a.40.2" if has_audio else v_codec
- return codec, duration, has_audio, width, height
+ return codec, duration, has_audio, width, height, raw_codec_name