diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-17 13:39:23 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-17 13:39:23 +0200 |
| commit | ad4ca3229002997934ccb5b2eaeb553c13b8888f (patch) | |
| tree | a680f9e5d3ba43a84236b84f73e0b71eaf916db4 /packages/meshbay-hub/src/meshbay_hub/static/locales | |
| parent | 3e6d514663a5df1be3b2f0286c5f67f669d9c1d6 (diff) | |
| download | meshbay-ad4ca3229002997934ccb5b2eaeb553c13b8888f.tar.gz | |
feat: embedded subtitles in the video player (MNP 3.3)
MSE decodes no in-band text track, so a subtitle cannot ride inside the
fragmented MP4 the player is fed. The node extracts one track whole, converts
it to WebVTT and caches it under its own hash; the client pulls that blob
through the ordinary file_req/chunk path and hangs a <track> on the video
element — the same indirection as a TMDB poster or an audio transcode, which
is what makes a film's subtitles extracted once in the life of the file rather
than once per viewing. Whole-file also makes the cues absolute, so a seek and
an audio-language change both leave the track untouched.
**The ordinal counts every subtitle stream, including the ones never listed.**
Only text codecs are offered: a bitmap track (PGS, VOBSUB — about a fifth of a
real library) has no path to WebVTT without OCR, and one extracted anyway
yields a header with no cues, which is a menu entry that shows nothing and
reports no error. Numbering the survivors of that filter would give a
PGS/SRT/SRT file the ordinals 0 and 1 for its text tracks and `-map 0:s:0`
would then extract the PGS — the same trap `AudioTrack.ordinal` exists for,
one level deeper. A fixture whose first subtitle stream cannot be decoded pins
it, and the handler checks membership of the probed list, never a range.
Additive and MINOR: the selector is drawn from `subtitle_tracks` in the node's
own `stream_init` and from no version number, so `subtitle_req` is never sent
to a peer that would not answer it. The floor stays at 3.0.
Also here: a failed extraction never touches playback, a superseded reply
cannot install its blob over a newer choice, and `_languageName` is shared
with the audio labels — lifted by both label harnesses, since a lift that
names one function stops covering the rule the moment logic moves out of it.
Tests: 9 node (tracks told apart by the words in the extracted cues, not by
tags), 10 client. Full suite green: 1545 node/common, 1252 hub.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UGY17EPph5LsLzePPXhUVc
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/locales')
10 files changed, 40 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js index 806fa38..dd53bcf 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js @@ -251,6 +251,10 @@ export default { 'video.from_start': "Von vorn beginnen", 'video.audio_track': 'Tonspur', 'video.audio_track_n': 'Spur {n}', + 'video.subtitles': 'Untertitel', + 'video.subtitles_off': 'Aus', + 'video.subtitle_track_n': 'Spur {n}', + 'video.err_subtitle': 'Diese Untertitelspur konnte nicht geladen werden', 'video.close': 'Schließen (Esc)', 'preview.pdf_fallback': 'Dieser Browser zeigt das PDF nicht direkt an. Laden Sie es ' + 'stattdessen herunter — entschlüsselt wurde es ohnehin hier.', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/en.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/en.js index 92114c9..e9f3d8d 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/en.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/en.js @@ -250,6 +250,10 @@ export default { 'video.from_start': "Start from the beginning", 'video.audio_track': 'Audio track', 'video.audio_track_n': 'Track {n}', + 'video.subtitles': 'Subtitles', + 'video.subtitles_off': 'Off', + 'video.subtitle_track_n': 'Track {n}', + 'video.err_subtitle': 'Could not load this subtitle track', 'video.close': 'Close (Esc)', 'preview.pdf_fallback': 'This browser will not display the PDF inline. Download it instead — it was decrypted here either way.', 'preview.too_large': 'This file is {size}, more than this page can hold in memory ({limit}). Download it instead — a download is written straight to disk.', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/es.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/es.js index d9b8f63..68fbe10 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/es.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/es.js @@ -249,6 +249,10 @@ export default { 'video.from_start': "Empezar desde el principio", 'video.audio_track': 'Pista de audio', 'video.audio_track_n': 'Pista {n}', + 'video.subtitles': 'Subtítulos', + 'video.subtitles_off': 'Ninguno', + 'video.subtitle_track_n': 'Pista {n}', + 'video.err_subtitle': 'No se pudo cargar esta pista de subtítulos', 'video.close': 'Cerrar (Esc)', 'preview.pdf_fallback': 'Este navegador no mostrará el PDF integrado. Descárguelo ' + 'en su lugar — en cualquier caso se descifró aquí.', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/fr.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/fr.js index d507d28..679a458 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/fr.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/fr.js @@ -250,6 +250,10 @@ export default { 'video.from_start': "Reprendre depuis le début", 'video.audio_track': 'Piste audio', 'video.audio_track_n': 'Piste {n}', + 'video.subtitles': 'Sous-titres', + 'video.subtitles_off': 'Aucun', + 'video.subtitle_track_n': 'Piste {n}', + 'video.err_subtitle': 'Impossible de charger cette piste de sous-titres', 'video.close': 'Fermer (Échap)', 'preview.pdf_fallback': 'Ce navigateur n’affichera pas le PDF directement. ' + 'Téléchargez-le plutôt — il a été déchiffré ici dans les deux cas.', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/it.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/it.js index b6c68dd..9a34c93 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/it.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/it.js @@ -250,6 +250,10 @@ export default { 'video.from_start': "Riparti dall'inizio", 'video.audio_track': 'Traccia audio', 'video.audio_track_n': 'Traccia {n}', + 'video.subtitles': 'Sottotitoli', + 'video.subtitles_off': 'Nessuno', + 'video.subtitle_track_n': 'Traccia {n}', + 'video.err_subtitle': 'Impossibile caricare questa traccia di sottotitoli', 'video.close': 'Chiudi (Esc)', 'preview.pdf_fallback': 'Questo browser non mostrerà il PDF nella pagina. Lo scarichi ' + 'invece — in ogni caso è stato decifrato qui.', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/ja.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/ja.js index 99e2e1f..1d58e2c 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/ja.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/ja.js @@ -247,6 +247,10 @@ export default { 'video.from_start': "最初から再生する", 'video.audio_track': '音声トラック', 'video.audio_track_n': 'トラック {n}', + 'video.subtitles': '字幕', + 'video.subtitles_off': 'なし', + 'video.subtitle_track_n': 'トラック {n}', + 'video.err_subtitle': 'この字幕トラックを読み込めませんでした', 'video.close': '閉じる(Esc)', 'preview.pdf_fallback': 'このブラウザーはページ内に PDF を表示しません。' + 'ダウンロードしてご覧ください。いずれにせよ復号はここで行われています。', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/nl.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/nl.js index 269fa70..5bef61f 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/nl.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/nl.js @@ -251,6 +251,10 @@ export default { 'video.from_start': "Vanaf het begin afspelen", 'video.audio_track': 'Audiospoor', 'video.audio_track_n': 'Spoor {n}', + 'video.subtitles': 'Ondertiteling', + 'video.subtitles_off': 'Geen', + 'video.subtitle_track_n': 'Spoor {n}', + 'video.err_subtitle': 'Dit ondertitelspoor kon niet worden geladen', 'video.close': 'Sluiten (Esc)', 'preview.pdf_fallback': 'Deze browser toont de PDF niet in de pagina zelf. Download ' + 'hem in plaats daarvan — ontsleuteld werd hij hoe dan ook hier.', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js index 363296c..8989880 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js @@ -256,6 +256,10 @@ export default { 'video.from_start': "Odtwórz od początku", 'video.audio_track': 'Ścieżka dźwiękowa', 'video.audio_track_n': 'Ścieżka {n}', + 'video.subtitles': 'Napisy', + 'video.subtitles_off': 'Brak', + 'video.subtitle_track_n': 'Ścieżka {n}', + 'video.err_subtitle': 'Nie udało się wczytać tej ścieżki napisów', 'video.close': 'Zamknij (Esc)', 'preview.pdf_fallback': 'Ta przeglądarka nie wyświetli pliku PDF na stronie. Proszę ' + 'go pobrać — i tak został odszyfrowany tutaj.', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/pt-BR.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/pt-BR.js index 2a90956..f1b8643 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/pt-BR.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/pt-BR.js @@ -251,6 +251,10 @@ export default { 'video.from_start': "Começar do início", 'video.audio_track': 'Faixa de áudio', 'video.audio_track_n': 'Faixa {n}', + 'video.subtitles': 'Legendas', + 'video.subtitles_off': 'Nenhuma', + 'video.subtitle_track_n': 'Faixa {n}', + 'video.err_subtitle': 'Não foi possível carregar esta faixa de legendas', 'video.close': 'Fechar (Esc)', 'preview.pdf_fallback': 'Este navegador não exibirá o PDF na própria página. Baixe ' + 'o arquivo — de todo modo ele foi descriptografado aqui.', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/zh-CN.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/zh-CN.js index e3aa440..91da464 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/zh-CN.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/zh-CN.js @@ -245,6 +245,10 @@ export default { 'video.from_start': "从头开始播放", 'video.audio_track': '音轨', 'video.audio_track_n': '音轨 {n}', + 'video.subtitles': '字幕', + 'video.subtitles_off': '关闭', + 'video.subtitle_track_n': '字幕 {n}', + 'video.err_subtitle': '无法加载此字幕轨道', 'video.close': '关闭(Esc)', 'preview.pdf_fallback': '此浏览器不会在页面内显示该 PDF。请改为下载——无论如何它都已在本地解密。', 'preview.too_large': '该文件为 {size},超出本页面可在内存中保存的上限({limit})。请改为下载——下载会直接写入磁盘。', |