Make conversion cancelable

This commit is contained in:
Vanilagy
2025-02-09 17:55:59 +01:00
parent 02ac371011
commit b3cd4de1f6
3 changed files with 68 additions and 1 deletions
+8 -1
View File
@@ -18,6 +18,12 @@
const target = new Metamuxer.BufferTarget();
const outputFormat = new Metamuxer.Mp4OutputFormat()
const abortController = new AbortController();
const button = document.createElement('button');
button.textContent = 'Cancel';
button.onclick = () => abortController.abort();
document.body.append(button);
console.time()
const res = await Metamuxer.convert({
input: new Metamuxer.Input({
@@ -61,7 +67,8 @@
},
onProgress: (event) => {
progress.value = event.completion;
}
},
abortSignal: abortController.signal
});
console.timeEnd()
console.log(res)
+40
View File
@@ -65,6 +65,7 @@ export type ConversionOptions = {
};
onProgress?: (event: { completion: number }) => unknown;
abortSignal?: AbortSignal;
};
/** @public */
@@ -227,6 +228,9 @@ class Conversion {
if (options.onProgress !== undefined && typeof options.onProgress !== 'function') {
throw new TypeError('options.onProgress, when provided, must be a function.');
}
if (options.abortSignal !== undefined && !(options.abortSignal instanceof AbortSignal)) {
throw new TypeError('options.abortSignal, when provided, must be an AbortSignal.');
}
this.input = options.input;
this.output = options.output;
@@ -242,6 +246,12 @@ class Conversion {
utilizedTracks: [],
discardedTracks: [],
};
options.abortSignal?.addEventListener('abort', () => {
if (!this.output.isFinalizing) {
void this.output.cancel();
}
});
}
async execute() {
@@ -370,6 +380,10 @@ class Conversion {
await this.synchronizer.wait(sample.timestamp);
}
if (this.options.abortSignal?.aborted) {
return;
}
await source.digest(sample, meta);
this.reportProgress(track.id, sample.timestamp + sample.duration);
}
@@ -452,6 +466,10 @@ class Conversion {
context.drawImage(canvas, 0, 0, canvas.width, canvas.height, dx, dy, newWidth, newHeight);
}
if (this.options.abortSignal?.aborted) {
return;
}
await source.digest(Math.max(timestamp - this.startTimestamp, 0), duration);
}
@@ -476,6 +494,10 @@ class Conversion {
timestamp: Math.max(timestamp - this.startTimestamp, 0),
});
if (this.options.abortSignal?.aborted) {
return;
}
await source.digest(clone);
clone.close();
}
@@ -548,6 +570,10 @@ class Conversion {
await this.synchronizer.wait(sample.timestamp);
}
if (this.options.abortSignal?.aborted) {
return;
}
await source.digest(sample, meta);
this.reportProgress(track.id, sample.timestamp + sample.duration);
}
@@ -633,6 +659,10 @@ class Conversion {
await this.synchronizer.wait(timestamp);
}
if (this.options.abortSignal?.aborted) {
return;
}
await source.digest(data);
data.close();
}
@@ -716,6 +746,11 @@ class Conversion {
if (endTimestamp >= currentContextEndTime) {
// Render the audio
const renderedBuffer = await currentContext.startRendering();
if (this.options.abortSignal?.aborted) {
return;
}
await source.digest(renderedBuffer);
currentContextStartFrame += currentContext.length;
@@ -739,6 +774,11 @@ class Conversion {
if (currentContext) {
const renderedBuffer = await currentContext.startRendering();
if (this.options.abortSignal?.aborted) {
return;
}
await source.digest(renderedBuffer);
}
+20
View File
@@ -86,8 +86,26 @@ export class Output<
/** @internal */
_finalizing = false;
/** @internal */
_finalized = false;
/** @internal */
_mutex = new AsyncMutex();
get isStarted() {
return this._started;
}
get isCanceled() {
return this._canceled;
}
get isFinalizing() {
return this._finalizing;
}
get isFinalized() {
return this._finalized;
}
constructor(options: OutputOptions<F, T>) {
if (!options || typeof options !== 'object') {
throw new TypeError('options must be an object.');
@@ -334,6 +352,8 @@ export class Output<
await this._writer.flush();
await this._writer.finalize();
this._finalized = true;
release();
}
}