Skip to content

feat(play): queue YouTube radio links and start playback faster - #12

Merged
Nxssie merged 3 commits into
mainfrom
feat/youtube-radio-fast-start
Oct 18, 2026
Merged

Nxssie merged 3 commits into
mainfrom
feat/youtube-radio-fast-start

Conversation

@Nxssie

@Nxssie Nxssie commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • A YouTube radio ("Mix") link (watch?v=…&list=RD…) now queues the radio's first 25 songs as a playlist. Before, the v= parameter made it play only the seed video.
  • /play no longer runs two full yt-dlp extractions back to back. Resolution extracts once (yt-dlp -J), caches the info JSON in memory, and the stream starts from it through --load-info-json -. Measured first audio byte: 0.67 s cached vs 4.99 s fresh.

Changes

File Change
packages/server/src/lib/youtube.ts isRadioUrl and RADIO_TRACK_LIMIT = 25
packages/server/src/lib/infoCache.ts Bounded TTL cache of yt-dlp info JSON (10 min, 20 entries), consumed once per stream
packages/server/src/index.ts Rwith --playlist-end 25;
getVideoInfo extracts with -J and caches; createAudioStream streams from the cache and falls back to a fresh extraction
README.md Lists radio links among the supported inputs
`odd/tasks/youtube-radio-fast-star specs, measurements and evidence

Design notes

  • Why 25 songs: a radio is endless. Unlimited, yt-dlp returned 360 songs in 15.4 s; capped at 25
    it resolves in ~1.3–1.8 s. - Why the cache is safe: the 10-minute TTL is far below the ~6 h lifetime of YouTube's signed
    media URLs, so a cached entry never streams from an expired URL. A missing, expired or already-usedentry falls back to today's extraction.
  • Memory bound: info JSON measured 86–660 KB per video, so 20 entries cap the cache at ~13 MB.
  • watch?v=X&list=PL… still plays tst=RD…is rejected by YouTube ("Thisplaylist type is unviewable"), so only thewatch` form counts as a radio.

Test plan

                                                                                             - [x] `bun test`: 84 pass, 0 fail (new `isRadioUrl` and `infoCache` cases)
  • bun build src/index.ts --target bun: exit 0 - [x] Live yt-dlp: radio with --playlist-end 25 → 25 entries in 1.8 s; first audio byte 0.67 s
    cached vs 4.99 s fresh
  • Live Discord smoke test (no ino): /play with a single YouTubelink, /play with a radio link

Known limitations

  • The first song of a YouTube playliile starting: those entries arrivewith a title, so they skip the cached resolution. Prefetching the next song during playback would cover them and the gap between songs.
  • A generic HLS/DASH stream with no audio-only format now shows its URL as the title; such streams already failed to play with the same format selector.

Supersedes #10, which was merged intinstead of main after #9 landed, so these commits never reached main.

@Nxssie
Nxssie merged commit 5a6a595 into main Oct 18, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant