fix: Canvas description缓存+关键帧容错+data字段修正
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 40s
AI Code Review / AI Code Review (pull_request) Failing after 1m58s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m58s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m14s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m17s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 20s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m55s
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m26s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 58s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m48s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 2m48s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 4m34s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 9m57s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 40s
AI Code Review / AI Code Review (pull_request) Failing after 1m58s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m58s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m14s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m17s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 20s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m55s
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m26s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 58s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m48s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 2m48s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 4m34s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 9m57s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
- 添加 descriptionCache ref,从第一个分片提取后缓存供后续分片使用 - configure 前添加调试日志确认 description 是否正确传递 - EncodedVideoChunk data 字段:sample.data.buffer → sample.data - 添加关键帧容错:跳过第一个 sync 之前的非关键帧 - destroy 时清理 descriptionCache
This commit is contained in:
@@ -204,6 +204,7 @@ export function useCanvasPlayer(
|
||||
const videoDimRef = useRef<{ width: number; height: number }>({ width: 0, height: 0 })
|
||||
const isDestroyedRef = useRef(false)
|
||||
const lastProgressUpdateRef = useRef<number>(0)
|
||||
const descriptionCache = useRef<Map<string, ArrayBuffer>>(new Map())
|
||||
|
||||
// 计算总时长
|
||||
const totalDuration = segments.reduce((sum, seg) => sum + (seg.endTime - seg.startTime), 0)
|
||||
@@ -277,7 +278,20 @@ export function useCanvasPlayer(
|
||||
}
|
||||
|
||||
// 提取编解码器配置数据(HEVC 必需,H.264 也需要)
|
||||
const description = extractCodecDescription(buffer)
|
||||
let description = extractCodecDescription(buffer)
|
||||
|
||||
// 如果当前分片没有 description,尝试从缓存获取(后续分片可能不含 moov box)
|
||||
if (!description) {
|
||||
for (const cached of descriptionCache.current.values()) {
|
||||
description = cached
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 如果找到了 description,缓存起来供后续分片使用
|
||||
if (description) {
|
||||
descriptionCache.current.set(segment.assetId, description)
|
||||
}
|
||||
|
||||
meta = {
|
||||
assetId: segment.assetId,
|
||||
@@ -338,6 +352,14 @@ export function useCanvasPlayer(
|
||||
},
|
||||
})
|
||||
|
||||
console.log("[useCanvasPlayer] configure:", {
|
||||
codec: meta.codec,
|
||||
description: meta.description,
|
||||
descriptionByteLength: meta.description?.byteLength,
|
||||
videoWidth: meta.videoWidth,
|
||||
videoHeight: meta.videoHeight,
|
||||
})
|
||||
|
||||
try {
|
||||
await decoder.configure({
|
||||
codec: meta.codec,
|
||||
@@ -388,16 +410,23 @@ export function useCanvasPlayer(
|
||||
// 等待 samples 收集完成(mp4box start() 是同步的)
|
||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||
|
||||
// 送入解码器
|
||||
// 送入解码器(跳过第一个关键帧之前的非关键帧)
|
||||
let hasKeyFrame = false
|
||||
for (const sample of samplesCollected) {
|
||||
if (!sample.data || isDestroyedRef.current) continue
|
||||
if (decoder.state === "closed") break
|
||||
|
||||
if (!hasKeyFrame && !sample.is_sync) {
|
||||
console.warn("[useCanvasPlayer] Skipping non-keyframe chunk before first sync")
|
||||
continue
|
||||
}
|
||||
if (sample.is_sync) hasKeyFrame = true
|
||||
|
||||
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,
|
||||
data: sample.data.buffer as ArrayBuffer,
|
||||
data: sample.data,
|
||||
})
|
||||
|
||||
try {
|
||||
@@ -590,6 +619,7 @@ export function useCanvasPlayer(
|
||||
frameQueueRef.current.clear()
|
||||
segmentDataRef.current.clear()
|
||||
segmentMetaRef.current = []
|
||||
descriptionCache.current.clear()
|
||||
}, [])
|
||||
|
||||
// ── 预加载下一个片段的数据 ──
|
||||
|
||||
Reference in New Issue
Block a user