Add xingHeader option to Mp3OutputFormat

This commit is contained in:
Vanilagy
2025-08-10 16:04:18 +02:00
parent 230f02fffc
commit 5608f519a7
3 changed files with 23 additions and 3 deletions
+7 -1
View File
@@ -206,11 +206,17 @@ const output = new Output({
The following options are available: The following options are available:
```ts ```ts
type Mp3OutputFormatOptions = { type Mp3OutputFormatOptions = {
xingHeader?: boolean;
onXingFrame?: (data: Uint8Array, position: number) => unknown; 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`\ - `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 ::: info
Most browsers don't support encoding MP3. Use the official [`@mediabunny/mp3-encoder`](./extensions/mp3-encoder) package to polyfill an encoder. Most browsers don't support encoding MP3. Use the official [`@mediabunny/mp3-encoder`](./extensions/mp3-encoder) package to polyfill an encoder.
+7 -2
View File
@@ -50,7 +50,9 @@ export class Mp3Muxer extends Muxer {
const release = await this.mutex.acquire(); const release = await this.mutex.acquire();
try { try {
if (!this.xingFrameData) { const writeXingHeader = this.format._options.xingHeader !== false;
if (!this.xingFrameData && writeXingHeader) {
const view = toDataView(packet.data); const view = toDataView(packet.data);
if (view.byteLength < 4) { if (view.byteLength < 4) {
throw new Error('Invalid MP3 header in sample.'); 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.validateAndNormalizeTimestamp(track, packet.timestamp, packet.type === 'key');
this.framePositions.push(this.writer.getPos());
this.writer.write(packet.data); this.writer.write(packet.data);
this.frameCount++; this.frameCount++;
await this.writer.flush(); await this.writer.flush();
if (writeXingHeader) {
this.framePositions.push(this.writer.getPos());
}
} finally { } finally {
release(); release();
} }
+9
View File
@@ -475,6 +475,12 @@ export class WebMOutputFormat extends MkvOutputFormat {
* @public * @public
*/ */
export type Mp3OutputFormatOptions = { 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. * Will be called once the Xing metadata frame is finalized.
* *
@@ -496,6 +502,9 @@ export class Mp3OutputFormat extends OutputFormat {
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.');
} }
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') { if (options.onXingFrame !== undefined && typeof options.onXingFrame !== 'function') {
throw new TypeError('options.onXingFrame, when provided, must be a function.'); throw new TypeError('options.onXingFrame, when provided, must be a function.');
} }