-
Notifications
You must be signed in to change notification settings - Fork 336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[question] MP4 audio to AudioBuffer #299
Comments
FYI const audioBuf = await audioCtx.decodeAudioData(data)
const frameCnt = audioBuf.sampleRate * audioBuf.duration * 2
const audioDataBuf = new Float32Array(frameCnt)
const chan0Buf = audioBuf.getChannelData(0)
audioDataBuf.set(chan0Buf, 0)
if (audioBuf.numberOfChannels >= 2) {
audioDataBuf.set(audioBuf.getChannelData(1), chan0Buf.length)
} else {
audioDataBuf.set(chan0Buf, chan0Buf.length)
}
const ad = new AudioData({
numberOfChannels: 2,
numberOfFrames: audioBuf.sampleRate * audioBuf.duration,
sampleRate: audioBuf.sampleRate,
timestamp: 0,
format: 'f32-planar',
data: audioDataBuf
}) |
Thanks so much @hughfenghen! I've tried variations of this with no luck. I've heard from other folks it's more complicated than just doing what you outlined. So the data I'm getting back from mp4box.js is a Uint8 buffer. The audio decoder method you've called out expects an ArrayBuffer. Of course I can get
It works perfectly as an EncodedAudioChunk, which can be decoded with the WebCodec API, but not using features of the Web Audio API. Perhaps there's a better way to get data where I wouldn't have this issue, but I'm not aware of it. My usage of mp4box grabs the audio as samples from the file like so:
And then the callback for |
@bengfarrell If you want AudioBuffer: Convert AudioData to AudioBuffer:
Step 1 export function extractAudioDataBuf (ad: AudioData): ArrayBuffer {
const bufs: ArrayBuffer[] = []
let totalSize = 0
for (let i = 0; i < ad.numberOfChannels; i++) {
const chanBufSize = ad.allocationSize({ planeIndex: i })
totalSize += chanBufSize
const chanBuf = new ArrayBuffer(chanBufSize)
ad.copyTo(chanBuf, { planeIndex: i })
bufs.push(chanBuf)
}
const rs = new Uint8Array(totalSize)
let offset = 0
for (const buf of bufs) {
rs.set(new Uint8Array(buf), offset)
offset += buf.byteLength
}
return rs.buffer
} I haven't written the code for the second step, but I think it should be possible, you need to refer to AudioBuffer.copyToChannel. |
@hughfenghen Thanks again - but I think I'm not quite getting across what I'm looking for. The problem is that Safari doesn't seem to be supporting the audio part of the Web Codec API, so that is a Chrome only solution. So to sum up - I'd like to
To rephrase this last step: MP4box gives me encoded audio data. Without using Apologies if I'm missing something, but I do feel like you haven't quite understood my problem yet. Thanks much for your help and patience! |
@bengfarrell Ok, I understand. You need to decode the MP4 audio sample, but you can't use the WebCodecs API.
I guess there are two ways to solve your problem:
I am not an expert in this area, the above is only my guess. |
@hughfenghen Thanks for trying! Yeah, that's basically where I ended up. Not enough of an expert on audio encoding/data to know what header data to add. |
Hi all,
Does anyone have any examples of reading and maybe queueing samples from MP4Box and creating an AudioBuffer from these?
Currently I have something that creates EncodedAudioChunks and it works great, but I'm having trouble using Web Codecs on the audio side to work well with AudioBuffers from elsewhere, so I'm thinking that I'd like to avoid using Web Codecs on the audio side. Unfortunately I fell short trying to process these samples without making the EncodedAudioChunks (other than decoding them all with Web Codecs)
Thanks!
The text was updated successfully, but these errors were encountered: