zhw2590582 / WFPlayer

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

Large file issue #38

Closed vivekd95 closed 1 year ago

vivekd95 commented 1 year ago

Hi @zhw2590582

I am trying to load the wfplayer for large files like audio with duration 1.5-2 hours. It is leading to memory explosion. I found the Issue as well as your instruction on the common problems (Links mentioned below)

https://github.com/zhw2590582/WFPlayer#common-problem , https://github.com/zhw2590582/WFPlayer/issues/19

I am already using ffmpeg -i path/to/video.mp4 -ac 1 -ar 8000 path/to/audio.mp3 on server to reduce the size of mp3. What more can I do to check why wfplayer is crashing?

zhw2590582 commented 1 year ago

How big is your audio file? You can try this:

(async function () {
  const arrayBuffer = await (await fetch("http://your-audio-file.mp3")).arrayBuffer();
  const uint8 = Uint8Array(arrayBuffer);

  const wf = new WFPlayer({
    container: document.querySelector("#waveform"),
  });

  wf.load(uint8);
})();
vivekd95 commented 1 year ago

Thanks for the reply @zhw2590582. For a 1.3 GB video file with duration of approximately 2.5 hours, the audio file is of approximately 8.7 MB.

This is the initialization function for WFPlayer (In reactjs). Can you please make changes you commented above into this code segment.

Where this.$waveform.current is ref attached to waveform div & this.props.pcmUrl contains the url for mp3.

initWFPlayer() {
        const { art } = this.props;
        const { $video } = art.template;
        if ($video.src) {
            if (this.wf) {
                this.wf.destroy();
            }
            this.wf = new WFPlayer({
                container: this.$waveform.current,
                mediaElement: document.querySelector('#video'),
                waveColor: 'rgba(255, 235, 59, 0.95)',
                progressColor: 'rgba(255, 255, 255, 0.3)',
                cors: true,
            });

            art.on('seek', () => {
                if (art.currentTime) {
                    this.wf.seek(art.currentTime);
                }
            });

            art.on('video:timeupdate', () => {
                this.wf.seek(art.currentTime);
            });
            this.wf.load(this.props.pcmUrl);
        }
    }
zhw2590582 commented 1 year ago
async initWFPlayer() {
        const { art } = this.props;
        const { $video } = art.template;
        if ($video.src) {
            if (this.wf) {
                this.wf.destroy();
            }
            this.wf = new WFPlayer({
                container: this.$waveform.current,
                mediaElement: document.querySelector('#video'),
                waveColor: 'rgba(255, 235, 59, 0.95)',
                progressColor: 'rgba(255, 255, 255, 0.3)',
                cors: true,
            });

            art.on('seek', () => {
                if (art.currentTime) {
                    this.wf.seek(art.currentTime);
                }
            });

            art.on('video:timeupdate', () => {
                this.wf.seek(art.currentTime);
            });

            const arrayBuffer = await (await fetch(this.props.pcmUrl)).arrayBuffer();
            const uint8 = Uint8Array(arrayBuffer);
            this.wf.load(uint8);
        }
    }
vivekd95 commented 1 year ago

Yeah. I did the same and the waveform is not loading. It is just keep loading. Any thing else that I can?

Also, Can you explain that is there any difference between below mentioned code segments

fetch(this.props.pcmUrl)                      |  const arrayBuffer = await (await fetch(this.props.pcmUrl)).arrayBuffer();
   .then((res) => res.arrayBuffer())          |  const uint8 = Uint8Array(arrayBuffer);
     .then((buffer) => {                      |  this.wf.load(uint8);
           const uint8 = Uint8Array(buffer);  |
            this.wf.load(uint8);              |
   });                                        |  
geekhunger commented 1 year ago

Also, Can you explain that is there any difference between below mentioned code segments

fetch(this.props.pcmUrl)                      |  const arrayBuffer = await (await fetch(this.props.pcmUrl)).arrayBuffer();
   .then((res) => res.arrayBuffer())          |  const uint8 = Uint8Array(arrayBuffer);
     .then((buffer) => {                      |  this.wf.load(uint8);
           const uint8 = Uint8Array(buffer);  |
            this.wf.load(uint8);              |
   });                                        |  

The code segments are totally equal.

zhw2590582 commented 1 year ago

@NinjaCoderDotCom Can you send me your audio file? Or give me a url of audio, I want to test it

vivekd95 commented 1 year ago

Also, Can you explain that is there any difference between below mentioned code segments

fetch(this.props.pcmUrl)                      |  const arrayBuffer = await (await fetch(this.props.pcmUrl)).arrayBuffer();
   .then((res) => res.arrayBuffer())          |  const uint8 = Uint8Array(arrayBuffer);
     .then((buffer) => {                      |  this.wf.load(uint8);
           const uint8 = Uint8Array(buffer);  |
            this.wf.load(uint8);              |
   });                                        |  

The code segments are totally equal.

Thank you for confirming. I just wanted to cross check.

vivekd95 commented 1 year ago

@NinjaCoderDotCom Can you send me your audio file? Or give me a url of audio, I want to test it

https://easyupload.io/a3cnnh

zhw2590582 commented 1 year ago

I wrote it wrongly, then I wrote you a demo, on my computer, the time it takes to decode your audio file is about 7 seconds:

const uint8 = Uint8Array(buffer)

const uint8 = new Uint8Array(buffer)

download it.zip

vivekd95 commented 1 year ago

I wrote it wrongly, then I wrote you a demo, on my computer, the time it takes to decode your audio file is about 7 seconds:

const uint8 = Uint8Array(buffer)

const uint8 = new Uint8Array(buffer)

download it.zip

Are you passing the audio url after getting it from backend or have you placed media files locally in public folder and then passing it to load function?

zhw2590582 commented 1 year ago

I wrote you a demo

Snipaste_2022-12-16_18-47-15

vivekd95 commented 1 year ago

I followed your demo and made changes in my react app example. You can download the attached zip file from the following URL. I am getting error that

WFPlayerError: The load target is not a string. If you are loading a mediaElement, make sure the mediaElement.src is not empty.

As far as I can see, I have passed mediaElement into the props and loading the media correctly in the this.wf.load().

https://easyupload.io/nlmbgp

zhw2590582 commented 1 year ago

The zip is 1.2G !! too big !!

vivekd95 commented 1 year ago

The zip is 1.2G !! too big !!

Sorry for late response. Yeah, It have media files also so that you can run the demo and check in exact same case in which I want it to use. Nonetheless, Can you tell me what is gridGap means in the value drawer.gridGap? Like which value does it represents? If this value can be shown in the waveform, do show it via screenshot or something.

zhw2590582 commented 1 year ago

gridGap means the split width of the horizontal axis, in pixels:

Snipaste_2022-12-26_22-04-36