mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-27 10:53:50 +02:00
Turn AudioBuffers into AudioData in a chunked fashion
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
/node_modules
|
||||
/build
|
||||
/dist
|
||||
todo.txt
|
||||
+3
-1
@@ -40,6 +40,7 @@
|
||||
format = new Metamuxer.Mp4OutputFormat({ fastStart: false }); // new Metamuxer.MkvOutputFormat();// new Metamuxer.Mp4OutputFormat({ fastStart: false });
|
||||
let target = new Metamuxer.ArrayBufferTarget();
|
||||
|
||||
/*
|
||||
target = new Metamuxer.StreamTarget(new WritableStream({
|
||||
async write(chunk) {
|
||||
console.log(chunk)
|
||||
@@ -47,6 +48,7 @@
|
||||
await new Promise(resolve => setTimeout(resolve, 250));
|
||||
}
|
||||
}), { chunked: true });
|
||||
*/
|
||||
|
||||
let output = new Metamuxer.Output({ format, target });
|
||||
|
||||
@@ -170,5 +172,5 @@ Testing... <00:17.350>One... <00:18.125>Two...
|
||||
await output.finalize();
|
||||
|
||||
console.log(target);
|
||||
//download(new Blob([target.buffer]), 'test.mp4');
|
||||
download(new Blob([target.buffer]), 'test.mp4');
|
||||
</script>
|
||||
@@ -1076,7 +1076,7 @@ export class IsobmffDemuxer extends Demuxer {
|
||||
|
||||
const startPos = this.isobmffReader.pos;
|
||||
|
||||
while (true) {
|
||||
while (this.isobmffReader.pos < boxEndPos) {
|
||||
const flagAndType = this.isobmffReader.readU8();
|
||||
const metadataBlockLength = this.isobmffReader.readU24();
|
||||
const type = flagAndType & BLOCK_TYPE_MASK;
|
||||
|
||||
+38
-21
@@ -517,32 +517,49 @@ export class AudioBufferSource extends AudioSource {
|
||||
throw new TypeError('audioBuffer must be an AudioBuffer.');
|
||||
}
|
||||
|
||||
const MAX_FLOAT_COUNT = 64 * 1024 * 1024;
|
||||
|
||||
const numberOfChannels = audioBuffer.numberOfChannels;
|
||||
const sampleRate = audioBuffer.sampleRate;
|
||||
const numberOfFrames = audioBuffer.length;
|
||||
const totalFrames = audioBuffer.length;
|
||||
const maxFramesPerChunk = Math.floor(MAX_FLOAT_COUNT / numberOfChannels);
|
||||
|
||||
// Create a planar F32 array containing all channels
|
||||
const data = new Float32Array(numberOfChannels * numberOfFrames);
|
||||
for (let channel = 0; channel < numberOfChannels; channel++) {
|
||||
const channelData = audioBuffer.getChannelData(channel);
|
||||
data.set(channelData, channel * numberOfFrames);
|
||||
let currentRelativeFrame = 0;
|
||||
let remainingFrames = totalFrames;
|
||||
|
||||
const promises: Promise<void>[] = [];
|
||||
|
||||
// Create AudioData in a chunked fashion so we don't create huge Float32Arrays
|
||||
while (remainingFrames > 0) {
|
||||
const framesToCopy = Math.min(maxFramesPerChunk, remainingFrames);
|
||||
const chunkData = new Float32Array(numberOfChannels * framesToCopy);
|
||||
|
||||
for (let channel = 0; channel < numberOfChannels; channel++) {
|
||||
audioBuffer.copyFromChannel(
|
||||
chunkData.subarray(channel * framesToCopy, channel * framesToCopy + framesToCopy),
|
||||
channel,
|
||||
currentRelativeFrame,
|
||||
);
|
||||
}
|
||||
|
||||
const audioData = new AudioData({
|
||||
format: 'f32-planar',
|
||||
sampleRate,
|
||||
numberOfFrames: framesToCopy,
|
||||
numberOfChannels,
|
||||
timestamp: (1e6 * (this._accumulatedFrameCount + currentRelativeFrame)) / sampleRate,
|
||||
data: chunkData,
|
||||
});
|
||||
|
||||
promises.push(this._encoder.digest(audioData));
|
||||
audioData.close();
|
||||
|
||||
currentRelativeFrame += framesToCopy;
|
||||
remainingFrames -= framesToCopy;
|
||||
}
|
||||
|
||||
const audioData = new AudioData({
|
||||
format: 'f32-planar',
|
||||
sampleRate,
|
||||
numberOfFrames,
|
||||
numberOfChannels,
|
||||
timestamp: Math.round(1e6 * this._accumulatedFrameCount / sampleRate),
|
||||
data: data,
|
||||
});
|
||||
|
||||
const promise = this._encoder.digest(audioData);
|
||||
audioData.close();
|
||||
|
||||
this._accumulatedFrameCount += numberOfFrames;
|
||||
|
||||
return promise;
|
||||
this._accumulatedFrameCount += totalFrames;
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
- Manual key frame passing
|
||||
- Progress reporting
|
||||
- Test tree shaking
|
||||
- Throw if edit list detected
|
||||
- Audio codec string regex validation
|
||||
- Add the new audio codecs to muxers
|
||||
- Mov muxer!!! Only mov can hold PCM audio, MP4 cannot
|
||||
- Metadata methods for computing average fps and bitrate
|
||||
- close method on Output to cancel it (and dispose the encoders). Perhaps abort is a better title
|
||||
- lower default key frame interval (3 secs is better I think?) and make it outside-configurable
|
||||
Reference in New Issue
Block a user