summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src/meshbay_node
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node')
-rw-r--r--packages/meshbay-node/src/meshbay_node/media_probe.py14
-rw-r--r--packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py6
2 files changed, 20 insertions, 0 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/media_probe.py b/packages/meshbay-node/src/meshbay_node/media_probe.py
index 06b1e28..81174c8 100644
--- a/packages/meshbay-node/src/meshbay_node/media_probe.py
+++ b/packages/meshbay-node/src/meshbay_node/media_probe.py
@@ -69,6 +69,16 @@ class SubtitleTrack:
language: str | None
title: str | None
codec_name: str | None
+ # **A forced track is not a shorter version of the full one.** It carries
+ # only signage and the lines spoken in another language — measured on a
+ # real film: 30 cues and 77 seconds of text across 2h32, against 1559 cues
+ # and 41% of the running time for the full track beside it. Picking it and
+ # seeing nothing for ten minutes is the ordinary outcome, not a fault, and
+ # nothing in the menu let a viewer tell those two apart. The disposition is
+ # what says which it is; the title tag that would also say it ("Forced",
+ # "SDH") is absent as often as it is present.
+ forced: bool = False
+ hearing_impaired: bool = False
@dataclass
@@ -143,6 +153,7 @@ async def probe_video(path: str) -> VideoProbe:
"-show_entries",
"stream=codec_name,profile,level,codec_type,width,height,channels",
"-show_entries", "stream_tags=language,title",
+ "-show_entries", "stream_disposition=forced,hearing_impaired",
"-show_entries", "format=duration",
"-of", "json", path,
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
@@ -192,11 +203,14 @@ async def probe_video(path: str) -> VideoProbe:
if codec_name not in TEXT_SUBTITLE_CODECS:
continue
tags = s.get("tags") or {}
+ disp = s.get("disposition") or {}
subtitle_tracks.append(SubtitleTrack(
ordinal=ordinal,
language=(tags.get("language") or "").strip() or None,
title=(tags.get("title") or "").strip() or None,
codec_name=codec_name,
+ forced=bool(disp.get("forced")),
+ hearing_impaired=bool(disp.get("hearing_impaired")),
))
has_audio = bool(audio_tracks)
diff --git a/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py b/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py
index 1e85f29..2863679 100644
--- a/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py
+++ b/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py
@@ -6267,6 +6267,12 @@ class WebRTCPeerSession:
"lang": tr.language,
"title": tr.title,
"codec": tr.codec_name,
+ # What tells a full translation from signage-only. Without
+ # it the two are the same menu entry, and picking the
+ # forced one shows nothing for minutes at a time — which
+ # reads as a broken feature and was reported as one.
+ "forced": tr.forced,
+ "sdh": tr.hearing_impaired,
}
for tr in probe.subtitle_tracks
],