mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-10-03 13:53:53 +02:00
Make conversion cancelable
This commit is contained in:
+8
-1
@@ -18,6 +18,12 @@
|
|||||||
const target = new Metamuxer.BufferTarget();
|
const target = new Metamuxer.BufferTarget();
|
||||||
const outputFormat = new Metamuxer.Mp4OutputFormat()
|
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()
|
console.time()
|
||||||
const res = await Metamuxer.convert({
|
const res = await Metamuxer.convert({
|
||||||
input: new Metamuxer.Input({
|
input: new Metamuxer.Input({
|
||||||
@@ -61,7 +67,8 @@
|
|||||||
},
|
},
|
||||||
onProgress: (event) => {
|
onProgress: (event) => {
|
||||||
progress.value = event.completion;
|
progress.value = event.completion;
|
||||||
}
|
},
|
||||||
|
abortSignal: abortController.signal
|
||||||
});
|
});
|
||||||
console.timeEnd()
|
console.timeEnd()
|
||||||
console.log(res)
|
console.log(res)
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ export type ConversionOptions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onProgress?: (event: { completion: number }) => unknown;
|
onProgress?: (event: { completion: number }) => unknown;
|
||||||
|
abortSignal?: AbortSignal;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
@@ -227,6 +228,9 @@ class Conversion {
|
|||||||
if (options.onProgress !== undefined && typeof options.onProgress !== 'function') {
|
if (options.onProgress !== undefined && typeof options.onProgress !== 'function') {
|
||||||
throw new TypeError('options.onProgress, when provided, must be a 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.input = options.input;
|
||||||
this.output = options.output;
|
this.output = options.output;
|
||||||
@@ -242,6 +246,12 @@ class Conversion {
|
|||||||
utilizedTracks: [],
|
utilizedTracks: [],
|
||||||
discardedTracks: [],
|
discardedTracks: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
options.abortSignal?.addEventListener('abort', () => {
|
||||||
|
if (!this.output.isFinalizing) {
|
||||||
|
void this.output.cancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute() {
|
async execute() {
|
||||||
@@ -370,6 +380,10 @@ class Conversion {
|
|||||||
await this.synchronizer.wait(sample.timestamp);
|
await this.synchronizer.wait(sample.timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.options.abortSignal?.aborted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await source.digest(sample, meta);
|
await source.digest(sample, meta);
|
||||||
this.reportProgress(track.id, sample.timestamp + sample.duration);
|
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);
|
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);
|
await source.digest(Math.max(timestamp - this.startTimestamp, 0), duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,6 +494,10 @@ class Conversion {
|
|||||||
timestamp: Math.max(timestamp - this.startTimestamp, 0),
|
timestamp: Math.max(timestamp - this.startTimestamp, 0),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (this.options.abortSignal?.aborted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await source.digest(clone);
|
await source.digest(clone);
|
||||||
clone.close();
|
clone.close();
|
||||||
}
|
}
|
||||||
@@ -548,6 +570,10 @@ class Conversion {
|
|||||||
await this.synchronizer.wait(sample.timestamp);
|
await this.synchronizer.wait(sample.timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.options.abortSignal?.aborted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await source.digest(sample, meta);
|
await source.digest(sample, meta);
|
||||||
this.reportProgress(track.id, sample.timestamp + sample.duration);
|
this.reportProgress(track.id, sample.timestamp + sample.duration);
|
||||||
}
|
}
|
||||||
@@ -633,6 +659,10 @@ class Conversion {
|
|||||||
await this.synchronizer.wait(timestamp);
|
await this.synchronizer.wait(timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.options.abortSignal?.aborted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await source.digest(data);
|
await source.digest(data);
|
||||||
data.close();
|
data.close();
|
||||||
}
|
}
|
||||||
@@ -716,6 +746,11 @@ class Conversion {
|
|||||||
if (endTimestamp >= currentContextEndTime) {
|
if (endTimestamp >= currentContextEndTime) {
|
||||||
// Render the audio
|
// Render the audio
|
||||||
const renderedBuffer = await currentContext.startRendering();
|
const renderedBuffer = await currentContext.startRendering();
|
||||||
|
|
||||||
|
if (this.options.abortSignal?.aborted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await source.digest(renderedBuffer);
|
await source.digest(renderedBuffer);
|
||||||
|
|
||||||
currentContextStartFrame += currentContext.length;
|
currentContextStartFrame += currentContext.length;
|
||||||
@@ -739,6 +774,11 @@ class Conversion {
|
|||||||
|
|
||||||
if (currentContext) {
|
if (currentContext) {
|
||||||
const renderedBuffer = await currentContext.startRendering();
|
const renderedBuffer = await currentContext.startRendering();
|
||||||
|
|
||||||
|
if (this.options.abortSignal?.aborted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await source.digest(renderedBuffer);
|
await source.digest(renderedBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,8 +86,26 @@ export class Output<
|
|||||||
/** @internal */
|
/** @internal */
|
||||||
_finalizing = false;
|
_finalizing = false;
|
||||||
/** @internal */
|
/** @internal */
|
||||||
|
_finalized = false;
|
||||||
|
/** @internal */
|
||||||
_mutex = new AsyncMutex();
|
_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>) {
|
constructor(options: OutputOptions<F, T>) {
|
||||||
if (!options || typeof options !== 'object') {
|
if (!options || typeof options !== 'object') {
|
||||||
throw new TypeError('options must be an object.');
|
throw new TypeError('options must be an object.');
|
||||||
@@ -334,6 +352,8 @@ export class Output<
|
|||||||
await this._writer.flush();
|
await this._writer.flush();
|
||||||
await this._writer.finalize();
|
await this._writer.finalize();
|
||||||
|
|
||||||
|
this._finalized = true;
|
||||||
|
|
||||||
release();
|
release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user