Skip to content

fix: live stream HTTP 400 and missing title/author metadata#215

Open
Wubbity wants to merge 1 commit into
lavalink-devs:mainfrom
Wubbity:fix/live-stream-and-metadata-extraction
Open

fix: live stream HTTP 400 and missing title/author metadata#215
Wubbity wants to merge 1 commit into
lavalink-devs:mainfrom
Wubbity:fix/live-stream-and-metadata-extraction

Conversation

@Wubbity

@Wubbity Wubbity commented May 24, 2026

Copy link
Copy Markdown

EDIT: Apologies to Devoxin, I accidentally deleted the repo I was working in which subsequently closed the PR. I've addressed your concerns and reopened it.

Summary

Two bugs that surface specifically with live streams and login-required content.


1. HTTP 400 when initializing live stream playback

File: YoutubeMpegStreamAudioTrack.java

updateGlobalSequence() fetches the current segment on stream start to read the sequence number. YoutubePersistentHttpStream appends a &range=0-N query parameter to any URL that does not already contain an rn= parameter.

Live broadcast URLs carry noclen=1 and live=1. YouTube's live segment servers reject HTTP range requests with HTTP 400, so updateGlobalSequence() always fails for live streams and sequence tracking is broken.

Fix: when trackInfo.isStream is true, append rn=0 to the URL before passing it to YoutubePersistentHttpStream. The stream class skips the range logic for any URL that already contains rn=, so the request goes through as a plain fetch and returns HTTP 200.

A per-segment log.debug that fires every few seconds for the lifetime of any live stream is also removed and replaced with a single log.info line when playback begins.


2. Missing title and author for TVHTML5 + OAuth responses

File: NonMusicClient.java

When a login-required video is loaded via the TV client with OAuth, the InnerTube player response returns a videoDetails object that contains videoId but omits title and author. The original code read videoDetails.title and videoDetails.author directly, so both fields come back null for this client/content combination.

Fix: two private static helper methods - extractTitle and extractAuthor - each try a cascade of known InnerTube response locations in order:

  • videoDetails.title as a plain string (existing behaviour)
  • videoDetails.title.simpleText (structured text node variant)
  • videoDetails.title.runs[0].text (rich text node variant)
  • microformat.playerMicroformatRenderer fields (TV client microformat)
  • microformat.microformatDataRenderer fields (web client microformat)

If either field is still null after all InnerTube paths, fetchOEmbed is called as a last resort. This endpoint is public, requires no authentication, and returns title and author_name for any publicly accessible video including login-required content and live streams. It is called at most once per load and only when needed. The method now accepts a HttpInterface so requests go through the pre-configured source manager interface rather than bypassing it with a raw client.

Test plan

  • Load a standard YouTube video - title and author extract via videoDetails as before, oEmbed not called
  • Load a login-required video via the TV client with OAuth - title and author populate from microformat or oEmbed fallback
  • Start a YouTube live stream - no HTTP 400 on initialization, playback begins, single INFO log line appears
  • Verify log.debug("Segment URL: ...") no longer fires every segment during live stream playback

Two separate bugs fixed in this commit:

1. YoutubeMpegStreamAudioTrack - HTTP 400 on live stream initialization

   updateGlobalSequence() fetches the current segment to read the
   sequence number. YoutubePersistentHttpStream appends a range header
   (&range=0-N) to any URL that does not already contain an "rn="
   parameter. Live broadcast URLs (noclen=1, live=1) reject range
   requests with HTTP 400.

   Fix: when trackInfo.isStream is true, append rn=0 to the URL before
   passing it to YoutubePersistentHttpStream. The stream class treats
   any URL that already has rn= as a segmented request and skips the
   range logic entirely, so the fetch completes without a 400.

   Also removes the per-segment debug log that fires every few seconds
   for the duration of a live stream, replacing it with a single INFO
   line when playback begins.

2. NonMusicClient - missing title/author for TVHTML5 + OAuth responses

   When loading login-required content via the TV client with OAuth,
   the InnerTube player response omits videoDetails.title and
   videoDetails.author. The original code read these fields directly
   and fell back only to logging "Unknown artist" when author was null.

   Fix cascade (in order):
   - videoDetails.title as plain text (existing behaviour)
   - videoDetails.title.simpleText (structured text node)
   - videoDetails.title.runs[0].text (rich text node)
   - microformat.playerMicroformatRenderer.title.simpleText (TV client)
   - microformat.microformatDataRenderer.title (web clients)
   - microformat.playerMicroformatRenderer.ownerChannelName (TV author)
   - microformat.microformatDataRenderer.pageOwnerDetails.name (web author)
   - YouTube oEmbed endpoint as final fallback - returns title and
     author_name for any public video without authentication. Only
     called when at least one of the two fields is still null after
     all InnerTube paths have been exhausted.
@Wubbity

Wubbity commented May 24, 2026

Copy link
Copy Markdown
Author

Closing to revise before re-submitting.

@Wubbity Wubbity closed this May 24, 2026
@Wubbity Wubbity reopened this May 24, 2026
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