From b560977b508eece8363364c8cacee65ff4246199 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Tue, 8 Sep 2026 16:19:56 +0200 Subject: [PATCH] Fix empty audio trim range crashing conversion (fixes #486) --- dev/convert.html | 4 +++- src/conversion.ts | 6 ++++++ src/sample.ts | 32 ++++++++++++++++---------------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/dev/convert.html b/dev/convert.html index 825693d..d153cf2 100644 --- a/dev/convert.html +++ b/dev/convert.html @@ -99,7 +99,7 @@ input, output, audio: { - discard: true, + forceTranscode: true, //discard: true, //codec: 'aac', //forceTranscode: true, @@ -162,6 +162,8 @@ } }, trim: { + start: 30, + end: 35, //start: -60, //end: 60, //start: -2, diff --git a/src/conversion.ts b/src/conversion.ts index 14b3663..2c010cd 100644 --- a/src/conversion.ts +++ b/src/conversion.ts @@ -2113,6 +2113,12 @@ export class Conversion { endFrame = Math.round((this._endTimestamp - sample.timestamp) * sample.sampleRate); } + if (startFrame >= endFrame) { + // Sample lies wholly out of trim region + sample.close(); + continue; // No break since we may be before the start + } + // Can't assign to "using" identifiers so we gotta do this let finalSampleLet: AudioSample; if (startFrame > 0 || endFrame < sample.numberOfFrames) { diff --git a/src/sample.ts b/src/sample.ts index ffb9fb1..c824e34 100644 --- a/src/sample.ts +++ b/src/sample.ts @@ -2866,32 +2866,32 @@ export class AudioSample implements Disposable { } /** - * Returns a new {@link AudioSample} containing only the frames in the range [startSample, endSample). Both bounds + * Returns a new {@link AudioSample} containing only the frames in the range [startFrame, endFrame). Both bounds * must lie within this sample's range of frames. The returned sample's timestamp is shifted to match the start of * the trimmed section. */ - trim(startSample: number, endSample = this.numberOfFrames) { - if (!Number.isInteger(startSample) || startSample < 0) { - throw new TypeError('startSample must be a non-negative integer.'); + trim(startFrame: number, endFrame = this.numberOfFrames) { + if (!Number.isInteger(startFrame) || startFrame < 0) { + throw new TypeError('startFrame must be a non-negative integer.'); } - if (!Number.isInteger(endSample) || endSample < 0) { - throw new TypeError('endSample must be a non-negative integer.'); + if (!Number.isInteger(endFrame) || endFrame < 0) { + throw new TypeError('endFrame must be a non-negative integer.'); } - if (startSample > this.numberOfFrames) { - throw new RangeError('startSample out of range.'); + if (startFrame > this.numberOfFrames) { + throw new RangeError('startFrame out of range.'); } - if (endSample > this.numberOfFrames) { - throw new RangeError('endSample out of range.'); + if (endFrame > this.numberOfFrames) { + throw new RangeError('endFrame out of range.'); } - if (endSample < startSample) { - throw new RangeError('endSample must not be less than startSample.'); + if (endFrame < startFrame) { + throw new RangeError('endFrame must not be less than startFrame.'); } if (this._closed) { throw new Error('AudioSample is closed.'); } - const frameCount = endSample - startSample; + const frameCount = endFrame - startFrame; const bytesPerSample = getBytesPerSample(this.format); let data: Uint8Array; @@ -2905,7 +2905,7 @@ export class AudioSample implements Disposable { this.copyTo(data.subarray(i * planeSize, (i + 1) * planeSize), { planeIndex: i, format: this.format, - frameOffset: startSample, + frameOffset: startFrame, frameCount, }); } @@ -2918,7 +2918,7 @@ export class AudioSample implements Disposable { this.copyTo(data, { planeIndex: 0, format: this.format, - frameOffset: startSample, + frameOffset: startFrame, frameCount, }); } @@ -2929,7 +2929,7 @@ export class AudioSample implements Disposable { format: this.format, sampleRate: this.sampleRate, numberOfChannels: this.numberOfChannels, - timestamp: this.timestamp + startSample / this.sampleRate, + timestamp: this.timestamp + startFrame / this.sampleRate, }); }