fix: prevent concurrent frame fetching in VideoEngine

Added a flag to manage the fetching state of video frames in the VideoEngine class. This change ensures that the updateNextFrame method does not attempt to fetch new frames while a previous fetch is still in progress, preventing potential race conditions and improving stability during playback.
This commit is contained in:
Harvey Zhao committed 2026-01-01 17:32:21 +08:00
1 parent 9d760a2f59
commit d892685a25
4 files changed
+114 -101

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@
const art = new Artplayer({
container: '.artplayer-app',
url: 'https://artplayer.org/assets/sample/frag_bunny.mp4',
autoSize: false,
autoSize: true,
screenshot: true,
setting: true,
loop: true,
@@ -523,7 +523,66 @@ class VideoShim {
}
exports.default = VideoShim;
},{"./MediaBunnyEngine.js":"j1QXy","./EventTarget.js":"7Odz0","@parcel/transformer-js/src/esmodule-helpers.js":"8oCsH"}],"j1QXy":[function(require,module,exports,__globalThis) {
},{"./EventTarget.js":"7Odz0","./MediaBunnyEngine.js":"j1QXy","@parcel/transformer-js/src/esmodule-helpers.js":"8oCsH"}],"7Odz0":[function(require,module,exports,__globalThis) {
/**
* Event Target Implementation
* Simple event system for video events
*/ var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports);
class EventTarget {
constructor(){
this.listeners = new Map();
}
addEventListener(type, fn) {
if (!this.listeners.has(type)) this.listeners.set(type, []);
this.listeners.get(type).push(fn);
}
removeEventListener(type, fn) {
const list = this.listeners.get(type);
if (!list) return;
const index = list.indexOf(fn);
if (index >= 0) list.splice(index, 1);
}
emit(type, detail) {
const evt = new Event(type);
evt.detail = detail;
const list = this.listeners.get(type);
if (list) list.forEach((fn)=>fn(evt));
}
}
exports.default = EventTarget;
},{"@parcel/transformer-js/src/esmodule-helpers.js":"8oCsH"}],"8oCsH":[function(require,module,exports,__globalThis) {
exports.interopDefault = function(a) {
return a && a.__esModule ? a : {
default: a
};
};
exports.defineInteropFlag = function(a) {
Object.defineProperty(a, '__esModule', {
value: true
});
};
exports.exportAll = function(source, dest) {
Object.keys(source).forEach(function(key) {
if (key === 'default' || key === '__esModule' || Object.prototype.hasOwnProperty.call(dest, key)) return;
Object.defineProperty(dest, key, {
enumerable: true,
get: function() {
return source[key];
}
});
});
return dest;
};
exports.export = function(dest, destName, get) {
Object.defineProperty(dest, destName, {
enumerable: true,
get: get
});
};
},{}],"j1QXy":[function(require,module,exports,__globalThis) {
/**
* Main MediaBunny Engine
* Coordinates audio and video playback
@@ -2668,37 +2727,7 @@ const isNumber = (x)=>{
return typeof x === 'number' && !Number.isNaN(x);
};
},{"@parcel/transformer-js/src/esmodule-helpers.js":"8oCsH"}],"8oCsH":[function(require,module,exports,__globalThis) {
exports.interopDefault = function(a) {
return a && a.__esModule ? a : {
default: a
};
};
exports.defineInteropFlag = function(a) {
Object.defineProperty(a, '__esModule', {
value: true
});
};
exports.exportAll = function(source, dest) {
Object.keys(source).forEach(function(key) {
if (key === 'default' || key === '__esModule' || Object.prototype.hasOwnProperty.call(dest, key)) return;
Object.defineProperty(dest, key, {
enumerable: true,
get: function() {
return source[key];
}
});
});
return dest;
};
exports.export = function(dest, destName, get) {
Object.defineProperty(dest, destName, {
enumerable: true,
get: get
});
};
},{}],"99VTc":[function(require,module,exports,__globalThis) {
},{"@parcel/transformer-js/src/esmodule-helpers.js":"8oCsH"}],"99VTc":[function(require,module,exports,__globalThis) {
/*!
* Copyright (c) 2025-present, Vanilagy and contributors
*
@@ -16433,6 +16462,7 @@ class VideoEngine {
this.stalled = false;
this.playbackRate = 1;
this.posterDrawn = false;
this.isFetching = false;
}
normalizeSource(src) {
if (typeof src === 'string') return new (0, _mediabunny.UrlSource)(src);
@@ -16539,24 +16569,29 @@ class VideoEngine {
} else this.drawPoster();
}
async updateNextFrame(localId) {
if (!this.videoIterator) return;
while(true){
const frame = (await this.videoIterator.next()).value ?? null;
if (!frame || localId !== this.asyncId) return;
const t = this.audioClock.currentTime;
const tolerance = this.dropLateFrames ? Math.max(0.06, this.avSyncTolerance / Math.max(1, this.playbackRate)) : 0;
if (this.dropLateFrames && frame.timestamp < t - tolerance) continue;
if (frame.timestamp <= t + tolerance) {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.ctx.drawImage(frame.canvas, 0, 0);
if (!this.dropLateFrames && frame.timestamp > t) {
this.nextFrame = null;
if (!this.videoIterator || this.isFetching) return;
this.isFetching = true;
try {
while(true){
const frame = (await this.videoIterator.next()).value ?? null;
if (!frame || localId !== this.asyncId) return;
const t = this.audioClock.currentTime;
const tolerance = this.dropLateFrames ? Math.max(0.06, this.avSyncTolerance / Math.max(1, this.playbackRate)) : 0;
if (this.dropLateFrames && frame.timestamp < t - tolerance) continue;
if (frame.timestamp <= t + tolerance) {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.ctx.drawImage(frame.canvas, 0, 0);
if (!this.dropLateFrames && frame.timestamp > t) {
this.nextFrame = null;
return;
}
} else {
this.nextFrame = frame;
return;
}
} else {
this.nextFrame = frame;
return;
}
} finally{
this.isFetching = false;
}
}
render() {
@@ -16625,35 +16660,6 @@ class VideoEngine {
}
exports.default = VideoEngine;
},{"mediabunny":"6p2EH","@parcel/transformer-js/src/esmodule-helpers.js":"8oCsH"}],"7Odz0":[function(require,module,exports,__globalThis) {
/**
* Event Target Implementation
* Simple event system for video events
*/ var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports);
class EventTarget {
constructor(){
this.listeners = new Map();
}
addEventListener(type, fn) {
if (!this.listeners.has(type)) this.listeners.set(type, []);
this.listeners.get(type).push(fn);
}
removeEventListener(type, fn) {
const list = this.listeners.get(type);
if (!list) return;
const index = list.indexOf(fn);
if (index >= 0) list.splice(index, 1);
}
emit(type, detail) {
const evt = new Event(type);
evt.detail = detail;
const list = this.listeners.get(type);
if (list) list.forEach((fn)=>fn(evt));
}
}
exports.default = EventTarget;
},{"@parcel/transformer-js/src/esmodule-helpers.js":"8oCsH"}]},["gqawh"], "gqawh", "parcelRequire4dc0", {})
},{"mediabunny":"6p2EH","@parcel/transformer-js/src/esmodule-helpers.js":"8oCsH"}]},["gqawh"], "gqawh", "parcelRequire4dc0", {})
//# sourceMappingURL=index.js.map
@@ -1 +1 @@
{"mappings":"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 truncated
{"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;CAGC;;6CAGuB;AAFxB;;AAEe,SAAS,yBAAyB,SAAS,CAAC,CAAC;IAC1D,OAAO,CAAC;QACN,MAAM,EAAE,WAAW,EAAE,GAAG;QACxB,MAAM,EAAE,aAAa,EAAE,GAAG,YAAY,KAAK;QAE3C,wBAAwB;QACxB,MAAM,SAAS,cAAc;QAC7B,MAAM,MAAM,OAAO,UAAU,CAAC;QAE9B,oBAAoB;QACpB,MAAM,OAAO,IAAI,CAAA,GAAA,2BAAS,AAAD,EAAE;YACzB;YACA;YACA;YACA;QACF;QAEA,+BAA+B;QAC/B,MAAM,wBAAwB,CAAC;QAC/B,IAAK,MAAM,QAAQ,OACjB,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,YAC1B,qBAAqB,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;QAIpD,sDAAsD;QACtD,MAAM,gBAAgB,IAAI,IAAI;eACzB,OAAO,mBAAmB,CAAC;eAC3B,OAAO,mBAAmB,CAAC,OAAO,cAAc,CAAC;SACrD;QAED,gCAAgC;QAChC,KAAK,MAAM,QAAQ,cAAe;YAChC,IAAI,SAAS,eACX;YACF,IAAI,CAAE,CAAA,QAAQ,MAAK,GACjB,OAAO,cAAc,CAAC,QAAQ,MAAM;gBAClC;oBACE,MAAM,QAAQ,IAAI,CAAC,KAAK;oBACxB,OAAO,OAAO,UAAU,aAAa,MAAM,IAAI,CAAC,QAAQ;gBAC1D;gBACA,KAAI,CAAC;oBACH,IAAI,CAAC,KAAK,GAAG;gBACf;gBACA,cAAc;gBACd,YAAY;YACd;QAEJ;QAEA,kCAAkC;QAClC,IAAK,MAAM,QAAQ,sBACjB,MAAM,CAAC,KAAK,GAAG,CAAC,GAAG,OAAS,qBAAqB,CAAC,KAAK,IAAI;QAG7D,gBAAgB;QAChB,SAAS;YACP,MAAM,SAAS,IAAI,QAAQ,EAAE;YAC7B,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,QAAQ,EAChC;YAEF,OAAO,MAAM,CAAC,OAAO,KAAK,EAAE;gBAC1B,OAAO;gBACP,QAAQ;gBACR,WAAW;YACb;QACF;QAEA,IAAI,EAAE,CAAC,UAAU;QACjB,IAAI,EAAE,CAAC,wBAAwB;QAE/B,qBAAqB;QACrB,IAAI,EAAE,CAAC,WAAW;YAChB,KAAK,OAAO;QACd;QAEA,OAAO;IACT;AACF;AAEA,IAAI,OAAO,WAAW,aACpB,OAAO,wBAAwB,GAAG;;;;;ACvFpC;;AACA;;;CAGC,GACD;;AAEA,SAAS,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG;IACxB,OAAO,KAAK,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,KAAK,OAAO,MAAM;AAClD;AAEe,MAAM;IACnB,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAE;QACxC,IAAI,CAAC,GAAG,GAAG;QACX,IAAI,CAAC,MAAM,GAAG;QACd,IAAI,CAAC,MAAM,GAAG;QAEd,eAAe;QACf,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA,GAAA,6BAAW,AAAD;QAE5B,oBAAoB;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA,GAAA,kCAAgB,AAAD,EAAE;YAAE;YAAQ;YAAK,QAAQ,IAAI,CAAC,MAAM;YAAE;QAAO;QAE9E,iBAAiB;QACjB,IAAI,CAAC,IAAI,GAAG;QACZ,IAAI,CAAC,OAAO,GAAG,OAAO,MAAM,IAAI;QAChC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,OAAO,KAAK;QAC5B,IAAI,CAAC,aAAa,GAAG;QAErB,uBAAuB;QACvB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM;QAE/C,8BAA8B;QAC9B,IAAI,CAAC,oBAAoB;QAEzB,mBAAmB;QACnB,IAAI,OAAO,MAAM,EACf,IAAI,CAAC,GAAG,GAAG,OAAO,MAAM;aAErB,IAAI,IAAI,MAAM,EAAE,KACnB,IAAI,CAAC,GAAG,GAAG,IAAI,MAAM,CAAC,GAAG;IAE7B;IAEA,uBAAuB;QACrB,MAAM,EAAE,QAAQ,SAAS,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM;QACzD,UAAU,OAAO,CAAC,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC;gBAClC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE;YACnC;QACF;IACF;IAEA,gBAAgB;IAChB,iBAAiB,IAAI,EAAE,EAAE,EAAE;QACzB,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM;IACrC;IAEA,oBAAoB,IAAI,EAAE,EAAE,EAAE;QAC5B,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAM;IACxC;IAEA,SAAS;IACT,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,IAAI;IAClB;IAEA,IAAI,IAAI,CAAC,EAAE;QACT,IAAI,CAAC,IAAI,GAAG;QACZ,IAAI,GACF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IACrB;IAEA,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,IAAI;IAClB;IAEA,OAAO;IACP,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW;IAChC;IAEA,IAAI,YAAY,CAAC,EAAE;QACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,MAAM;IAChC;IAEA,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ;IAC7B;IAEA,2BAA2B;IAC3B,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ;IACtD;IAEA,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW;IACzD;IAEA,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ;IACtD;IAEA,iBAAiB,KAAK,EAAE,GAAG,EAAE;QAC3B,MAAM,WAAW,IAAI,CAAC,MAAM,CAAC,QAAQ;QACrC,IAAI,CAAC,YAAY,OAAO,KAAK,CAAC,aAAa,OAAO,GAChD,OAAO;YAAE,QAAQ;YAAG,OAAO,IAAM;YAAG,KAAK,IAAM;QAAE;QAEnD,OAAO;YACL,QAAQ;YACR,OAAO,IAAM;YACb,KAAK,IAAM;QACb;IACF;IAEA,iBAAiB;IACjB,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM;IAC3B;IAEA,IAAI,UAAU;QACZ,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK;IAClD;IAEA,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK;IAC1B;IAEA,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO;IAC5B;IAEA,cAAc;IACd,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU;IAC/B;IAEA,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY;IACjC;IAEA,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK;IAC1B;IAEA,gBAAgB;IAChB,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,aAAa;IAC3B;IAEA,IAAI,aAAa,CAAC,EAAE;QAClB,MAAM,OAAO,OAAO;QACpB,IAAI,OAAO,KAAK,CAAC,SAAS,QAAQ,GAChC;QAEF,IAAI,CAAC,aAAa,GAAG;QACrB,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IACnB;IAEA,SAAS;IACT,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,OAAO;IACrB;IAEA,IAAI,OAAO,CAAC,EAAE;QACZ,IAAI,CAAC,OAAO,GAAG,MAAM,GAAG,GAAG;QAC3B,IAAI,CAAC,MAAM,GAAG;QACd,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM;QAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IACnB;IAEA,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM;IACpB;IAEA,IAAI,MAAM,CAAC,EAAE;QACX,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM;QAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IACnB;IAEA,mBAAmB;IACnB,OAAO;QACL,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI;IACzB;IAEA,QAAQ;QACN,IAAI,CAAC,MALine truncated
@@ -52,6 +52,7 @@ export default class VideoEngine {
this.stalled = false
this.playbackRate = 1
this.posterDrawn = false
this.isFetching = false
}
normalizeSource(src) {
@@ -197,37 +198,43 @@ export default class VideoEngine {
}
async updateNextFrame(localId) {
if (!this.videoIterator)
if (!this.videoIterator || this.isFetching)
return
while (true) {
const frame = (await this.videoIterator.next()).value ?? null
if (!frame || localId !== this.asyncId)
return
this.isFetching = true
try {
while (true) {
const frame = (await this.videoIterator.next()).value ?? null
if (!frame || localId !== this.asyncId)
return
const t = this.audioClock.currentTime
const tolerance = this.dropLateFrames
? Math.max(0.06, this.avSyncTolerance / Math.max(1, this.playbackRate))
: 0
const t = this.audioClock.currentTime
const tolerance = this.dropLateFrames
? Math.max(0.06, this.avSyncTolerance / Math.max(1, this.playbackRate))
: 0
if (this.dropLateFrames && frame.timestamp < t - tolerance) {
// Skip late frame
continue
}
if (this.dropLateFrames && frame.timestamp < t - tolerance) {
// Skip late frame
continue
}
if (frame.timestamp <= t + tolerance) {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
this.ctx.drawImage(frame.canvas, 0, 0)
if (frame.timestamp <= t + tolerance) {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
this.ctx.drawImage(frame.canvas, 0, 0)
if (!this.dropLateFrames && frame.timestamp > t) {
this.nextFrame = null
if (!this.dropLateFrames && frame.timestamp > t) {
this.nextFrame = null
return
}
}
else {
this.nextFrame = frame
return
}
}
else {
this.nextFrame = frame
return
}
}
finally {
this.isFetching = false
}
}