peaks.js
peaks.js copied to clipboard
player can't play the audio after called the setSource function
I am trying to call setSource function to update the wave and audio. After I calling this function, I can see the wave just changed immediatly. However, when I call the play function of the Player, nothing happened.
Can you share a minimal code example that demonstrates the problem?
let blob = new Blob(this.replaceClipCurrentBuffer, {type: 'audio/mp3'})
let fileReader = new FileReader()
fileReader.onloadend = (evt) => {
this.audioContext.decodeAudioData(evt.target.result).then(audioBuffer => {
let audioSourceElement = document.getElementById('audio')
audioSourceElement.src = URL.createObjectURL(blob)
// let convertedBuffer = blobToAudioBuffer(this.audioContext, blob)
// var audioElement = document.getElementById('audio')
//
audioSourceElement.load()
this.peaksInstance.setSource({
mediaUrl: audioSourceElement.src,
webAudio: {
audioContext: this.audioContext,
audioBuffer: audioBuffer
},
}, (error) => {
// this.audioBuffer = concatenateBuffer
console.log('finish')
})
}).catch(error => {
})
}
fileReader.readAsArrayBuffer(blob)
Your example works OK for me - the only difference is that I used <input type="file">
and so I do URL.createObjectURL()
using a File
and not a Blob
. I don't think that's significant though.
Note that the intention with setSource()
is that it updates the media element's src
for you, and you shouldn't need to call load()
. Also, as you have an AudioBuffer
you don't also need to pass in the AudioContext
.
const options = {
mediaUrl: URL.createObjectURL(blob),
webAudio: {
audioBuffer: audioBuffer
}
};
peaksInstance.setSource(options, callback);
@chrisn I just found if i directly access the url of Blob, it takes some time to generate the audio. I am not sure is it because I am building a blob through the audioBuffer? And it might also be reason why the audio can't be played?
What happens if you set the media element src
without calling peaks.setSource()
? Does this also stop the audio being played?
What Peaks.js does internally when you call setSource()
is change the media element's src
, waits for a media element canplay
event, then updates the waveform view.
@chrisn I tryied to set src without calling peaks.setSource() and still unable to play the audio. But I found if I add browser default controls to the audio, it was able to be played. Not sure what's happening behind the curtain.
Are there any clues in the browser console? I wonder if it's being blocked because of autoplay policy.
There is no error logs. And I also found if called the URL.createObjectURL(), even for the default browser control bar might take few seconds to let me play. If I clicked the play button before that time, the progress bar just retunred to the zero. However the progress already displayed the duration of the audio.
@chrisn Looks like I found the issue, if I added preload='auto'
to the audio element the issue will be resolved.
Excellent! I might experiment with preload settings to see if we should anything about that to the documentation.
For my case, the scenario requires the aduio to be loaded immedaitly after the I set the src attribute. Not sure this preload='auto'
should be applied for all the time. But anyway, thanks for the help on this issue! If you need anything from me when doing the experiment, please let me know.
I had this same issue.. I'm using the new File System Access API and have a FileHandle that points to the local file, but that doesn't appear to be supported by the audio element yet.
So I was attempting to convert the arraybuffer as described in various SO articles:
const file = await track.fileHandle.getFile();
const arraybuffer = await file.arrayBuffer;
const blob = new Blob([arraybuffer], { type: 'audio/mp3' });
const url = window.URL.createObjectURL(blob);
waveform.setSource({ mediaUrl: url, webAudio: { audioBuffer } },
err => { if (err) console.error(err) });
However that wasn't working. Based on your comments above, I tried just using the file, and that did the trick (no preload='auto'
necessary):
const file = await track.fileHandle.getFile();
const url = window.URL.createObjectURL(file);
waveform.setSource({ mediaUrl: url, webAudio: { audioBuffer } },
err => { if (err) console.error(err) });
I've just fixed setSource()
to also call mediaElement.load()
which hopefully solves this. Please re-open if there are still any problems.