zhw2590582 / WFPlayer

:ocean: WFPlayer.js is an audio waveform generator
https://wfplayer.js.org
MIT License
262 stars 32 forks source link

Browser crash on loading video/audio of duration around 2 hours #39

Closed bugcoder closed 1 year ago

bugcoder commented 1 year ago

We are using mp3 file of 7.6 MB with duration around 2 hours. WFPlayer is working fine with less duration audio files and not using much memory. However, whenever we are using audio with large duration such as 2 hours, it's consuming around 4 GB of memory and keep on using more memory and browser get crash eventually.

We are using below code:

var wf = new WFPlayer({
        container: document.querySelector('#waveform')
    });

//fetching audio with duration more than 2 hours
    fetch('example.com/mp3')
        .then((res) => res.arrayBuffer())
        .then((arrayBuffer) => {
            const uint8 = new Uint8Array(arrayBuffer);
            wf.load(uint8);
        });

Memory Usage:

image
zhw2590582 commented 1 year ago

https://github.com/zhw2590582/WFPlayer/issues/38#issuecomment-1354499219

You can download this demo to have a look. In fact, Browser crash is not a problem of wfplayer, but a limitation of native AudioContext, this is the process of decoding mp3 audio to pcm audio, which is an unavoidable problem in browsers:

https://github.com/zhw2590582/WFPlayer/blob/67cedab9721b37a7bc5b306c110d21932249f997/src/decoder.js#L12

ExtReMLapin commented 1 year ago

Alright, but what's weird is I would have expected some kind "decode 4096 bytes by 4096"

I'll try to dive into it tomorrow, thanks for the quick answer

yuguaa commented 1 year ago

This problem also occurs in the project. When decoding, the bit rate is too high, resulting in too much audio sample data, and too little rendering waveform will cause problems. After consideration, we decided to cancel the rendering of the waveform. Based on this, we changed this package., disabled the decoder, other functions are normal, but no waveform diagram

ExtReMLapin commented 1 year ago

You don't need to @yuguaa

You can use ffmpeg WASM to convert the file in browser !

   async videoOrAudioToMP3(ffmpegInstance, videoOrAudioFile) {
      // Prepare the files for ffmpeg.wasm
      //remove all spaces and special characters from the file name
      const videoOrAudioFileName = videoOrAudioFile.name.replace(/[^a-zA-Z0-9.]/g, "");
      const outputFileName = "output_" + videoOrAudioFileName + ".mp3";

      ffmpegInstance.FS("writeFile", videoOrAudioFileName, new Uint8Array(await videoOrAudioFile.arrayBuffer()));

      // Run FFmpeg command to replace the audio track
      this.conversionProgress = 0
      //const self = this;
      await ffmpegInstance.run(
        "-i",
        videoOrAudioFileName,
        "-vn",
        "-acodec",
        "libmp3lame",
        "-ac",
        "1",
        "-ar",
        "16000",
        "-ab",
        "128k",
        outputFileName
      );

      // Read the output file and return it as a File object
      const outputFileBuffer = ffmpegInstance.FS("readFile", outputFileName);
      const outputFileBlob = new Blob([outputFileBuffer.buffer], { type: "audio/mpeg" });
      const outputFile = new File([outputFileBlob], outputFileName, { type: "audio/mpeg" });
      this.conversionProgress = 100

      return outputFile;
    },
yuguaa commented 1 year ago

Thank you for your response. I appreciate it. I understand that I can do it this way. Moreover, I manually modified the drawWave method and simulated audio data using video subtitles' data. The result is that when I simulate a lower bitrate, the project runs smoothly. This might be because my practice project is based on the open-source project Subplayer by the author. However, when rendering the wfplayer with simulated data, it still crashes due to the large amount of data. It seems that I need to do more optimization for the React project. In any case, I appreciate your response.

worker.js image image index.js image image

ExtReMLapin commented 1 year ago

I wish I was this naturally polite and friendly as you are