Skip to content

Commit bf20e22

Browse files
committed
fix: AVCanvas.preFrame may cause flickering
1 parent 216a67c commit bf20e22

File tree

2 files changed

+31
-16
lines changed

2 files changed

+31
-16
lines changed

.changeset/khaki-lines-repeat.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@webav/av-canvas': patch
3+
---
4+
5+
fix: AVCanvas.preFrame may cause flickering

packages/av-canvas/src/av-canvas.ts

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ export class AVCanvas {
8383
on = this.#evtTool.on;
8484

8585
#opts;
86+
/**
87+
* 预览帧生成中
88+
*/
89+
#waitingPreviewFrame = false;
8690

8791
/**
8892
* 创建 `AVCanvas` 类的实例。
@@ -145,6 +149,9 @@ export class AVCanvas {
145149
if ((performance.now() - start) / (expectFrameTime * runCnt) < 1) {
146150
return;
147151
}
152+
// 如果正在准备下一次预览画面,则暂时跳过渲染;避免多个素材之间来回 seek 导致闪烁
153+
if (this.#waitingPreviewFrame) return;
154+
148155
runCnt += 1;
149156
this.#cvsCtx.fillStyle = opts.bgColor;
150157
this.#cvsCtx.fillRect(0, 0, this.#cvsEl.width, this.#cvsEl.height);
@@ -167,12 +174,10 @@ export class AVCanvas {
167174
}
168175

169176
#pause() {
170-
const emitPaused = this.#playState.step !== 0;
177+
if (this.#playState.step === 0) return;
171178
this.#playState.step = 0;
172-
if (emitPaused) {
173-
this.#evtTool.emit('paused');
174-
this.#audioCtx.suspend();
175-
}
179+
this.#evtTool.emit('paused');
180+
this.#audioCtx.suspend();
176181
for (const asn of this.#playingAudioCache) {
177182
asn.stop();
178183
asn.disconnect();
@@ -307,18 +312,23 @@ export class AVCanvas {
307312
*/
308313
async previewFrame(time: number) {
309314
this.#pause();
310-
await Promise.all(
311-
this.#spriteManager.getSprites({ time: false }).map((vs) => {
312-
if (
313-
time >= vs.time.offset &&
314-
time <= vs.time.offset + vs.time.duration
315-
) {
316-
return vs.preFrame(time - vs.time.offset);
317-
}
318-
return null;
319-
}),
320-
);
321315
this.#updateRenderTime(time);
316+
this.#waitingPreviewFrame = true;
317+
try {
318+
await Promise.all(
319+
this.#spriteManager.getSprites({ time: false }).map((vs) => {
320+
if (
321+
time >= vs.time.offset &&
322+
time <= vs.time.offset + vs.time.duration
323+
) {
324+
return vs.preFrame(time - vs.time.offset);
325+
}
326+
return null;
327+
}),
328+
);
329+
} finally {
330+
this.#waitingPreviewFrame = false;
331+
}
322332
}
323333

324334
/**

0 commit comments

Comments
 (0)