Merge pull request #15926 from abitofevrything/feat/accurate_hls_seeking

Refactor HLS transcode seeking
This commit is contained in:
Abitofevrything
2026-01-18 12:17:06 +01:00
committed by GitHub
parent b9abf590c5
commit 8d052a6cb1
31 changed files with 61 additions and 188 deletions

View File

@@ -2914,8 +2914,8 @@ namespace MediaBrowser.Controller.MediaEncoding
if (time > 0)
{
// For direct streaming/remuxing, we seek at the exact position of the keyframe
// However, ffmpeg will seek to previous keyframe when the exact time is the input
// For direct streaming/remuxing, HLS segments start at keyframes.
// However, ffmpeg will seek to previous keyframe when the exact frame time is the input
// Workaround this by adding 0.5s offset to the seeking time to get the exact keyframe on most videos.
// This will help subtitle syncing.
var isHlsRemuxing = state.IsVideoRequest && state.TranscodingType is TranscodingJobType.Hls && IsCopyCodec(state.OutputVideoCodec);
@@ -2932,17 +2932,16 @@ namespace MediaBrowser.Controller.MediaEncoding
if (state.IsVideoRequest)
{
var outputVideoCodec = GetVideoEncoder(state, options);
var segmentFormat = GetSegmentFileExtension(segmentContainer).TrimStart('.');
// Important: If this is ever re-enabled, make sure not to use it with wtv because it breaks seeking
// Disable -noaccurate_seek on mpegts container due to the timestamps issue on some clients,
// but it's still required for fMP4 container otherwise the audio can't be synced to the video.
if (!string.Equals(state.InputContainer, "wtv", StringComparison.OrdinalIgnoreCase)
&& !string.Equals(segmentFormat, "ts", StringComparison.OrdinalIgnoreCase)
&& state.TranscodingType != TranscodingJobType.Progressive
&& !state.EnableBreakOnNonKeyFrames(outputVideoCodec)
&& (state.BaseRequest.StartTimeTicks ?? 0) > 0)
// If we are remuxing, then the copied stream cannot be seeked accurately (it will seek to the nearest
// keyframe). If we are using fMP4, then force all other streams to use the same inaccurate seeking to
// avoid A/V sync issues which cause playback issues on some devices.
// When remuxing video, the segment start times correspond to key frames in the source stream, so this
// option shouldn't change the seeked point that much.
// Important: make sure not to use it with wtv because it breaks seeking
if (state.TranscodingType is TranscodingJobType.Hls
&& string.Equals(segmentContainer, "mp4", StringComparison.OrdinalIgnoreCase)
&& (IsCopyCodec(state.OutputVideoCodec) || IsCopyCodec(state.OutputAudioCodec))
&& !string.Equals(state.InputContainer, "wtv", StringComparison.OrdinalIgnoreCase))
{
seekParam += " -noaccurate_seek";
}
@@ -7084,7 +7083,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
#nullable disable
public void TryStreamCopy(EncodingJobInfo state)
public void TryStreamCopy(EncodingJobInfo state, EncodingOptions options)
{
if (state.VideoStream is not null && CanStreamCopyVideo(state, state.VideoStream))
{
@@ -7101,8 +7100,14 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
var preventHlsAudioCopy = state.TranscodingType is TranscodingJobType.Hls
&& state.VideoStream is not null
&& !IsCopyCodec(state.OutputVideoCodec)
&& options.HlsAudioSeekStrategy is HlsAudioSeekStrategy.TranscodeAudio;
if (state.AudioStream is not null
&& CanStreamCopyAudio(state, state.AudioStream, state.SupportedAudioCodecs))
&& CanStreamCopyAudio(state, state.AudioStream, state.SupportedAudioCodecs)
&& !preventHlsAudioCopy)
{
state.OutputAudioCodec = "copy";
}