如何使用 HTML5
我正在尝试构建一个视频排序器,能够连续无缝播放视频 URL 列表。视频之间不能有间隙;播放需要尽可能接近帧精度。
尝试#1 我使用了一种相当明显且直接的方法,类似于本线程中提到的方法。 HTML 5 视频或音频播放列表
这种方法的问题是,每次视频结束后,后续视频被指定为新源,但新视频仍需要加载,从而导致可能存在很长的间隙。如果可以强制所有视频在 video.src 中命名之前进行预加载,那么这种方法仍然可能有效。
尝试#2 我重写了脚本,以便列表中的每个视频都会创建一个单独的视频元素,但不会附加到文档(使用 createElement)。然后,当每个视频结束时,我删除了前一个节点并附加了下一个元素。
页面加载时执行的代码:
for (i in timelinePlay) if (timelinePlay[i] != null) { var element = document.createElement('video'); element.id = 'video1-' + (i); element.src = timelinePlay[i]['URL']; element.preload = 'load'; video1Array[i] = element; }
视频“结束”事件的代码:(
videoElement.addEventListener("ended", function (event) { if (this.currentTime > 0) { if (player.hasChildNodes()) while (player.childNodes.length > 0) player.removeChild(player.firstChild); player = document.getElementById('canvas-player'); player.appendChild(video1Array[timelineCurrent]); nextVideo = document.getElementById('video1-' + timelineCurrent); nextVideo.play(); timelineCurrent++; } }, false);
请注意,这些代码示例是部分的并且有些简化。此外,我确实意识到我使用对象作为关联数组不是最佳实践)
此修改的结果是更接近了,因为视频现在已在需要播放的时间加载,但视频之间仍然存在短暂且不一致的间隙。
尝试#3 我将“结束”事件侦听器替换为“timeupdate”侦听器,开始如下:(
nextVideo.addEventListener("timeupdate", function (event) { if (this.currentTime > (this.duration - 0.1) && this.currentTime > 1) { this.removeEventListener("timeupdate", function () { return; }, false);
“this.currentTime > 1”只是为了确保上一个视频实际播放)
我希望视频之间的间隙足够接近为了保持一致,在上一个视频结束前任意 0.1 秒开始下一个视频会将间隙纠正到可接受的程度。结果是时机确实比较好,但是就是跳过视频。我将跳过的视频归因于“timeupdate”事件的失败,但我可能是错的。
我还考虑过其他替代方案: SMIL 脚本(似乎已过时,并且可能会出现相同的同步问题) 后端使用 ffmpeg 连接视频(我的主机不允许 shell 脚本)
仅供参考,我目前正在为 Safari 5.0.3 开发
I am attempting to build a video sequencer that is capable of playing back a list of video URLs seamlessly in series. There cannot be a gap between the videos; the playback needs to be as close to frame-accurate as possible.
Attempt #1
I used a fairly obvious and straightforward approach, similar to that mentioned in this thread.
HTML 5 video or audio playlist
The issue with this approach was that each time one video ended and the subsequent video was specified as the new source, that new video still needed to load, resulting in a potentially long gap. If it is possible to force all the videos to preload even before they are named in video.src, this approach could still potentially work.
Attempt #2
I rewrote the script so each video in the list would result in a separate video element being created, but not attached to the document (using createElement). Then as each video ended, I removed the previous node and appended the next element.
Code executed on page load:
for (i in timelinePlay) if (timelinePlay[i] != null) { var element = document.createElement('video'); element.id = 'video1-' + (i); element.src = timelinePlay[i]['URL']; element.preload = 'load'; video1Array[i] = element; }
Code for video 'ended' event:
videoElement.addEventListener("ended", function (event) { if (this.currentTime > 0) { if (player.hasChildNodes()) while (player.childNodes.length > 0) player.removeChild(player.firstChild); player = document.getElementById('canvas-player'); player.appendChild(video1Array[timelineCurrent]); nextVideo = document.getElementById('video1-' + timelineCurrent); nextVideo.play(); timelineCurrent++; } }, false);
(Note that these code examples are partial and somewhat simplified. Also, I do realize that my use of Objects as Associative Arrays is not best practice)
The result of this modification was MUCH closer, because the videos were now loaded by the time they were required to play, but there was still a short and inconsistent gap between the videos.
Attempt #3
I replaced the 'ended' event listener with a 'timeupdate' listener, beginning as follows:
nextVideo.addEventListener("timeupdate", function (event) { if (this.currentTime > (this.duration - 0.1) && this.currentTime > 1) { this.removeEventListener("timeupdate", function () { return; }, false);
('this.currentTime > 1' is simply to ensure that the previous video actually plays)
My hope was that the gap between videos was close enough to being consistent that starting the next video an arbitrary 0.1 seconds before the previous video ended would correct the gap to an acceptable extent. The result was that the timing was indeed better, but it was skipping videos. I attribute the skipped videos to misfiring of the 'timeupdate' event, but I could be mistaken.
Other alternative options I had also considered:
SMIL Script (seems to be obsolete, and would likely have the same syncing issues anyway)
ffmpeg on the backend to concatenate the videos (my host will not allow shell scripts)
FYI I am developing for Safari 5.0.3 at the moment
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我遇到了类似的问题,由于您的提示,我现在已经解决了。结果是可能是动态的视频元素列表,可以连续无间隙地播放。
我在多个视频元素上使用 jwplayer,而不是本机视频标签。
启动时,所有元素开始播放一秒,暂停并倒回至零。
然后逐个播放并通过 display: block 使其可见。
添加到舞台后,“预加载”视频一到两秒:
(摘抄)
I had a similar problem that I managed to solve now thanks to your hints. The result is a possibly dynamic list of video elements that may be played back one after another without gaps.
Instead of a native Video Tag I use jwplayer on several video elements.
On startup all elements begin to play one second, are paused and rewound to zero.
Then one by another is played and made visible with display: block.
On added to stage, 'preload' the video one or two seconds:
(Excerpt)
HTML5 的 mediaElement 接口有时在预加载、加载和缓冲之间非常混乱。
但是您是否尝试过在视频中添加一个事件来检测,例如视频结束前 3 秒?
然后在 ajax 中尝试在新的 div 中加载下一个视频。
在视频结束时,您可以切换 div,这样您的下一个视频就有足够的负载可以播放。
下一个视频依此类推。
http://www.w3.org/TR/html5/video.html #媒体元素
The mediaElement interface of HTML5 can be quite confusing sometimes between preload, load and buffered.
But have you tried to put an event on your video to detect for example 3 seconds before the end of your video ?
Then in ajax try to load the next video in a new div.
On the ended event of your video you could switch the div, so your next video will be enough loaded to be played.
And so on for the next videos.
http://www.w3.org/TR/html5/video.html#media-elements
您也许可以使用 http://popcornjs.org/ 来完成此操作。他们提供js钩子,使用html5视频标签逐帧插入视频。还有很多活动等等。
You might be able to do so with http://popcornjs.org/. They provide js hooks, on a frame by frame level into the video using html5 video tag. There are a lot of events etc.