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.