diff --git a/k-tv-backend/infra/src/jellyfin.rs b/k-tv-backend/infra/src/jellyfin.rs index 46b756a..a3ab53a 100644 --- a/k-tv-backend/infra/src/jellyfin.rs +++ b/k-tv-backend/infra/src/jellyfin.rs @@ -158,18 +158,20 @@ impl IMediaProvider for JellyfinMediaProvider { /// Build an HLS stream URL for a Jellyfin item. /// - /// Returns a `master.m3u8` playlist URL. Jellyfin transcodes to H.264/AAC - /// segments on the fly. HLS is preferred over a single MP4 stream because - /// `StartTimeTicks` works reliably with HLS — each segment is independent, - /// so Jellyfin can begin the playlist at the correct broadcast offset - /// without needing to byte-range seek into an in-progress transcode. + /// Returns a `master.m3u8` playlist URL. HLS is preferred over a single + /// MP4 stream because hls.js `startPosition` can seek to the broadcast + /// offset before the first segment fetch, without byte-range seeking into + /// an in-progress transcode. + /// + /// `allowVideoStreamCopy=true` and `allowAudioStreamCopy=true` tell + /// Jellyfin to remux (not re-encode) content that is already H.264/AAC, + /// avoiding transcode cache file buildup. Content in other codecs will + /// still be transcoded to H.264/AAC for browser compatibility. /// /// The API key is embedded so the player needs no separate auth header. - /// The caller (stream proxy route) appends `StartTimeTicks` when there is - /// a non-zero broadcast offset. async fn get_stream_url(&self, item_id: &MediaItemId) -> DomainResult { Ok(format!( - "{}/Videos/{}/master.m3u8?videoCodec=h264&audioCodec=aac&VideoBitRate=40000000&mediaSourceId={}&api_key={}", + "{}/Videos/{}/master.m3u8?videoCodec=h264&audioCodec=aac&allowVideoStreamCopy=true&allowAudioStreamCopy=true&mediaSourceId={}&api_key={}", self.config.base_url, item_id.as_ref(), item_id.as_ref(),