From 2356f12f111cb59729f5d6e1a6b764e372d3c1d2 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 20 Aug 2026 13:31:57 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20VideoDecoder=20flus?= =?UTF-8?q?h=20timeout=20=E8=A7=A3=E7=A0=81=E5=99=A8=E8=B6=85=E6=97=B6?= =?UTF-8?q?=E5=8D=A1=E6=AD=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - decoder.decode(chunk) 改为 await,捕获异步 rejection - 添加 decodeErrors 计数,连续 3 次解码失败跳过当前片段 - flush 之前检查 decoder.state,只在 configured 状态才执行 - 避免在 error/closed 状态调用 flush 导致卡死 --- .../pages/generate/hooks/useCanvasPlayer.ts | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) 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) + } } }, [],