After hitting the segment-timing wall on our hand-rolled DASH MPD
(audio drifted -25s -> -44s behind video on long content), pivoted to
delegating playback to plugin.video.youtube v7.4.3 which already has
years of sidx-parsed SegmentTimeline + multi-client fallback work.
torttube._play() now:
1. Tries _delegate_to_pv_youtube(yt_id) — sets a resolved URL of
'plugin://plugin.video.youtube/play/?video_id=<id>'. Kodi
chain-resolves to pv.youtube which builds the proper MPD and
hands inputstream.adaptive a correctly-aligned manifest. Default.
2. Falls back to our DASH builder (still in code, gated by
'dash_enabled' setting + dash.on marker) if pv.youtube is absent.
3. Falls through to yt-dlp progressive 360p as the final safety net.
When delegating, we skip our SponsorBlock monitor — pv.youtube has its
own and would double-skip otherwise.
Cobb-verified live on Livingroom Pi: LTT 'Trump Phone' (which crashed
our DASH with audio sync errors growing to -44s) now plays HD with
audio synced. 'Please sign in' message in log is from the tv_unplugged
Innertube client; pv.youtube falls back to a working client
automatically — no user account required.
Settings: prefer_pv_youtube boolean (default true). Addon v0.0.11.
Reference: https://kodi.wiki/view/Add-on:YouTube
Big strides today:
- Sidecar resolve_dash op works (verified live on Pi)
- MPD builder generates valid MPEG-DASH on-demand manifest with
H.264 720p/1080p video reps + best AAC audio rep
- ThreadingHTTPServer serves the MPD over the LAN IP (not 127.0.0.1
— curl in Kodi 20's inputstream.adaptive can't open that)
- inputstream.adaptive PARSES our manifest cleanly: 'Successfully
parsed manifest file (Periods: 1, Streams in first period: 2)'
- Segment GETs work once we set stream_headers with User-Agent
+ Origin + Referer (otherwise googlevideo 403s the audio segments)
Remaining issue:
- Audio drifts -25s → -44s behind video within seconds of playback
start. inputstream.adaptive needs explicit SegmentTimeline timing
derived from each rep's sidx box to stay aligned. Plugin.video.youtube
does this; we'd need to fetch+parse sidx ourselves or fork their
MPD-builder. Documented as M7-blocking + upstream PR candidate.
Default remains the stable yt-dlp progressive 360p path. DASH is
behind dash_enabled setting OR a dash.on marker file in addon_data.
Toggle on via:
ssh <kodi> 'touch /storage/.kodi/userdata/addon_data/plugin.video.torttube/dash.on'
Toggle off:
ssh <kodi> 'rm /storage/.kodi/userdata/addon_data/plugin.video.torttube/dash.on'
Addon v0.0.10. docs/upstream.md has the full segment-timing analysis.
Sidecar Playlist op via rustypipe playlist(). Returns playlist metadata
block (id, name, channel, video_count) + items array. Verified live
against LTT's 'Consumer Advocacy' (PL8mG-RkN2uTzwoF72GqeqAJMI-N7scqtI):
returns the single video with full metadata.
Addon ?action=playlist&id=PL... lists items via _add_video_items reuse.
Verified via Files.GetDirectory JSON-RPC.
resources/settings.xml gains a 'dash_enabled' toggle (boolean, default
off). main.py checks ADDON.getSettingBool('dash_enabled') OR the
TORTTUBE_DASH env fallback before attempting the DASH path. Toggle via
Kodi Settings → Add-on settings → torttube, OR via
Addons.SetSettings JSON-RPC.
docs/upstream.md: filed a 'watching' entry for rustypipe PR #77
(Schmiddiii's late-May YouTube parsing fixes) with our independent
test data — player(), search(), and channel_videos() all still work
against current YouTube on 0.11.4, suggesting the PR fixes code paths
torttube doesn't yet exercise. Endorsement comment pending: gated on
creating a Sulkta-Coop codeberg account.
Observation from kodi.log: plugin.video.youtube successfully parsed a
DASH MPD with 26 streams via inputstream.adaptive on this same Pi —
proves DASH is solvable on our setup, just need to match the URL
pattern they use. M7 stabilization carrying forward.
Addon version 0.0.9.
Sidecar resolve_dash op shipped — returns rustypipe's full video_only_streams
+ audio_streams (16+ representations for NGGYU, from 360p H.264 through 4K
AV1). Addon _build_dash_mpd assembles a valid on-demand MPEG-DASH manifest
filtered to H.264 ≤1080p + best AAC audio.
Two unblocked-by-WIP issues surfaced during integration:
- inputstream.adaptive's libcurl can't open file:// URLs (logged in
docs/upstream.md as an enhancement-target).
- Rapid Player.Open retries can trigger Kodi's 'two concurrent
busydialogs' fatal exit; need lifecycle hardening before re-enabling.
Pivoted to localhost HTTP-server serving (ThreadingHTTPServer on a
port-0 socket, MPD bytes captured in a per-instance handler subclass).
Lifecycle: server.shutdown() runs in a finally block after the
SponsorBlockMonitor watcher exits. Works in isolation but Kodi crashed
under rapid retry conditions — needs more testing.
For v0.0.5: DASH path is gated behind TORTTUBE_DASH=1 env var; default
falls through to the stable yt-dlp progressive 360p path that's been
verified live. M7 milestone added to track the remaining work; PRs
to inputstream.adaptive + Kodi candidates logged in docs/upstream.md.
Cobb wants rustypipe primary, yt-dlp fallback, and rip-to-temp as the
last-resort path when streams die mid-play. README expanded to spell
out all three tiers + adds the 'fight YouTube alongside the FOSS
ecosystem' framing. MILESTONES M1 rewritten to cover all three tiers.
New file docs/upstream.md tracks every PR we file against rustypipe /
NPE / yt-dlp with honest outcomes. Opens empty; fills as M1+ surface
real bugs to fix.