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.
|
||
|---|---|---|
| addon/plugin.video.torttube | ||
| docs | ||
| scripts | ||
| sidecar | ||
| .gitignore | ||
| LICENSE | ||
| MILESTONES.md | ||
| README.md | ||
torttube
Kodi addon for YouTube via RustyPipe extraction + SponsorBlock segment skipping.
Replaces the dead plugin.video.youtube on LibreELEC RPi TVs after Google
required account-linking for the upstream addon.
Architecture
Kodi (LibreELEC, RPi)
└── plugin.video.torttube [Python addon — UI, browse, settings]
└── torttube-sidecar [Rust binary — JSON-over-stdio]
├── rustypipe [Tier 1: native Rust Innertube]
├── yt-dlp subprocess [Tier 2: fallback resolve]
├── yt-dlp rip-to-temp [Tier 3: download to /storage/.kodi/temp,
│ play local file when streams die mid-play]
└── sponsorblock [REST client, SHA-256 prefix lookup]
Kodi addons are Python — the engine layer (n-param sig decoding, Innertube, SponsorBlock hashing) lives in a Rust sidecar so we get a single maintained extraction surface and clean aarch64/armv7 cross-compiles.
Three-tier resolve because YouTube actively fights every extractor:
- rustypipe (Rust) — preferred. Fast, in-process, no Python dep on the RPi.
- yt-dlp subprocess — fallback when rustypipe sig-decoding falls behind YouTube's deobfuscator changes. yt-dlp updates weekly; we shell out, parse
-jJSON. - Rip-to-temp — last resort when stream URLs 403 mid-playback (poToken expiry, cookie session mismatch). yt-dlp downloads to
/storage/.kodi/temp/torttube/<id>.<ext>, Kodi plays the local file. Temp dir has size cap + age cleanup.
Status
M0 scaffold. Nothing playable yet — see MILESTONES.md.
Upstream — we fight with the FOSS extractor ecosystem, not next to it
YouTube's anti-scraping changes hit every extractor: NewPipe, yt-dlp, Invidious, rustypipe. Every fix we make in our sidecar gets evaluated for "is this upstreamable?" — if yes, the fix lands at the upstream project, not just here.
Active lanes:
- rustypipe (Rust, codeberg.org/ThetaDev/rustypipe) — maintenance has slowed.
Open PR #77 "Some fixes" is unmerged as of 2026-05-23. We will either help land
it (review + ping maintainer) or fork to
Sulkta-Coop/rustypipeif upstream stays quiet. Forking is the worst case, not the first move. - NewPipeExtractor (Java, github.com/TeamNewPipe/NewPipeExtractor) — actively maintained, 177 open issues. We use it as the reference implementation for Innertube behaviour. PRs to NPE land in Rust here via rustypipe, and vice versa.
- yt-dlp (Python, github.com/yt-dlp/yt-dlp) — the gold standard. We're more consumers than contributors here, but if our rip-to-temp tier surfaces a specific extractor bug we file it.
Issues we're watching:
- NPE #1339 — n-parameter deobfuscation
- NPE #1444 — distinguish unavailable vs unextractable
- NPE #1360 — refactor link handlers (help wanted)
- NPE #1357 — JDoc checks in PR pipeline (good first issue)
- rustypipe PR #77 — open as of 2026-05-23, unmerged
Contribution log lives at docs/upstream.md — every PR we file lands there with its outcome.
License
GPL-3.0-or-later. Matches RustyPipe and NewPipeExtractor.