diff --git a/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts b/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts index e5acdd92d..a684ac0dc 100644 --- a/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts +++ b/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts @@ -277,11 +277,25 @@ export function useCanvasPlayer( return new Promise((resolve) => { let meta: SegmentMeta | null = null + let resolved = false + + // ✅ 超时保护:5秒后如果 onSamples 没有触发,返回 null + const timeout = setTimeout(() => { + if (!resolved) { + console.error( + `[useCanvasPlayer] Timeout: onSamples not triggered for segment ${segIndex}`, + ) + resolved = true + resolve(null) + } + }, 5000) mp4File.onReady = (info: Movie) => { const videoTrack = info?.videoTracks?.[0] if (!videoTrack) { console.warn("[useCanvasPlayer] No video track found for segment", segIndex) + clearTimeout(timeout) + resolved = true resolve(null) return } @@ -324,7 +338,11 @@ export function useCanvasPlayer( } mp4File.onSamples = (_trackId: number, _user: unknown, samples: Sample[]) => { + if (resolved) return // ✅ 防止重复 resolve + if (!meta) { + clearTimeout(timeout) + resolved = true resolve(null) return } @@ -368,11 +386,15 @@ export function useCanvasPlayer( ) // ✅ 关键修复:等待 onSamples 完成后再返回 + clearTimeout(timeout) + resolved = true resolve(meta) } mp4File.onError = (_module: string, message: string) => { console.error(`[useCanvasPlayer] MP4Box error: ${message}`) + clearTimeout(timeout) + resolved = true resolve(null) }