Reputation: 53616
The following code reaches the flush
promise, however the created Blob
does not play because the HTMLAudioElement
fails with NotSupportedError: Failed to load because no supported source was found.
.
What am I missing?
function audioBufferToF32Planar(input: AudioBuffer): Float32Array {
const channels = input.numberOfChannels;
const result = new Float32Array(input.length * channels);
let offset = 0;
for (let channel = 0; channel < channels; channel++) {
const data = input.getChannelData(channel);
result.set(data, offset);
offset = offset + data.length;
}
return result;
}
const outputData = new ArrayBuffer(1024, { maxByteLength: 100_000_000 });
let outputOffset = 0;
const encoder = new AudioEncoder({
output: (e: EncodedAudioChunk) => {
const chunkLength = e.byteLength;
if (outputOffset + chunkLength > outputData.byteLength) {
outputData.resize(
Math.min(
outputData.byteLength + chunkLength * 10,
outputData.maxByteLength
)
);
}
const outputView = new Uint8Array(outputData);
const chunkData = new Uint8Array(chunkLength);
e.copyTo(chunkData);
outputView.set(chunkData, outputOffset);
outputOffset = outputOffset + chunkLength;
},
error: console.error,
});
// buffer is an AudioBuffer containing PCM audio data
const data = new AudioData({
format: "f32-planar",
sampleRate: buffer.sampleRate,
numberOfChannels: buffer.numberOfChannels,
numberOfFrames: buffer.length,
timestamp: 0,
data: audioBufferToF32Planar(buffer),
});
encoder.configure({
codec: "opus",
sampleRate: buffer.sampleRate,
numberOfChannels: buffer.numberOfChannels,
bitrate: 128_000,
});
encoder.encode(data);
encoder.flush().then(() => {
const data = outputData.transferToFixedLength();
const blob = new Blob([data], {
type: "audio/webm;codecs=opus",
});
// testing audio...
const player = new Audio();
player.src = URL.createObjectURL(blob);
player.play().then(
() => {
console.log("playing!");
},
(err) => {
console.error(err); // <-- error here
}
);
player.onended = () => {
URL.revokeObjectURL(player.src);
};
});
Upvotes: 2
Views: 61