HTML5视频中如何动态使用第一帧作为海报?

75

我想知道是否有一种简单直接的方法来实现这个效果,而不需要后端代码来提取帧、将其保存为jpg并在某处存储。

当视频加载时,第一帧仅作为海报显示的效果会非常有帮助(显然,只有浏览器能播放视频,才能起作用,这可能与传统的 poster 的工作方式略有不同,但这并不是一个问题)。

8个回答

103

您尝试了以下方法吗?

只需在源URL后添加时间(秒)#t={seconds}

  <video controls width="360">
    <source src="https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/1080/Big_Buck_Bunny_1080_10s_1MB.mp4#t=0.1" type="video/mp4" />
  </video>

我选择了一个极短的时间(0.1秒)来保持帧数的少量,因为我怀疑如果你设置了1秒,它会"预加载"视频的前1秒(即24帧或更多…)。以防万一...
在桌面上的Chrome和Firefox上效果很好 :)
但是在Android手机上无法工作:(
我还没有在iOS、iPhone、IE上测试过??

2021年5月更新:

我意识到许多现代浏览器现在会自动显示第一帧的海报。
看起来他们听到了我们的声音 :-)

5
应该接受这个答案。使用这个简单的技巧不需要使用复杂的库。 - Rubenxfd
2
重要的是,参数preload不应设置为“none”,也不应该没有给出,因此默认值为“auto”或手动设置为“preload =” auto“。 - wittich
2
即使t值很小,这显著增加了我的页面加载时间。 - zerohedge
1
这显然被称为“媒体片段”。https://blog.addpipe.com/10-advanced-features-in-html5-video-player/ - Dmitry Minkovsky
这对于前90个视频的链接有效,但之后浏览器在1秒钟内就放弃了。 - MeSo2
显示剩余2条评论

42
为了简单起见,您只需在

24

有一个名为Popcorn.js的插件,名为Popcorn.capture,它允许您从HTML5视频的任何帧创建海报。

浏览器强制实施了一个限制,禁止读取跨域请求的像素数据(使用画布API记录当前帧的值)。要使此方法有效,源视频必须托管在与请求脚本和HTML页面相同的域上。

使用此插件创建海报的代码非常简单:

// This block of code must be run _after_ the DOM is ready
// This will capture the frame at the 10th second and create a poster
var video = Popcorn( "#video-id" );

// Once the video has loaded into memory, we can capture the poster
video.listen( "canplayall", function() {

  this.currentTime( 10 ).capture();

});

看起来像我需要的。不幸的是,不能让popcorn本身工作...每次调用它都会出现 "Uncaught Error: INVALID_STATE_ERR: DOM Exception 11 popcorn.js:389 Popcorn.extend.Popcorn.forEach.ret popcorn.js:389" 的错误。 - Damon
看起来你没有等待视频加载完成。我已经更新了上面的代码示例,现在会先等待再设置海报。 - Rick
1
谢谢,这让它工作了。至少大部分是这样的。我以为从文档中得出的结论是 this.capture({at: 1}).currentTime(0); 会从第一秒开始获取海报,然后将视频放到开头,但实际上它仍然停留在第一秒。你有相关经验吗? - Damon
其实,那听起来像是一个 bug :) 你能在 Github 存储库上提交一个问题吗? - Rick
3
我只是让它开始播放并停在加载的第一帧。 - Pencilcheck
在Popcorn中,"#video-id"是什么意思( "#video-id" )?我在我的主机上有一个视频链接,并且正在使用jwplayer来展示我的视频!我该如何使用这个API?谢谢。 - Saeid

18

最近我在一个可在桌面和移动设备上使用的项目中进行了这项工作。关键是使其在iPhone上正常工作。

preload=metadata 在桌面和安卓设备上有效,但在iPhone上无效。

对于iPhone,我必须将其设置为autoplay,这样海报图像就会在初始加载时自动出现。iPhone会阻止视频自动播放,但结果会显示海报图像。

我需要使用Pavan在此处找到的答案检查iPhone。 检测iPhone浏览器。 然后根据设备使用适当的视频标签,带有或不带autoplay

var agent = navigator.userAgent;
var isIphone = ((agent.indexOf('iPhone') != -1) || (agent.indexOf('iPod') != -1)) ;

$videoTag = "";
if(isIphone()) {
    $videoTag = '<video controls autoplay preload="metadata">';
} else {
    $videoTag = '<video controls preload="metadata">';
}

1
这个答案解释了为什么会出现这个问题,并提供了一个解决方法。请注意,在iOS 10中,如果满足某些条件,autoplay属性可能会被执行。因此,我建议每个人立即暂停视频,以防止实际的自动播放。 - Alessandro Vendruscolo
@Alessandro,你能展示一些代码吗?我们如何在iOS 10中处理它将会很棒。谢谢。 - Mourice
5
var video = document.createElement('video'); video.controls = true; video.preload = 'metadata'; if (isIphone) { video.autoplay = true; video.pause(); } 翻译:创建一个名为"video"的变量,赋值为文档新建一个<video>元素。设置该元素属性"controls"为true表示显示视频控制条,设置"preload"属性为'metadata'表示在页面加载时只预加载元数据。如果是在iPhone上浏览,那么设置"autoplay"属性为true表示自动播放视频,并暂停视频。 - Alessandro Vendruscolo
你救了我的一天,伙计。你对我来说价值就像50分一样 :) - pery mimon
2
除非您确实需要自动播放,否则请勿使用此方法,因为iOS现在支持静音视频的内联自动播放。 - Michael Giovanni Pumo
但这样做最终会缓冲整个视频并消耗带宽,至少element.play().then(()=> element.pause());是这样的。 - MarcinL

8
您可以在视频元素上设置preload='auto'来自动加载视频的第一帧。

2
仅提供一个建议:预加载意味着视频可能会在没有用户操作的情况下自动下载。这是在桌面上Chrome、Firefox和IE上默认发生的情况。因此,请确保它不会影响您网页上的用户体验。 - Loïc Lopes
1
虽然这只是一个提示而不是指令,但这是一个好的观点,尤其是在桌面端。这篇文章有些过时,但可以参考一下:https://www.stevesouders.com/blog/2013/04/12/html5-video-preload/ - James Westgate
在我的情况下,当鼠标悬停时,视频只有8秒播放,它可以正常工作! - WesleyMacente

5
解决方案针对第二个、第三个框架等。我们需要为重置默认帧附加一次性处理程序 .one()。
<video width="300" height="150" id='my-video'>
   <source src="testvideo.mp4#t=2" type="video/mp4" />
</video>

$(function () {
     let videoJs = videojs('my-video');
     videoJs.one('play', function () {
          this.currentTime(0);
     });
});

显示其他框架的好主意 - Hargun Singh

3
我找到了一种很好的方法来动态添加视频海报!要显示视频中所需的帧(在我的情况下是1.75秒处的帧)-将preload =“metadata”添加到视频元素中,并在源URL的结尾处添加#t=1.75。向视频元素添加eventListener,仅监听play事件一次。一旦事件被触发,重置视频时间。
<video width="100%" controls="controls" preload="metadata" id="myVid">
    <source src="path/to/your/video#t=1.75" type="video/mp4">
</video>

<script>
    var el = document.getElementById('myVid');
    el.addEventListener('play', () => {
        el.currentTime = 0;
    }, { once: true });
</script>

1

对于其他想要指定图片作为海报的人,请使用poster属性

<video src="/path/to/video.mp4" poster="/path/to/poster.png"></video>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接