crunker icon indicating copy to clipboard operation
crunker copied to clipboard

split large audio file [help]

Open unixxxx opened this issue 4 years ago • 2 comments

I have successfully used this library for concatenating audio files, but I was wandering if it can be used for splitting files too.

  const reader = new FileReader();
  const blob = file.slice(offset, chunkSize + offset);
  r.onload = readEventHandler;
  r.readAsArrayBuffer(blob);

reading the file in chunks, and then trying to get AudioBuffer in the readEventHandler

const readEventHandler = evt => {
    const arrayBuffer = evt.target.result as ArrayBuffer;
    crunker._context.decodeAudioData(
          arrayBuffer,
          d => console.log(d),
          e => console.log(e)
    );
}

the problem is that only the first part of the file is getting decoded since only it has the necessary headers. For the rest of the parts I am getting DOMException: Unable to decode audio data.

I tried to manually add the headers to each chunk with modified writeHeaders function , but the audio I get is somehow too fast.

Any suggestions?

const writeHeaders = (arrayBuffer: ArrayBuffer) => {
  // const arrayBuffer = new ArrayBuffer(44 + buffer.length * 2);
  const view = new DataView(arrayBuffer);
  const sampleRate = 44100;

  writeString(view, 0, 'RIFF');
  view.setUint32(4, 32 + arrayBuffer.byteLength * 2, true);
  writeString(view, 8, 'WAVE');
  writeString(view, 12, 'fmt ');
  view.setUint32(16, 16, true);
  view.setUint16(20, 1, true);
  view.setUint16(22, 2, true);
  view.setUint32(24, sampleRate, true);
  view.setUint32(28, sampleRate * 4, true);
  view.setUint16(32, 4, true);
  view.setUint16(34, 16, true);
  writeString(view, 36, 'data');
  view.setUint32(40, arrayBuffer.byteLength * 2, true);

  return floatTo16BitPCM(view, arrayBuffer, 44);
};

unixxxx avatar Dec 20 '20 23:12 unixxxx

@unixxxx If the audio is too fast, it could be that the arrayBuffer is using the original byteLength rather than the new split length?

Did you have any luck with this? I think splitting would be a good method to add to this project.

jaggad avatar Feb 01 '21 08:02 jaggad

If you use decodeAudioData() first you can get any part of the AudioBuffer from any offset.

If you do not split the file first you can use AudioWorklet or Media Capture Transform to get the exact time slices expected as Float32Arrays and then merge the data.

For live-streaming you can utilize RTCRtpSender.replaceTrack() with MediaRecorder to dynamically change the track(s).

guest271314 avatar Mar 21 '21 16:03 guest271314

This https://github.com/guest271314/audioInputToWav (is not fast) will create a WAV file from an AudioBuffer, or when modified, Float32Array(s).

If you are trying to concantenate specific time slices of of multiple audio (and, or, video) Media Fragment URI can be useful https://github.com/guest271314/MediaFragmentRecorder.

guest271314 avatar Mar 21 '21 18:03 guest271314

decodeAudioData() requires metadata. It is possible to create files from the output when the entire file is passed to the function.

guest271314 avatar Sep 11 '22 14:09 guest271314