fix(filmstrip): seeked event never fires at t=0; add per-frame seek timeout
Two bugs: 1. Frame 0 sets currentTime=0 but probe starts at t=0 after onloadedmetadata, so 'seeked' never fires (no position change). Promise hangs until the 15s global timeout kills the whole build. Fix: when currentTime is already at target (within 0.05s), call done() immediately without waiting for seeked. 2. Seeks into unbuffered regions of large MP4s can stall indefinitely. Fix: 3s per-frame timeout captures the current decoded frame and moves on, so a slow/stalled seek doesn't block the remaining 27 frames.
This commit is contained in:
parent
e9eeb84c5f
commit
89645f160e
1 changed files with 22 additions and 5 deletions
|
|
@ -135,6 +135,7 @@ function AssetDetail({ asset, onClose }) {
|
|||
const nextFrames = [];
|
||||
for (let i = 0; i < frameCount; i++) {
|
||||
const at = frameCount === 1 ? 0 : (probe.duration * i) / (frameCount - 1);
|
||||
const target = Math.min(Math.max(at, 0), Math.max(0, probe.duration - 0.05));
|
||||
await new Promise(function(resolve) {
|
||||
const done = function() {
|
||||
try {
|
||||
|
|
@ -145,12 +146,28 @@ function AssetDetail({ asset, onClose }) {
|
|||
}
|
||||
resolve();
|
||||
};
|
||||
const onSeeked = function() {
|
||||
probe.removeEventListener('seeked', onSeeked);
|
||||
// If already at the target position (frame 0 at t=0), 'seeked' will
|
||||
// never fire because the browser sees no position change — call done()
|
||||
// directly. Otherwise wait for the seeked event with a per-frame
|
||||
// timeout so a stalled seek (unbuffered range) doesn't hang the strip.
|
||||
if (Math.abs(probe.currentTime - target) < 0.05) {
|
||||
done();
|
||||
};
|
||||
probe.addEventListener('seeked', onSeeked);
|
||||
probe.currentTime = Math.min(Math.max(at, 0), Math.max(0, probe.duration - 0.05));
|
||||
} else {
|
||||
let frameTimer;
|
||||
const onSeeked = function() {
|
||||
clearTimeout(frameTimer);
|
||||
probe.removeEventListener('seeked', onSeeked);
|
||||
done();
|
||||
};
|
||||
probe.addEventListener('seeked', onSeeked);
|
||||
probe.currentTime = target;
|
||||
// 3s per-frame deadline — if seek stalls (e.g. unbuffered remote range),
|
||||
// capture whatever frame is currently decoded and move on.
|
||||
frameTimer = setTimeout(function() {
|
||||
probe.removeEventListener('seeked', onSeeked);
|
||||
done();
|
||||
}, 3000);
|
||||
}
|
||||
});
|
||||
if (cancelled) return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue