From d1b68295cc2be73d242e721a196cc49cb75c6a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=AE=8F=E6=9D=B0?= Date: Wed, 19 Aug 2026 18:42:02 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=85=A8=E9=87=8F=E5=8F=AF=E9=80=89?= =?UTF-8?q?=E9=93=BE+=E7=A9=BA=E5=80=BC=E5=85=9C=E5=BA=95=EF=BC=8C?= =?UTF-8?q?=E6=9D=9C=E7=BB=9D=20TypeError?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - info?.videoTracks?.[0] 安全访问视频轨道 - videoTrack 属性加 fallback 默认值(id=1, timescale=90000, codec=avc1.42E01E) - segments?.[segIndex] 安全索引 - sample.cts/duration 可选链 - EncodedVideoChunk 构建加 sample.data 空值检查 - meta.timescale 除零保护 --- .../pages/generate/hooks/useCanvasPlayer.ts | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts b/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts index cdd8f0314..a859f61a9 100644 --- a/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts +++ b/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts @@ -260,8 +260,11 @@ export function useCanvasPlayer( // ── 解封装单个片段,提取轨道元数据 + 按时间范围过滤样本 ── const demuxSegment = useCallback( (buffer: ArrayBuffer, segIndex: number): SegmentMeta | null => { - const segment = segments[segIndex] - if (!segment) return null + const segment = segments?.[segIndex] + if (!segment) { + console.warn("[useCanvasPlayer] No segment at index", segIndex) + return null + } // 计算全局偏移 let globalStart = 0 @@ -273,9 +276,9 @@ export function useCanvasPlayer( let meta: SegmentMeta | null = null mp4File.onReady = (info: Movie) => { - const videoTrack = info.videoTracks[0] + const videoTrack = info?.videoTracks?.[0] if (!videoTrack) { - console.error("[useCanvasPlayer] No video track found for segment", segIndex) + console.warn("[useCanvasPlayer] No video track found for segment", segIndex) return } @@ -300,9 +303,9 @@ export function useCanvasPlayer( videoUrl: segment.videoUrl, globalStartTime: globalStart, globalEndTime: globalStart + (segment.endTime - segment.startTime), - trackId: videoTrack.id, - timescale: videoTrack.timescale, - codec: videoTrack.codec, + trackId: videoTrack.id ?? 1, + timescale: videoTrack.timescale ?? 90000, + codec: videoTrack.codec ?? "avc1.42E01E", videoWidth: videoTrack.track_width || 1280, videoHeight: videoTrack.track_height || 720, description, @@ -310,8 +313,8 @@ export function useCanvasPlayer( } // 提取所有 samples - mp4File.setExtractionOptions(videoTrack.id, null, { - nbSamples: videoTrack.nb_samples, + mp4File.setExtractionOptions(videoTrack.id ?? 1, null, { + nbSamples: videoTrack.nb_samples ?? 0, }) mp4File.start() } @@ -325,7 +328,7 @@ export function useCanvasPlayer( const endCts = segment.endTime * timescale // 过滤出时间范围内的样本 - let filtered = samples.filter((s) => s.cts >= startCts && s.cts < endCts) + let filtered = samples.filter((s) => (s?.cts ?? 0) >= startCts && (s?.cts ?? 0) < endCts) // 确保从关键帧开始(跳过第一个 sync 之前的非关键帧) let foundSync = false @@ -436,10 +439,11 @@ export function useCanvasPlayer( if (!sample.data || isDestroyedRef.current) continue if (decoder.state === "closed") break + if (!sample.data) continue 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, + timestamp: ((sample.cts ?? 0) / (meta.timescale || 90000)) * 1_000_000, + duration: ((sample.duration ?? 0) / (meta.timescale || 90000)) * 1_000_000, data: sample.data, }) -- 2.54.0