Chrome浏览器支持播放.avi视频的探索

前言

最近碰到一个bug,客户上传的avi格式视频不能在Chrome浏览器播放,让支持播放。代码直接用的video标签播放,搜索一番了解到是浏览器本身不支持avi格式的播放,于是让后端在视频上传时将avi转为mp4保存,但是客户不满意,客户爸爸的话就是圣旨,就只能让前端想办法兼容一下。

探索思路

Chrome浏览器支持avi的播放,针对该问题,经过思考与搜索,得到了三种解决思路:

  • 播放器:代码中用的是video标签,而电脑自带的多媒体播放器就能打开.avi格式的视频,如果有支持播放avi格式的播放器依赖,我直接下载引入,简单快捷。
  • 格式转换:将avi格式转为浏览器支持播放的格式,如mp4格式,相当于把刚开始后端的工作放到前端,这样直接使用video标签即可。
  • 源码修改:chrome浏览器底层是用FFmpeg去解码播放的,底层代码配置项不包含avi格式,这也就是不兼容的原因。可以找到源码去添加配置项,重新编译,将编译好的文件替换旧文件,就能播放avi格式了。
    上述思路,果断去掉第三种,该方法自己的浏览器可以尝试一下,剩下两种我们一个个去尝试。

plyr播放器

播放器的思路是找到支持播放avi格式的播放器,先去npm用video+avi格式搜索了一下,搜索结果更多是转换格式的库,于是问了一下ai,提到了plry的库,该库是一个简洁功能强大的音频视频播放器,视频支持画中画、字幕等功能。选定好了库,写一个简单的demo看能不能播放avi格式。 新建一个html文档,用cdn方式引入plry,plry的样式也需要引入。

js 复制代码
   <link rel="stylesheet" href="https://cdn.plyr.io/3.7.8/plyr.css" />
   <script src="https://cdn.plyr.io/3.7.8/plyr.js"></script>

plry在网页端应用很简单,直接new一个对象去绑定video元素即可。

js 复制代码
    <video id="player" control> 
    <source src="./123.avi" type="video/avi"></source>
    </video>
     <script>
        const player = new Plyr('#player');
      </script>

字幕画中画等功能我们按照官方给出的配置项做对应的配置即可,这里我们就直接绑定不搞花里胡哨,打开页面,不能播放。

该样式要比原生video样式好看,但就是不支持播放avi格式,我就去搜了下issue,作者提到了是浏览器本身不支持,也就是思路三提到的。看来plyr只是对video标签进行了功能添加与样式修改,本质上没有对视频格式进行兼容出来。到此我觉得播放器大多应该是对功能的支持,具体格式还是受限于浏览器自身,只能尝试格式转换。

格式转换

将avi转为mp4肯定能兼容浏览器,问了下后端转换方法是使用FFmpeg相关的库,谷歌也是用的FFmpeg,前端转换看来也是要用FFmpeg,站内搜索了FFmpeg,有好几篇大佬介绍FFmpeg相关的文章,就决定使用ffmpeg.wasm,接下来开整。

格式转换播放思路很明确,借助库将avi格式转为mp4格式,然后用createObjectURL 创建一个url,用video去播放该url。该库不支持cdn方式引入,官网给出了解释: 我当时试的时候还有cdn引入的例子,也用cdn方式写了demo,运行不起来,现在文档直接取消并解释了,很好的团队。

该依赖有两大版本,具体的api跟node版本的支持有所区别,我们可以根据需要安装合适的版本。

  • 0.11x版本,该版本创建实例api为createFFmpeg
  • 0.12+版本,创建实例api为 new FFmpeg(),该版本node需要大于等于18.17.0
    详细对比可以查看官网文档,因为公司项目node版本达不到18以上,就安装了0.11x版本。
js 复制代码
   <template>
  <div>
    <video ref="videoRef" controls></video>
  </div>
</template>
<script setup lang="ts">
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'
import { ref, onMounted } from 'vue'
const videoRef = ref<HTMLVideoElement | null>(null)
const ffmpeg = createFFmpeg({ log: true })
const load = async () => {
  // 加载
  await ffmpeg.load()
  // 写入文件
  ffmpeg.FS(
    'writeFile',
    'test.avi',
    await fetchFile('/video/test.avi'),
  )
  // 执行 格式转换 命令
  await ffmpeg.run('-i', 'test.avi', 'test.mp4')
  // 读取mp4文件
  const data = ffmpeg.FS('readFile', 'test.mp4')
  //
  if (videoRef.value) {
    videoRef.value.src = URL.createObjectURL(
      new Blob([data.buffer], { type: 'video/mp4' }),
    )
  }
}
onMounted(() => {
  load()
})
</script>

ffmpeg加载过程要使用await ,等待所需资源加载完。运行完毕打开页面会有一个报错,SharedArrayBuffer is not defined,Chrome安全策略的变更导致这一错误,这个错误在60-91的版本不会存在。解决的办法也很简单,在vite.config,ts中添加给响应头添加两个属性。

js 复制代码
headers: {
        'Cross-Origin-Opener-Policy': 'same-origin',
        'Cross-Origin-Embedder-Policy': 'require-corp',
      },

再次运行等待一会,我们就能看到video加载出来视频了,在console页面也能看到转换过程。

该库实现的转换会比较慢,10M的视频转换了3分钟,这个结果客户肯定不满意。官网也提到了慢的问题,并建议使用mt多线程版本,但是多线程需要兼容SharedArrayBuffer 。除此之外,如果想要上线还要进行一些配置,具体操作可以看大佬的ffmpeg实现web在线转码播放,简单来说,ffmpeg.wasm在加载过程中会加载放到unpkg上的工具包,客户一般往往会有内网需求,所以需要配置。

总结

以上就是探索过程,最终实现效果不太理想,也勉强算是实现了,在这个过程中也学到了一些知识。如果客户不介意转换速度,可以尝试用ffmpeg.wasm库兼容avi视频的播放;如果浏览器版本支持多线程的话,可以用多线程加快转换过程。

相关推荐
玩电脑的辣条哥2 小时前
Python如何播放本地音乐并在web页面播放
开发语言·前端·python
ew452182 小时前
ElementUI表格表头自定义添加checkbox,点击选中样式不生效
前端·javascript·elementui
suibian52352 小时前
AI时代:前端开发的职业发展路径拓宽
前端·人工智能
Moon.92 小时前
el-table的hasChildren不生效?子级没数据还显示箭头号?树形数据无法展开和收缩
前端·vue.js·html
垚垚 Securify 前沿站2 小时前
深入了解 AppScan 工具的使用:筑牢 Web 应用安全防线
运维·前端·网络·安全·web安全·系统安全
工业甲酰苯胺5 小时前
Vue3 基础概念与环境搭建
前端·javascript·vue.js
mosquito_lover16 小时前
怎么把pyqt界面做的像web一样漂亮
前端·python·pyqt
柴柴的小记8 小时前
前端vue引入特殊字体不生效
前端·javascript·vue.js
柠檬豆腐脑9 小时前
从前端到全栈:新闻管理系统及多个应用端展示
前端·全栈
bin91539 小时前
DeepSeek 助力 Vue 开发:打造丝滑的颜色选择器(Color Picker)
前端·javascript·vue.js·ecmascript·deepseek