From 1b0a3db4392f99bc60478e0da414b3efb85ce277 Mon Sep 17 00:00:00 2001 From: foxyz Date: Sun, 11 Oct 2026 01:53:36 +0300 Subject: [PATCH] Player: leave Bilibili's danmaku out of yt-dlp subtitles (it stalled playback) The danmaku XML is served raw-deflate; ffmpeg fails to inflate it on every read, logging a warning each time (millions, drained on the UI thread) while the video waits on the track: a frame every few seconds. mpv's hook now asks yt-dlp for sub-langs all,-danmaku. Co-Authored-By: Claude Opus 5.5 --- apps/desktop/lib/src/playback/yt_dlp_app.dart | 16 ++++++++++++---- docs/ARCHITECTURE.md | 4 +++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/apps/desktop/lib/src/playback/yt_dlp_app.dart b/apps/desktop/lib/src/playback/yt_dlp_app.dart index 151e1a1..3316e81 100644 --- a/apps/desktop/lib/src/playback/yt_dlp_app.dart +++ b/apps/desktop/lib/src/playback/yt_dlp_app.dart @@ -7,6 +7,12 @@ import 'package:sync_relay_core/core.dart'; /// mpv's `ytdl-format` for links every player opens itself. const ytdlFormat = 'bv*[height<=1080]+ba/b'; +/// yt-dlp's `--sub-langs` for mpv's hook (its default is `all`), without +/// Bilibili's danmaku: an XML comment feed served raw-deflate, which +/// ffmpeg fails to inflate on every read (a warning each time) while the +/// video waits on it. +const ytdlSubLangs = 'all,-danmaku'; + /// The app's yt-dlp (see [YtDlp]): in the app-support folder, shared with /// the hosted server. [probe] remembers what pasted links are for a while, /// so the Link preview and the swap ask once. @@ -28,13 +34,15 @@ class AppYtDlp { /// update check afterwards). void warmUp() => unawaited(ytDlp.then((y) => y.ensure()).catchError((_) => null)); - /// mpv's `ytdl-raw-options` for the cookies in the yt-dlp folder ('' for - /// none; see [YtDlpCookies]). + /// mpv's `ytdl-raw-options`: [ytdlSubLangs] and the cookies in the + /// yt-dlp folder (see [YtDlpCookies]). Future mpvRawOptions() async { + const subs = 'sub-langs=%${ytdlSubLangs.length}%$ytdlSubLangs'; try { - return (await ytDlp).cookies.mpvRawOptions(); + final cookies = (await ytDlp).cookies.mpvRawOptions(); + return cookies.isEmpty ? subs : '$subs,$cookies'; } catch (_) { - return ''; + return subs; } } diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index ad617a6..0eaf0dc 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -638,7 +638,9 @@ all three link modes. Nothing is bundled or installed by hand. own drop target is off on Settings so only this box takes the file); its hosted server shares the folder, so it uses them too. mpv's hook gets the same as `ytdl-raw-options` (`cookies=%N%` / `cookies-from-browser=%N%`, length-quoted), - re-set before each external link when it changed. The dedicated + re-set before each external link when it changed, after + `sub-langs=all,-danmaku` (Bilibili's danmaku XML is served raw-deflate: + ffmpeg warns on every read and the video waits on the track). The dedicated server: `--yt-dlp-cookies ` / `ytDlpCookies` converted into its folder at start; without it the copy and browser setting are removed. Values are never logged and never leave the machine.