实现浏览器支持各种视频格式文件播放
背景
浏览器支持的视频格式有限。而ffmpeg有很强的格式转换功能。那我们能不能通过ffmpeg把不支持的视频转成浏览器可以支持的视频呢?
方案
要实现以上方案要解决几个问题:
- 如何实时获取ffmpeg的转换后的数据
- 如何将数据实时传给浏览器
- 浏览器收到数据后如何播放
如何实时获取ffmpeg的转换后的数据
正常我们通过 ffmpeg 是可以将一个视频文件转换成另一种视频文件。
如下是将一个其他编码的mp4文件编码格式进行转换
ffmpeg -i 1.mp4 -c:v libx264 -f mp4 mp4-264.mp4
但我们怎么通过程序调用ffmpeg来获取转换后的数据呢。
ffmpeg 提供了一个pipe的功能可以将数据传给标准输入输出
nodejs 可以通过spawn来调用ffmpeg获取输出流
let ffmpeg = spawn('ffmpeg', //ffmpeg 自己从官网上载,改成自己路径,或配置成全局变量['-i', 'html/1.mp4','-c:v', 'libx264', // 如果原视频已经是264格式可以不转'-movflags', 'frag_keyframe+empty_moov+default_base_moof', // 转成fragment mp4'-f', 'mp4','pipe:1' // 输出流]);ffmpeg.stdout.on('data', chunk=>{console.log("data")})
如何将数据实时传给浏览器
现在转换后的视频数据拿到了,怎么将数据传给浏览器呢。
浏览器实时数据的传输一般想到的是用websocket.
我这边想到的是用两条websocket. 一条传输控制命令,一条传输视频数据。
websocket 支持二进制数据传输和文本数据传输。这里控制命令用文本类型。视频数据用的是二进制数据类型。
ffmpeg.stdout.on('data', chunk=>{console.log("data")//转码后的数据用二制制传输ws.send(chunk, {binary: true, mask: false});})
浏览器收到数据后如何播放
视频流的播放这里用到了MediaSourceExtension(MSE). https://developer.mozilla.org/en-US/docs/Web/API/MediaSource
需要注意的是,MSE只支持 fragmented mp4 用ffmpeg指定转framented mp4参数
-movflags frag_keyframe+empty_moov+default_base_moof // 转成fragment mp4
let video = document.querySelector('video');
let mediasource = new MediaSource();
video.src = URL.createObjectURL(mediasource);
可将websocket接收到数据传给Mediasource
ws.onmessage = (event) => {sourceBuffer.appendBuffer(event.data);};
由于播放速度和转码的数据不一致,所以要根据播放进度来控制进度。这里用到刚提到的控制websocket, 通过监听播放进度和缓存的时间来判断是否要从后端拉取数据.
function getData() {controlWs.send("get")}// updateend会在往MediaSource放数据后调用, 可以读取到缓存时间
sourceBuffer.addEventListener('updateend', () => {let buffered = sourceBuffer.bufferedfor (let i = 0; i < buffered.length; i++) {bufferTime = buffered.end(i); // 缓存了多少时间的数据}/***readyState* 0 = HAVE_NOTHING - 没有关于音频/视频是否就绪的信息1 = HAVE_METADATA - 关于音频/视频就绪的元数据2 = HAVE_CURRENT_DATA - 关于当前播放位置的数据是可用的,但没有足够的数据来播放下一帧/毫秒3 = HAVE_FUTURE_DATA - 当前及至少下一帧的数据是可用的4 = HAVE_ENOUGH_DATA - 可用数据足以开始播放* */if (video.readyState !== 4) {// 数据不够拉数据getData();}});video.addEventListener('timeupdate', (e)=>{console.log("timeupdate: " , bufferTime , video.currentTime, video.readyState);// 缓存10秒if (bufferTime - video.currentTime < 10) {getData()}})
以上依赖ffmpeg强大的转码能力,可以将各种视频格式转成浏览器可识别的格式进行播放
完整代码
https://gitee.com/morris-mao/websocket-video
实现浏览器支持各种视频格式文件播放相关推荐
- video视频相关问题:火狐浏览器报错“没有找到支持的视频格式和MIME类型”
1.需求:上传 .mp4 格式的视频到服务器,然后获取展示到前台页面. 2.遇到的问题:在谷歌浏览器上能正常显示视频,但是在火狐浏览器不能显示视频,提示:"没有找到支持的视频格式和MIME类 ...
- 如何在Windows 10上播放不受支持的视频格式
Windows apps like Movies & TV and Windows Media Player allow the playback of certain types of vi ...
- 解决微信视频号 当前浏览器不支持此视频格式 的错误消息
我试图用电脑端的微信视频号助手,上传一个后缀为 mp4 的视频时,遇到如下错误消息:当前浏览器不支持此视频格式,建议上传 MP4 或 H.264 格式文件. 然而我能肯定,我是使用格式工厂这款软件,将 ...
- 暴风影音能播放html视频吗,暴风影音播放器支持哪些视频格式
暴风影音播放器是一款非常给力的视频播放器.该软件能够支持主流的视频格式,当然一些特殊的格式也基本支持,下面就和小编一起来看看到底都支持哪些格式吧! 暴风影音播放器支持哪些视频格式: 1.常规视频.DV ...
- 红米note3支持html,红米Note3支持什么视频格式?支持RMVB播放吗?
红米Note3支持什么视频格式 红米Note3支持MP4.M4V.MKV.XVID.ASF视频格式. 红米Note3的指纹识别对手的湿度也有要求,需要保持手指干燥,潮湿的话就可能导致无法识别.红米No ...
- 让linux 支持视频格式,配置 Nginx 支持 f4v视频格式播放
Nginx默认不支持f4v视频格式播放,解决方法为编辑mime.types文件,在video/mp4加上f4v即可 types { # Data interchange application/ato ...
- html 播放f4v,配置 nginx 支持 f4v视频格式播放
Nginx默认不支持f4v视频格式播放,解决方法为编辑mime.types文件,在video/mp4加上f4v即可types { # Data interchange application/atom ...
- iphone保存html视频格式,iPhone6支持什么视频格式?iPhone6支持RMVB播放吗?
iPhone6支持什么视频格式 iPhone6支持MP4,AVI,NAVI,DV-AVI,DIVX,MOV,ASF,WMV,RM,RMVB等视频格式. 关于iPhone6支持什么视频格式的疑问,下面将 ...
- Html 播放 mp4格式视频提示 没有发现支持的视频格式和mime类型
转自原文 Html 播放 mp4格式视频提示 没有发现支持的视频格式和mime类型 播放mp4格式的时候提示 Html 播放 mp4格式视频提示 没有发现支持的视频格式和mime类型 原因是在IIS中 ...
最新文章
- Microsoft Surface Toolkit Beta 版发布
- 自然语言处理(NLP)之使用TF-IDF模型计算文本相似度
- merge r语言daframe_R语言读取多个excel文件后合并:rbind/merge/cmd合并
- 浅析网站设计风格对网站建设的重要性
- 五种网络管理技巧优化网络办公环境
- Python连接Mysql数据库SQL注入问题的解决
- marbin mysql_跨浏览器图像灰度(grayscale)解决方案
- 操作系统实验报告12:线程2
- ContactsContract.Contacts与ContactsContract.CommonDataKinds.Phone的区别
- 重新构想原子化 CSS
- 深入浅出分布式文件系统MogileFS集群
- 前端学习(2249)注册 创建 拉取
- grep 和 sed:linux经常使用工具 amp; 基本正則表達式
- python图像处理模块_Python图像处理库PIL的ImageEnhance模块使用介绍
- Caffe学习:使用pycaffe生成mean_file.py文件
- c语言打印%-6llu,C语言-输出指定个数的质数
- ydisk安卓版本_mydisktest
- J6412四网口迷你主机折腾虚拟机教程
- 房天下二手交易平台房源数据采集
- Redis——狂聊教程笔记