diff --git a/docs/guide/output-formats.md b/docs/guide/output-formats.md index a086fb7..4317ee6 100644 --- a/docs/guide/output-formats.md +++ b/docs/guide/output-formats.md @@ -206,11 +206,17 @@ const output = new Output({ The following options are available: ```ts type Mp3OutputFormatOptions = { + xingHeader?: boolean; onXingFrame?: (data: Uint8Array, position: number) => unknown; }; ``` +- `xingHeader`\ + Controls whether the Xing header, which contains additional metadata as well as an index, is written to the start of the MP3 file. Defaults to `true`. + ::: info + When set to `false`, this option ensures [append-only writing](#append-only-writing). + ::: - `onXingFrame`\ - Will be called once the Xing metadata frame is finalized, which happens at the end of the writing process. + Will be called once the Xing metadata frame is finalized, which happens at the end of the writing process. This callback only fires if `xingHeader` isn't set to `false`. ::: info Most browsers don't support encoding MP3. Use the official [`@mediabunny/mp3-encoder`](./extensions/mp3-encoder) package to polyfill an encoder. diff --git a/src/mp3/mp3-muxer.ts b/src/mp3/mp3-muxer.ts index d461543..051bcf9 100644 --- a/src/mp3/mp3-muxer.ts +++ b/src/mp3/mp3-muxer.ts @@ -50,7 +50,9 @@ export class Mp3Muxer extends Muxer { const release = await this.mutex.acquire(); try { - if (!this.xingFrameData) { + const writeXingHeader = this.format._options.xingHeader !== false; + + if (!this.xingFrameData && writeXingHeader) { const view = toDataView(packet.data); if (view.byteLength < 4) { throw new Error('Invalid MP3 header in sample.'); @@ -97,11 +99,14 @@ export class Mp3Muxer extends Muxer { this.validateAndNormalizeTimestamp(track, packet.timestamp, packet.type === 'key'); - this.framePositions.push(this.writer.getPos()); this.writer.write(packet.data); this.frameCount++; await this.writer.flush(); + + if (writeXingHeader) { + this.framePositions.push(this.writer.getPos()); + } } finally { release(); } diff --git a/src/output-format.ts b/src/output-format.ts index 5f22e3d..5faebcb 100644 --- a/src/output-format.ts +++ b/src/output-format.ts @@ -475,6 +475,12 @@ export class WebMOutputFormat extends MkvOutputFormat { * @public */ export type Mp3OutputFormatOptions = { + /** + * Controls whether the Xing header, which contains additional metadata as well as an index, is written to the start + * of the MP3 file. When disabled, the writing process becomes append-only. Defaults to true. + */ + xingHeader?: boolean; + /** * Will be called once the Xing metadata frame is finalized. * @@ -496,6 +502,9 @@ export class Mp3OutputFormat extends OutputFormat { if (!options || typeof options !== 'object') { throw new TypeError('options must be an object.'); } + if (options.xingHeader !== undefined && typeof options.xingHeader !== 'boolean') { + throw new TypeError('options.xingHeader, when provided, must be a boolean.'); + } if (options.onXingFrame !== undefined && typeof options.onXingFrame !== 'function') { throw new TypeError('options.onXingFrame, when provided, must be a function.'); }