如何使用 HTML5 <video> 创建帧精确的视频序列器?

Posted

技术标签:

【中文标题】如何使用 HTML5 <video> 创建帧精确的视频序列器?【英文标题】:How to create a frame-accurate video sequencer with HTML5 <video>? 【发布时间】:2011-06-05 15:40:03 【问题描述】:

我正在尝试构建一个能够连续无缝播放视频 URL 列表的视频定序器。视频之间不能有间隙;播放需要尽可能接近帧精度。

尝试 #1 我使用了一种相当明显和直接的方法,类似于这个线程中提到的方法。 html 5 video or audio playlist

这种方法的问题在于,每次一个视频结束且后续视频被指定为新来源时,仍需要加载该新视频,从而导致可能存在较长的间隙。如果可以强制所有视频在 video.src 中命名之前进行预加载,那么这种方法仍然可能有效。

尝试 #2 我重写了脚本,因此列表中的每个视频都会创建一个单独的视频元素,但不会附加到文档(使用 createElement)。然后当每个视频结束时,我删除了前一个节点并附加了下一个元素。

页面加载时执行的代码:

对于(我在时间线播放) if (timelinePlay[i] != null) var element = document.createElement('video'); element.id = 'video1-' + (i); element.src = 时间线播放[i]['URL']; element.preload = '加载'; video1Array[i] = 元素;

视频“结束”事件的代码:

videoElement.addEventListener(“结束”,函数(事件) 如果(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(); 时间线当前++; , 错误的);

(请注意,这些代码示例是部分的并且有些简化。另外,我确实意识到我将对象用作关联数组并不是最佳实践)

这种修改的结果更接近了,因为视频现在在需要播放的时候加载了,但视频之间仍然存在短暂且不一致的间隙。

尝试 #3 我用 'timeupdate' 监听器替换了 'ended' 事件监听器,开始如下:

nextVideo.addEventListener("timeupdate", 函数(事件) 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 开发

【问题讨论】:

【参考方案1】:

由于您的提示,我现在设法解决了类似的问题。结果是一个可能是动态的视频元素列表,可以一个接一个地不间断地播放。

我在几个视频元素上使用 jwplayer,而不是原生视频标签。 启动时,所有元素开始播放一秒钟,暂停并倒带为零。 然后一个接一个地播放并通过 display: block 显示出来。

<ul class="playlist">
    <li>
        <video class="playlist" id="vid01" poster="img/preview.jpg">
            <source src="vid/v01.mp4" type="video/mp4">
        </video>
    </li>
    <li>
        <video class="playlist" id="vid02" poster="img/preview.jpg">
            <source src="vid/v02.mp4" type="video/mp4">
        </video>
    </li>
    <li>
        <video class="playlist" id="vid03" poster="img/preview.jpg">
            <source src="vid/v03.mp4" type="video/mp4">
        </video>
    </li>
    <li>
        <video class="playlist" id="vid04" poster="img/preview.jpg">
            <source src="vid/v04.mp4" type="video/mp4">
        </video>
    </li>
</ul>

添加到舞台后,“预加载”视频一到两秒: (摘录)

var isPrebuffering = false,
    isSeeking = false;

$player = jwplayer(videoId).setup(
    width: '800px',
    height: '450px',
    autoplay: false,
    modes: [
         type: 'html5' 
    ],
    events: 
        onReady: function(e) 
            prebuffer();
        ,
// There is a quirk in jwplayer that makes it impossible to pause at the 
// new position directly after seeking. So we have to work around that.
        onTime: function(e) 
            if((e.position > 1.0 && isPrebuffering) || isSeeking) 
                finishPrebuffering();
            
        
    
);

function prebuffer() 
    isPrebuffering = true;
    $player.setMute(true);
    $player.play();
;

function finishPrebuffering() 
    if(isPrebuffering) 
        isPrebuffering = false;
        isSeeking = true;
        $player.seek(0);
    

    if($player.getPosition() === 0) 
        isSeeking = false;
        $player.pause();
        $player.setMute(false);
    
;

【讨论】:

【参考方案2】:

HTML5 的 mediaElement 接口有时会在预加载、加载和缓冲之间产生混淆。 但是您是否尝试在您的视频上放置一个事件以在视频结束前 3 秒进行检测? 然后在 ajax 中尝试在新的 div 中加载下一个视频。 在您的视频结束事件中,您可以切换 div,这样您的下一个视频就可以加载到足以播放。 等下一个视频。

http://www.w3.org/TR/html5/video.html#media-elements

【讨论】:

谢谢蒂姆。实际上,我确实尝试了与尝试 2 和 3 类似的操作。在这两种情况下,确实似乎视频已及时加载以按顺序播放,但在视频之间切换节点的过程似乎并不发生得足够快或一致,足以实现无缝或接近无缝播放。 不用在 Dom 节点上播放,你可以只使用 display:block;显示:无;或发挥知名度。多亏了这一点,过渡可能会很好。 你是对的,蒂姆。简单地切换显示样式似乎确实减少了切换节点的延迟。有一定的改进,但仍然不是很无缝。【参考方案3】:

您也许可以通过http://popcornjs.org/ 做到这一点。他们提供了 js 钩子,使用 html5 视频标签逐帧进入视频。有很多活动等等。

【讨论】:

以上是关于如何使用 HTML5 <video> 创建帧精确的视频序列器?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Youtube 视频嵌入 HTML5 <video> 标签?

如何使用 Spring MVC 返回视频,以便可以使用 html5 <video> 标签进行导航?

如何使用 HTML5 <video> 元素播放 m3u8(文件)视频?

如何在 iOS 上自动播放 HTML5 <video> 和 <audio> 标签?

html5如何更改video的src属性

浏览器如何计算 HTML5 <video> 的帧速率 (fps) 以实现准确的帧搜索?