From cb903e3bd6e3de4f48f1d76b604d145c2e848d4e Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 20 Aug 2026 14:11:13 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=A7=BB=E9=99=A4=20rotation=20?= =?UTF-8?q?=E5=85=83=E6=95=B0=E6=8D=AE=E6=A3=80=E6=B5=8B=EF=BC=8C=E4=BB=8E?= =?UTF-8?q?=20VideoFrame=20=E8=8E=B7=E5=8F=96=E5=AE=9E=E9=99=85=E5=B0=BA?= =?UTF-8?q?=E5=AF=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除 extractVideoRotation 函数 - 删除 demuxSegment 和 decodeSegment 中的旋转检测+宽高交换代码 - 删除 decoder.configure() 中的 codedWidth/codedHeight 参数 - 在 VideoDecoder output 回调中从第一帧获取实际帧尺寸 - 核心思路:不再依赖 mp4box.js 的 track_width/track_height 和 rotation 元数据, 改为从 VideoDecoder 实际输出的 VideoFrame 获取真实尺寸 --- .../pages/generate/hooks/useCanvasPlayer.ts | 69 ++----------------- 1 file changed, 5 insertions(+), 64 deletions(-) diff --git a/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts b/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts index 812858d0c..79d8a8267 100644 --- a/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts +++ b/apps/web/src/pages/generate/hooks/useCanvasPlayer.ts @@ -81,47 +81,6 @@ function findCodecConfigRecursive( return undefined } -/** - * 从 MP4 buffer 中解析视频轨道的旋转角度。 - * iOS HEVC 竖屏视频用 rotation=90° 元数据标记, - * mp4box.js 的 track_width/track_height 不反映旋转后的尺寸。 - */ -function extractVideoRotation(buffer: ArrayBuffer): number { - try { - const view = new DataView(buffer) - let offset = 0 - while (offset < buffer.byteLength - 8) { - const size = view.getUint32(offset) - const type = String.fromCharCode( - view.getUint8(offset + 4), - view.getUint8(offset + 5), - view.getUint8(offset + 6), - view.getUint8(offset + 7), - ) - if (size <= 0 || offset + size > buffer.byteLength) break - if (type === "tkhd") { - const version = view.getUint8(offset + 8) - const matrixOffset = offset + (version === 0 ? 28 : 40) - if (matrixOffset + 36 <= offset + size) { - const a = view.getInt32(matrixOffset) - const b = view.getInt32(matrixOffset + 4) - if (Math.abs(b) > 0x00008000) { - return b > 0 ? 90 : 270 - } - if (a < -0x00008000) { - return 180 - } - return 0 - } - } - offset += size - } - } catch { - // 解析失败不阻塞,返回 0 - } - return 0 -} - // ── 帧队列(环形缓冲区) ── interface FrameEntry { frame: VideoFrame @@ -411,18 +370,6 @@ export function useCanvasPlayer( samples: [], } - // ═══ 新增:检测旋转元数据,交换宽高 ═══ - const rotation = extractVideoRotation(buffer) - if (rotation === 90 || rotation === 270) { - const tmpW = meta.videoWidth - meta.videoWidth = meta.videoHeight - meta.videoHeight = tmpW - console.log( - `[useCanvasPlayer] Rotation ${rotation}° detected, swapped dimensions to ${meta.videoWidth}x${meta.videoHeight}`, - ) - } - // ═══ 新增结束 ═══ - // 提取所有 samples mp4File.setExtractionOptions(videoTrack.id ?? 1, null, { nbSamples: Infinity, // 提取所有 sample @@ -510,6 +457,11 @@ export function useCanvasPlayer( // 配置解码器(每个片段可能需要不同的 codec/分辨率) const decoder = new VideoDecoder({ output: (frame: VideoFrame) => { + // 从第一帧获取实际尺寸 + if (videoDimRef.current.width === 0 || videoDimRef.current.height === 0) { + videoDimRef.current = { width: frame.codedWidth, height: frame.codedHeight } + console.log(`[useCanvasPlayer] Actual frame size: ${frame.codedWidth}x${frame.codedHeight}`) + } const localTime = frame.timestamp / 1_000_000 const globalTime = localTime + meta.globalStartTime frameQueueRef.current.push({ @@ -532,19 +484,8 @@ export function useCanvasPlayer( }) try { - // ═══ 新增:旋转检测 ═══ - const rotation = extractVideoRotation(_buffer) - if (rotation === 90 || rotation === 270) { - const tmpW = meta.videoWidth - meta.videoWidth = meta.videoHeight - meta.videoHeight = tmpW - } - // ═══ 新增结束 ═══ - await decoder.configure({ codec: meta.codec, - codedWidth: meta.videoWidth, - codedHeight: meta.videoHeight, ...(meta.description ? { description: meta.description } : {}), }) decoderRef.current = decoder