Skip to content

fix: respect TypedArray byteOffset and byteLength in RawAudio.toBlob()#1714

Open
jahanzaib-iqbal-dev wants to merge 1 commit into
huggingface:mainfrom
jahanzaib-iqbal-dev:fix/raw-audio-typed-array-subarray
Open

fix: respect TypedArray byteOffset and byteLength in RawAudio.toBlob()#1714
jahanzaib-iqbal-dev wants to merge 1 commit into
huggingface:mainfrom
jahanzaib-iqbal-dev:fix/raw-audio-typed-array-subarray

Conversation

@jahanzaib-iqbal-dev

Copy link
Copy Markdown

Summary

Fixes RawAudio.toBlob() producing malformed WAV files when audio chunks are TypedArray subarrays with non-zero byteOffset.

Root Cause

The encodeWAV method uses chunk.buffer to get the raw binary data from each audio chunk. However, for TypedArray subarrays (created via .subarray() or .slice() in streaming contexts), .buffer returns the entire backing ArrayBuffer regardless of the view's offset and length. This causes the WAV blob to contain extra bytes from outside the actual audio data, creating a length mismatch with the WAV header.

Fix

Replace chunk.buffer with new Uint8Array(c.buffer, c.byteOffset, c.byteLength) to correctly extract only the relevant portion of the backing buffer, respecting the TypedArray view's offset and length.

Before:
```js
return new Blob([buffer, ...chunks.map((chunk) => chunk.buffer)], { type: 'audio/wav' });
```

After:
```js
return new Blob([buffer, ...chunks.map((c) => new Uint8Array(c.buffer, c.byteOffset, c.byteLength))], { type: 'audio/wav' });
```

Impact

Fixes silent audio corruption in TTS pipelines that use streaming output, where audio chunks are subarrays of a larger buffer. The WAV header length fields are computed correctly from chunk.length (number of elements), but the old chunk.buffer could include padding bytes outside the view's range, causing the actual data payload to mismatch the declared lengths.

Fixes #1704

When audio chunks are TypedArray subarrays (non-zero byteOffset), using
chunk.buffer returns the entire backing ArrayBuffer, causing WAV header
and payload length mismatch.

Fix uses new Uint8Array(c.buffer, c.byteOffset, c.byteLength) to correctly
slice only the relevant portion of the backing buffer.

Fixes huggingface#1704
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RawAudio.toBlob() encodes the entire underlying ArrayBuffer, ignoring TypedArray byteOffset/length

1 participant