torttube/docs/install.md
Kayos 284fe5fde7 M6 DONE — torttube ships, Rick Astley plays fullscreen on the Livingroom Pi
Live install verified end-to-end:
- SSH'd into 192.168.0.158 (LibreELEC, Kodi 20.3 Nexus, kernel aarch64
  / userspace armhf — that's why the static Rust sidecar runs but the
  PyInstaller yt-dlp binary couldn't)
- Dropped addon dir into /storage/.kodi/addons/
- systemctl restart kodi → Kodi rescans /storage/.kodi/addons/
- JSON-RPC Addons.SetAddonEnabled flipped enabled:false → true
- Player.Open with plugin URL → 7s yt-dlp resolve → VideoFullScreen.xml,
  fullscreen:true, currentwindow 12005, audio+video synced

Fixes that surfaced during the install:
- yt-dlp swap: PyInstaller aarch64 binary needs ld-linux-aarch64.so.1
  which LibreELEC doesn't ship. Switched to the universal Python zipapp
  (~3MB) which runs on /usr/bin/python3.11. build-addon-zip.sh updated.
- main.py now puts the addon's bin/ dir on PATH so the sidecar's
  Command::new('yt-dlp') call resolves to the bundled zipapp.
- Cosmetic fix: resolve.rs's classify_yt_dlp_error preserves the
  original error message (was downcasing it for keyword matching and
  then using the lowercased copy as the user-facing error).

Caveats logged for later:
- 360p ceiling (yt-dlp '-f best[ext=mp4]' picks itag 18; 720p
  progressive itag 22 is deprecated by YouTube; higher quality wants
  DASH manifest generation).
- ALSA sink: device 'sysdefault:CARD=vc4hdmi1' fails to open on this
  Pi but Kodi auto-falls-back to 'sysdefault' so audio works. Worth
  cleaning up in Kodi audio settings later.

MILESTONES + docs/install.md updated with the SSH + JSON-RPC alternate
install path.
2026-05-23 10:18:26 -07:00

3.5 KiB

Installing torttube on the LibreELEC RPi

The addon ships as a single plugin.video.torttube-<version>.zip that contains the Python addon, a static aarch64 sidecar binary, and yt-dlp's aarch64 release binary (for Tier 2/3 fallback). Nothing else needs to be installed on the Pi.

Build the zip (Sulkta-internal)

bash scripts/build-addon-zip.sh
# → /mnt/user/downloads/torttube/plugin.video.torttube-0.0.1.zip on Lucy

The script cross-compiles the sidecar in a throwaway messense/rust-musl-cross:aarch64-musl container, fetches yt-dlp's official yt-dlp_linux_aarch64 release binary, packages everything, drops the result at /mnt/user/downloads/torttube/ (Lucy SMB).

Install on the Pi (Kodi UI flow)

  1. On the Pi: Settings → File manager → Add source → enter smb://lucy/downloads/ → name it lucy-downloads.
  2. Settings → Add-ons → Install from zip file → lucy-downloadstorttube/plugin.video.torttube-<version>.zip.
  3. Kodi installs, the addon appears under Video add-ons.

Unsigned addons need Settings → System → Add-ons → Unknown sources ON.

Install via SSH + JSON-RPC (no UI needed)

If SSH is enabled (Settings → Services → SSH):

# from any LAN host with ssh access to the Pi
scp plugin.video.torttube-0.0.1.zip kodi-host:/tmp/
ssh kodi-host 'cd /storage/.kodi/addons && unzip -o /tmp/plugin.video.torttube-0.0.1.zip && chmod +x plugin.video.torttube/bin/*'
ssh kodi-host 'systemctl restart kodi'

# wait ~5s for Kodi to come back, then enable the addon
curl -u kodi:<pw> -H "Content-Type: application/json" -X POST http://<kodi-host>:8080/jsonrpc \
  -d '{"jsonrpc":"2.0","id":1,"method":"Addons.SetAddonEnabled","params":{"addonid":"plugin.video.torttube","enabled":true}}'

Freshly-installed addons land in Kodi's database as enabled:false — the SetAddonEnabled call above flips that. Without it, Player.Open with the plugin URL fails silently with "Unable to find plugin" in kodi.log.

Verify

After install, fire the smoke from any LAN client:

curl -u kodi:pineapple -H "Content-Type: application/json" \
  -X POST http://192.168.0.158:8080/jsonrpc -d '{
    "jsonrpc": "2.0", "id": 1, "method": "Player.Open",
    "params": {"item": {"file":
      "plugin://plugin.video.torttube/?action=play&id=dQw4w9WgXcQ"}}}'

The TV should switch to playback of "Never Gonna Give You Up" within a few seconds (rustypipe resolve takes ~1s, then Kodi starts the stream).

Troubleshooting

  • Black screen + "no stream URL" notification: rustypipe returned separate audio + video streams (DASH-style), and we're picking the video stream which may be video-only. This is the M3 known gap — needs the audio+video merge work in M3+. Workaround: try a video that yt-dlp's tier-2 path can resolve to a combined format; the sidecar falls back automatically.
  • Sidecar crashes: cat /storage/.kodi/temp/kodi.log | grep torttube on the Pi. Sidecar logs to stderr; Kodi captures those.
  • yt-dlp permission denied: addon's bin/ dir needs +x. The zip preserves perms but if you copied files manually, chmod +x bin/*.
  • HTTPS errors from sidecar: it bundles rustls + webpki roots, so no system CA store needed. If you see "invalid certificate", your Pi clock is wrong (LibreELEC's NTP failed).

Updating

Just rebuild + bump the version in addon/plugin.video.torttube/addon.xml, re-run build-addon-zip.sh, install the new zip from the same SMB location. Kodi will treat it as an upgrade if the version is higher.