torttube/MILESTONES.md
Kayos 76bd1d970e M0 docs — lock three-tier resolve + upstream-contribution posture
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.
2026-05-23 08:20:50 -07:00

2.9 KiB

torttube milestones

M0 — Scaffold [current]

  • Sulkta-Coop/torttube on LAN Gitea
  • Layout: addon/ (Python) + sidecar/ (Rust workspace)
  • GPL-3.0 license headers
  • crafting-table build target produces a static aarch64 sidecar binary

M1 — sidecar resolve (three-tier)

  • reads {"op":"resolve","id":"<yt-id>"} from stdin
  • Tier 1: rustypipe → {"streams":[…],"title":"…","duration_s":N,"source":"rustypipe"}
  • Tier 2: on Tier-1 failure, shell out to yt-dlp -j <url> → same JSON shape with "source":"yt-dlp"
  • Tier 3: new op {"op":"rip","id":"<yt-id>","dest":"/storage/.kodi/temp/torttube/<id>.<ext>"} invoked by addon on Tier-1+2 stream failures or 403-mid-play; yt-dlp downloads file, sidecar returns local path
  • typed errors for age-restricted / region-restricted / private (not panics)
  • sig decoding verified against a known-good video
  • DASH manifest URL or per-itag direct stream URL — whichever inputstream.adaptive prefers

M2 — SponsorBlock

  • {"op":"sponsorblock","id":"<yt-id>"} → segments array
  • SHA-256 prefix lookup (privacy-preserving — only send first 4 hex chars)
  • category filter honoured from addon settings (skip / mute / show only)
  • cache per-session

M3 — Kodi addon plays one video

  • addon.xml + main.py register as video plugin
  • hardcoded list of 3 test videos
  • select → sidecar resolve → stream URL → Kodi player
  • verified end-to-end on LibreELEC RPi at 192.168.0.158

M4 — search + channel browse

  • search box → sidecar {"op":"search","q":"…"} → results
  • channel browse → {"op":"channel","id":"…"}
  • playlist browse → {"op":"playlist","id":"…"}
  • result thumbnails + duration + uploader

M5 — SponsorBlock skipping

  • background thread on Player() polls position
  • when position enters a skip segment → xbmc.Player().seekTime(end)
  • toast on skip + skip-counter in settings
  • category toggles in settings.xml

M6 — install + cross-compile

  • crafting-table builds torttube-sidecar.aarch64 + .armv7
  • addon.zip ships with platform detect via xbmc.getCondVisibility('system.platform.linux.raspberrypi')
  • one-shot install path documented for LibreELEC /storage/.kodi/

Upstream PR work (parallel lane — every bug evaluated for "fix it upstream?")

This isn't a separate milestone, it's a posture. Every sidecar bug we diagnose: ask "is this rustypipe / NPE / yt-dlp's bug?" — if yes, fix lands upstream too. Log every filed PR in docs/upstream.md.

Opening shortlist:

  • rustypipe PR #77 — review + help land
  • NPE #1357 (JDoc) — smallest credible PR, opens the relationship
  • NPE #1444 (typed errors) — clean signal/contract change
  • NPE #1360 (refactor link handlers, "help wanted")
  • rustypipe ↔ NPE port — anything one project has that the other lacks