Fix video/audio desync on Firefox in web video player
Two issues were causing audio to drift out of sync with video on Firefox: 1. fastSeek() seeks video to the nearest keyframe but keeps audio at the precise timestamp, causing progressive drift. Disable fastSeek on Firefox and use currentTime for precise seeking instead. 2. Low-quality segment flushing only flushed video buffers, leaving stale audio data that could desync from newly-loaded video. Flush both audio and video buffers together when upgrading quality. https://claude.ai/code/session_01LGFSY2GgQJ3iw5Cp4XwiuL
This commit is contained in:
@@ -169,11 +169,19 @@ function useHLS({
|
||||
continue
|
||||
}
|
||||
|
||||
// Flush both video and audio buffers to keep them in sync.
|
||||
// Flushing only video leaves stale audio data that can desync,
|
||||
// particularly on Firefox.
|
||||
hls.trigger(Hls.Events.BUFFER_FLUSHING, {
|
||||
startOffset: lowQualFrag.start,
|
||||
endOffset: lowQualFrag.end,
|
||||
type: 'video',
|
||||
})
|
||||
hls.trigger(Hls.Events.BUFFER_FLUSHING, {
|
||||
startOffset: lowQualFrag.start,
|
||||
endOffset: lowQualFrag.end,
|
||||
type: 'audio',
|
||||
})
|
||||
|
||||
flushed.push(lowQualFrag)
|
||||
}
|
||||
@@ -269,6 +277,11 @@ function useHLS({
|
||||
endOffset: lowQualFrag.end,
|
||||
type: 'video',
|
||||
})
|
||||
hls.trigger(Hls.Events.BUFFER_FLUSHING, {
|
||||
startOffset: lowQualFrag.start,
|
||||
endOffset: lowQualFrag.end,
|
||||
type: 'audio',
|
||||
})
|
||||
setLowQualityFragments([])
|
||||
}
|
||||
})
|
||||
|
||||
@@ -27,7 +27,7 @@ import {Pause_Filled_Corner0_Rounded as PauseIcon} from '#/components/icons/Paus
|
||||
import {Play_Filled_Corner0_Rounded as PlayIcon} from '#/components/icons/Play'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {IS_WEB_MOBILE_IOS, IS_WEB_TOUCH_DEVICE} from '#/env'
|
||||
import {IS_WEB_FIREFOX, IS_WEB_MOBILE_IOS, IS_WEB_TOUCH_DEVICE} from '#/env'
|
||||
import {GifPresentationControls} from '../../GifPresentationControls'
|
||||
import {TimeIndicator} from '../TimeIndicator'
|
||||
import {ControlButton} from './ControlButton'
|
||||
@@ -196,7 +196,9 @@ export function Controls({
|
||||
const onSeek = useCallback(
|
||||
(time: number) => {
|
||||
if (!videoRef.current) return
|
||||
if (videoRef.current.fastSeek) {
|
||||
// Avoid fastSeek on Firefox - it seeks video to the nearest keyframe
|
||||
// but keeps audio at the precise time, causing audio/video desync
|
||||
if (videoRef.current.fastSeek && !IS_WEB_FIREFOX) {
|
||||
videoRef.current.fastSeek(time)
|
||||
} else {
|
||||
videoRef.current.currentTime = time
|
||||
|
||||
Reference in New Issue
Block a user