h5播放视频
一个在h5页面播放视频的需求。最先采用了video标签的方案,后改为使用JSMpeg。
video标签方案
使用html原生的video标签播放。
video标签文档:https://www.runoob.com/tags/tag-video.html
使用如下:
1 | <template> |
只需填写配置即可,controls是控制条,poster是封面图,loop是循环播放,等等。详细见上面文档。
可以用id或ref获取video元素,调用播放、暂停等方法。
video在不同浏览器也会有不同表现,需要加上以下属性:
- webkit-playsinline=”true” /这个属性是ios 10中设置可以让视频在小窗内播放,即不全屏播放/
- playsinline=”true” /IOS微信浏览器支持小窗内播放/
- x-webkit-airplay=”allow” /使此视频支持ios的AirPlay功能/
- x5-video-player-type=”h5” /启用H5播放器,是wechat安卓版特性/
- x5-video-player-fullscreen=”true” /全屏设置,设置为 true 是防止横屏/>
- x5-video-orientation=”portraint” /播放器支付的方向,landscape横屏,portraint竖屏,默认值为竖屏/
遇到的问题:
- 自动播放:很多设备是无效的,需要手动点击播放;
- 静音:很多时候不设置静音也会默认静音播放,需要用户手动交互一下。
- ios解码问题:我们的视频是mp4格式,但是部分视频在ios不播放,调研发现是ios对h.264的支持不完善,压缩比较高的时候无法播放。
- 层级问题:一些浏览器会将video置于最顶层,上面遮挡的元素会失效。

左图是期望,以及在主流浏览器展示效果,右图是在一些系统浏览器、UC浏览器等展示效果。
后两个问题比较严重,因此改用JSMpeg播放。
JSMpeg方案
参考文章:https://segmentfault.com/a/1190000040622805?utm_source=sf-similar-article
使用JSMpeg,首先需要用FFMpeg将视频转换为ts格式。然后使用如下:
1 | <script type="text/javascript" src="https://jsmpeg.com/jsmpeg.min.js"></script> |
1 | <template> |
JSMpeg是先拿到视频内容进行解析视频和音频,然后用canvas去逐帧针的画出来,同时播放声音。因此上面video的不同设备表现就统一了,也没有层级问题,自动播放也没有问题。部分设备可能还是要点一下才有声音,因为声音还是调用的设备能力。
JSMpeg的缺点是,不像video标签一样有控制条盒精细的操作,不能前进后退。我们用JSMpeg的场景就是正常的播放。这里静音也是,不解析音频,中途无法再打开声音。
另外,JSMpeg是先用ajax请求资源,因此存在跨域问题,需要视频文件和页面在同一个域名,或者视频所在服务器允许跨域。
对比
| 原生video标签 | JSMpeg |
|---|---|
| + 可以显示控制条进行操作; + 无需引入额外文件 |
+ canvas无兼容问题,各个设备表现基本一致,自动播放和静音播放等都正常(部分设备需要点一下才有声音); + 可以分块加载数据,加载体验更好; |
| + 自动播放部分设备不生效 + 声音需要用户交互 + ios不支持部分mp4压缩比 + 不同浏览器,video展现不同 + 部分浏览器video层级最高,无法控制 |
+ 不可精细控制; + 需要引入额外的js; + 视频文件需要先转换为ts格式; + 请求资源需要解决跨域问题 |
可以看到,二者各有自己的优缺点,像是做一些在线视频播放功能,video更合适一些,方便用户操作,可以前进后退、投屏等,看需求可以进一步引入一些js库操作video。而做一些活动页,插入一些广告视频,无需用户操控视频,用JSMpeg更合适一些,样式可控。
JSMpeg兼容问题
当ts文件和html文件在一起时,不存在跨域问题,播放也正常。但是当ts文件放在oss上,并设置了允许跨域,部分手机请求正常但是不播放。如小米手机用支付宝扫码时,已经iphone12、iphone13手机各种浏览器环境。
开始怀疑是视频的问题,修改各种视频参数去试验,还是不行。换成相对路径或者同一个域名就可以。确认应该是服务器问题,并且我们用竞品服务器的ts链接,各个手机播放都正常。
这里我们用的阿里云oss,看了下设置都没问题。换了一个思路来解决。
写一个html文件,通过url接受视频地址参数,执行JSMpeg播放。然后把这个文件和视频文件放在同一个oss。在原先的页面,视频播放位置放一个iframe。测试iframe方案各个手机播放正常。