fix: Canvas description缓存+关键帧容错+data字段修正 #1443

Closed
xiaoxia wants to merge 1 commits from fix/canvas-description-cache-and-keyframe into develop
@@ -204,6 +204,7 @@ export function useCanvasPlayer(
const videoDimRef = useRef<{ width: number; height: number }>({ width: 0, height: 0 })
const isDestroyedRef = useRef(false)
const lastProgressUpdateRef = useRef<number>(0)
const descriptionCache = useRef<Map<string, ArrayBuffer>>(new Map())
// 计算总时长
const totalDuration = segments.reduce((sum, seg) => sum + (seg.endTime - seg.startTime), 0)
@@ -277,7 +278,20 @@ export function useCanvasPlayer(
}
// 提取编解码器配置数据(HEVC 必需,H.264 也需要)
const description = extractCodecDescription(buffer)
let description = extractCodecDescription(buffer)
// 如果当前分片没有 description,尝试从缓存获取(后续分片可能不含 moov box)
if (!description) {
for (const cached of descriptionCache.current.values()) {
description = cached
break
}
}
// 如果找到了 description,缓存起来供后续分片使用
if (description) {
descriptionCache.current.set(segment.assetId, description)
}
meta = {
assetId: segment.assetId,
@@ -338,6 +352,14 @@ export function useCanvasPlayer(
},
})
console.log("[useCanvasPlayer] configure:", {
codec: meta.codec,
description: meta.description,
descriptionByteLength: meta.description?.byteLength,
videoWidth: meta.videoWidth,
videoHeight: meta.videoHeight,
})
try {
await decoder.configure({
codec: meta.codec,
@@ -388,16 +410,23 @@ export function useCanvasPlayer(
// 等待 samples 收集完成(mp4box start() 是同步的)
await new Promise((resolve) => setTimeout(resolve, 10))
// 送入解码器
// 送入解码器(跳过第一个关键帧之前的非关键帧)
let hasKeyFrame = false
for (const sample of samplesCollected) {
if (!sample.data || isDestroyedRef.current) continue
if (decoder.state === "closed") break
if (!hasKeyFrame && !sample.is_sync) {
console.warn("[useCanvasPlayer] Skipping non-keyframe chunk before first sync")
continue
}
if (sample.is_sync) hasKeyFrame = true
const chunk = new EncodedVideoChunk({
type: sample.is_sync ? "key" : "delta",
timestamp: (sample.cts / meta.timescale) * 1_000_000,
duration: (sample.duration / meta.timescale) * 1_000_000,
data: sample.data.buffer as ArrayBuffer,
data: sample.data,
})
try {
@@ -590,6 +619,7 @@ export function useCanvasPlayer(
frameQueueRef.current.clear()
segmentDataRef.current.clear()
segmentMetaRef.current = []
descriptionCache.current.clear()
}, [])
// ── 预加载下一个片段的数据 ──