export const MAX_SYNC_OFFSET_MS = 2000 export const SYNC_OFFSET_STEP_MS = 50 const toFiniteNumber = (value) => { const numericValue = Number(value ?? 0) return Number.isFinite(numericValue) ? numericValue : 0 } export const clampSyncOffsetMs = (value, maxOffsetMs = MAX_SYNC_OFFSET_MS) => { const safeMax = Math.max(0, toFiniteNumber(maxOffsetMs)) const safeValue = toFiniteNumber(value) return Math.min(safeMax, Math.max(-safeMax, safeValue)) } export const snapSyncOffsetMs = ( value, stepMs = SYNC_OFFSET_STEP_MS, maxOffsetMs = MAX_SYNC_OFFSET_MS ) => { const safeStep = Math.max(1, Math.round(toFiniteNumber(stepMs) || 1)) const clampedValue = clampSyncOffsetMs(value, maxOffsetMs) return clampSyncOffsetMs(Math.round(clampedValue / safeStep) * safeStep, maxOffsetMs) } export const getSyncTrimMs = (syncOffsetMs = 0) => { const safeOffsetMs = clampSyncOffsetMs(syncOffsetMs) return { audioTrimMs: safeOffsetMs < 0 ? Math.abs(safeOffsetMs) : 0, videoTrimMs: safeOffsetMs > 0 ? safeOffsetMs : 0, } } export const getTimelinePositionMs = (audioPositionMs = 0, syncOffsetMs = 0) => { const { audioTrimMs } = getSyncTrimMs(syncOffsetMs) return Math.max(0, toFiniteNumber(audioPositionMs) - audioTrimMs) } export const getTimelineDurationMs = (audioDurationMs = 0, syncOffsetMs = 0) => { const { audioTrimMs } = getSyncTrimMs(syncOffsetMs) return Math.max(0, toFiniteNumber(audioDurationMs) - audioTrimMs) } export const getAudioPositionMs = (timelinePositionMs = 0, syncOffsetMs = 0) => { const { audioTrimMs } = getSyncTrimMs(syncOffsetMs) return Math.max(0, toFiniteNumber(timelinePositionMs) + audioTrimMs) } export const getVideoPositionMs = (timelinePositionMs = 0, syncOffsetMs = 0) => { const { videoTrimMs } = getSyncTrimMs(syncOffsetMs) return Math.max(0, toFiniteNumber(timelinePositionMs) + videoTrimMs) } export const formatSyncOffsetMs = (value) => { const safeValue = snapSyncOffsetMs(value) if (safeValue === 0) return '0 ms' return `${safeValue > 0 ? '+' : ''}${safeValue} ms` } export const toSyncOffsetSeconds = (value) => clampSyncOffsetMs(value) / 1000