fix: 第12轮 — 背压超时保护+帧输出等待+feedFrames阈值
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1m19s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m25s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
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 / Validate - Migration (alembic) (push) Successful in 1m55s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m11s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m24s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 2m29s
CI/CD Pipeline / Build Staging API Image (push) Successful in 3m49s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 30s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m5s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 39s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m32s
AI Code Review / AI Code Review (pull_request) Failing after 5m11s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m51s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 6m55s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 59s
CI/CD Pipeline / Validate - Code Quality (push) Successful in 8m47s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 1m0s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 59s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 9m59s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m12s
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled

- 背压等待加 idleTicks 计数,超3秒自动break防止死循环
- 解码完成后等待帧输出(最多500ms),确保队列有帧
- 加解码完成日志便于排查
- renderFrame 中 feedFrames 调用加 size<80 阈值保护
This commit is contained in:
xiaoxia
2026-08-22 00:57:38 +08:00
parent 2885ede533
commit ece1f25f71
@@ -560,17 +560,26 @@ export function useCanvasPlayer(
// 从 cursor 继续喂 sample(流水线批量提交,不 await 单个 decode
let decoded = 0
let si = cursor
let idleTicks = 0 // 背压等待计数器,防止死循环
while (si < samples.length && decoded < maxFrames) {
if (decodeGenerationRef.current !== gen || isDestroyedRef.current) break
if ((decoder.state as string) === "closed") break
// 队列快满时停止,等播放消费后再补充
if (frameQueueRef.current.size >= 180) break
// 解码器内部队列积压过多时暂停提交,做背压
// 解码器内部队列积压时短暂等待
if (decoder.decodeQueueSize > 20) {
idleTicks++
if (idleTicks > 300) {
// 等待超过3秒(300×10ms),解码器可能卡住,放弃这批
console.warn(
`[useCanvasPlayer] Segment ${segIdx} decode backpressure timeout after 3s, decoded ${decoded} frames`,
)
break
}
await new Promise((r) => setTimeout(r, 10))
continue
}
idleTicks = 0
const sample = samples[si]
si++
if (!sample.data) continue
@@ -583,7 +592,6 @@ export function useCanvasPlayer(
})
try {
// 不 await 单个 decode,让硬件解码器流水线并行处理
decoder.decode(chunk)
decoded++
} catch (e) {
@@ -594,8 +602,18 @@ export function useCanvasPlayer(
cursor = si
segmentSampleCursorRef.current.set(segIdx, cursor)
// 解码器一点时间输出帧
await new Promise((r) => setTimeout(r, 16))
// 等待解码器输出帧(最多500ms),但不永久阻塞
if (decoded > 0 && (decoder.state as string) === "configured") {
let waited = 0
while (frameQueueRef.current.size < Math.min(decoded, 10) && waited < 500) {
await new Promise((r) => setTimeout(r, 20))
waited += 20
if (isDestroyedRef.current) break
}
}
console.log(
`[useCanvasPlayer] Segment ${segIdx} decoded ${decoded} frames, queue size: ${frameQueueRef.current.size}`,
)
return decoded
},
[],
@@ -769,7 +787,9 @@ export function useCanvasPlayer(
return s
})
// 后台补充帧:队列不足时自动续解码
feedFrames(currentTime)
if (frameQueueRef.current.size < 80) {
void feedFrames(currentTime)
}
}
if (currentTime >= totalDuration) {