我目前正在冒险,我的理智受到威胁,我尝试在我的网络应用程序上简单地播放 mp3 文件。此 mp3 是按块加载的,以使体验更具响应性。
尽管 MediaSource API 的文档非常有用,而且数百个解释良好的示例为拯救铺平了道路,但我发现自己无法使一切正常工作。
我面临的最后一个问题是搜索功能。我对这个功能的简单想法就是简单地杀死所有活着的东西,烧毁所有东西然后再次复活。更准确地说,如果用户需要,我会停止机器并从头开始播放所有内容,但具有所需的偏移量(以秒为单位)。
到目前为止,一切都正常,除了最后一件事:currentTime
,在我将其设置为用户请求的时间后,被设置为不同的值。轨道继续按预期播放,但
问题是currentTime
用于为用户可视化轨道内的当前位置。这就是用户搜索之前和之后事件发生的方式
[play-click] <--- User clicks play button
:
[timeupdate] currentTime: 00.01
[timeupdate] currentTime: 00.02
[timeupdate] currentTime: 00.03
[seek-click] <--- User seeks, stop() is called and then playFrom(seconds)
[loadstart] currentTime: 33.33 # This is the (correct) time set in playFrom(seconds)
[loadmetadata] currentTime: 10.12 # Now the time gets set to this (wrong) value
[seek] currentTime: 10.12 # The triggered seek event comes in
[seeked] currentTime: 10.12
[canplay] currentTime: 10.12
[playing] currentTime: 10.12
[timeupdate] currentTime: 10.13 # Track continues to play correctly but this value is still wrong
:
这就是寻找发生的方式:
public play(track: Track) {
this.track = track;
this.playFrom(0);
}
public seekTo(seconds: number) {
this.stop();
this.playFrom(seconds);
}
public stop() {
this.logger.debug('Stop ..');
this.sourceBuffer.abort();
this.audioObj.pause();
this.removeEvents(this.audioObj, this.audioEvents, this.audioEventsHandler);
this.audioObj = null;
this.sourceBuffer = null;
this.mediaSource = null;
}
现在,playFrom(seconds)
方法比这更复杂一些,但它真正所做的只是重新创建我刚刚销毁的所有内容:
private playFrom(seconds: number) {
this.logger.debug(`Start playing from ${seconds.toFixed(2)} seconds`)
// [:] (collapsed some less important code here)
// Create the media source object
this.mediaSource = new MediaSource();
this.mediaSource.addEventListener('sourceopen', this.onSourceOpen);
// Create audio element
this.audioObj = document.createElement('audio');
this.audioObj.src = URL.createObjectURL(this.mediaSource);
this.audioObj.currentTime = seconds;
this.addEvents(this.audioObj, this.audioEvents, this.audioEventsHandler);
this.logger.debug(`Object-url: ${this.audioObj.src}`);
this.state = {currentTime: seconds, playing: true};
}
如何在这里获取正确的当前时间?我尝试了另一个想法,我试图创建一个新的
SourceBuffer
并将其添加到
MediaSource
,并让它从那里播放音频,但我也无法做到这一点。
设置 MediaSource 持续时间,但至少与当前缓冲的最高媒体演示结束时间一样高。
您可以在本地测试演示播放器。访问存储库
https://github.com/stacknide/mp4box-apps 并查看 demo-player 文件夹