diff --git a/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts b/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts index 699661b86..812858d0c 100644 --- a/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts +++ b/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts @@ -576,6 +576,7 @@ export function useCanvasPlayer( // 送入解码器 let decodedCount = 0 let skippedCount = 0 + let decodeErrors = 0 for (const sample of samplesCollected) { if (!sample.data || isDestroyedRef.current) { skippedCount++ @@ -591,27 +592,30 @@ export function useCanvasPlayer( }) try { - decoder.decode(chunk) + await decoder.decode(chunk) // 修复:await 捕获异步错误 decodedCount++ } catch (e) { - console.warn("[useCanvasPlayer] Decode chunk error:", e) + decodeErrors++ + console.warn(`[useCanvasPlayer] Decode chunk error (${decodeErrors}):`, e) + // 连续 3 次解码失败,放弃当前片段 + if (decodeErrors >= 3) { + console.error("[useCanvasPlayer] Too many decode errors, aborting segment") + break + } } } console.log( - `[useCanvasPlayer] Segment ${meta.assetId}: decoded ${decodedCount}, skipped ${skippedCount}, decoder.state=${decoder.state}`, + `[useCanvasPlayer] Segment ${meta.assetId}: decoded ${decodedCount}, skipped ${skippedCount}, errors ${decodeErrors}, decoder.state=${decoder.state}`, ) - // flush 超时保护:10秒 - try { - await Promise.race([ - decoder.flush(), - new Promise((_, reject) => - setTimeout(() => reject(new Error("flush timeout 10s")), 10_000), - ), - ]) - console.log(`[useCanvasPlayer] Segment ${meta.assetId}: flush complete`) - } catch (e) { - console.warn("[useCanvasPlayer] Decoder flush error:", e) + // flush 仅在解码器状态正常时执行 + if (decoder.state === "configured") { + try { + await decoder.flush() + console.log(`[useCanvasPlayer] Segment ${meta.assetId}: flush complete`) + } catch (e) { + console.warn("[useCanvasPlayer] Decoder flush error:", e) + } } }, [],