jaggad / crunker

Simple way to merge or concatenate audio files with the Web Audio API.
https://jaggad.github.io/crunker/examples/client/
MIT License
404 stars 56 forks source link

Concatenate MP4 file - speed is slower than the original mp4 #52

Closed JeremCafeyn closed 2 years ago

JeremCafeyn commented 3 years ago

Hello,

I'm using your lib for a project of media player. I have to upload several mp4 files, concatenate them and read the audio file created by crunker. The problem is that the final audio file is slower than the original ones. The speed of the concatenate file is a bit slower. Is it normal?

This is how I use it:

private async createCrunker(trackSrc: string[]) {
    const crunker = new Crunker();
    const concatenatedTrack =  await crunker
      .fetchAudio(...trackSrc)
      .then((buffers: AudioBuffer[]) => crunker.concatAudio(buffers))
      .then((concatenate: AudioBuffer) => {
        const blob = crunker.export(concatenate, 'video/mp4');
        return {
          src: blob.url,
          name: '',
          isPlaying: false,
          order: 1,
        };
      });
    return concatenatedTrack;
  }

The trackSrc is an array of the property src, created via URL.createObjectURL with this function:

private formatAudioFiles(files: FileList): IAudioTrack[] {
    const customFiles: IAudioTrack[] = [];
    for (let i = 0; i < files.length; i++) {
        const src = URL.createObjectURL(files[i]);
        customFiles.push({
          name: files[i].name,
          src,
          isPlaying: false,
          order: i + 1,
        });
      // }
    }
    return customFiles;
  }

And then I read it with another lib which is HowlerJs. Is this a known problem? Or does it come from my code :D ?

jaggad commented 2 years ago

@JeremCafeyn Have you tried just exporting the concatenated audio as a wav or mp3 and not consuming the blob via another library? This should help you with pinpointing if it's an issue with Crunker or HowlerJS.

It's also potentially an issue with MP4 file. Not sure if that will be explicilty supported. You could try converting the mp4 to mp3 and then seeing if the same issue remains.

JeremCafeyn commented 2 years ago

Hi @jackedgson, thanks for your answer. Yes I tried to use other files and also with MP3 and it was the same result. BUT by changing the samplingRate in the constructor I have the result that I expected. (For MP4 and MP3) Do you know if it's a correct fix?

By the way do you know if types on crunker are available?

private async createCrunker(trackSrc: string[]) {
    const crunker = new Crunker({ sampleRate: 48000 });
    const concatenatedTrack =  await crunker
      .fetchAudio(...trackSrc)
      .then((buffers: AudioBuffer[]) => crunker.concatAudio(buffers))
      .then((concatenate: AudioBuffer) => {
        const blob = crunker.export(concatenate, 'audio/mp3');
        return {
          src: blob.url,
          name: '',
          isPlaying: false,
          order: 1,
        };
      });
    return concatenatedTrack;
  }
jaggad commented 2 years ago

@JeremCafeyn Yes if there is an explicity sampleRate you are aware of that will fix it.. if we can't infer it correctly it default to sampleRate: 44100 so that explains the slowness perfectly.

Considering this fixed.. I believe I had worked on a Typescript or Flow refactor a while back but I think it's dropped off now and probably is quite out of date.

I'd love to have the library written in Typescript instead of ES6. For now I won't be leading that, I'd be open to working with another dev on it if you'd like to create and lead the PR. Otherwise at the moment the library isn't typed.

JeremCafeyn commented 2 years ago

Ok thanks for your help and your explanation. Sure! If I have extra time I will contact you and the team before to create a PR. I close the issue now. Thanks again!