当前位置: 首页 > news >正文

在HTML5上开发音视频应用的五种思路

问题背景:

无论是实时视频监控还是直播点播等应用场景,最起码的一个操作就是播放视频。其中最基本的思路就是利用OS的API在PC开发桌面应用、在移动端开发Native App,目前这种技术已经成熟,大厂小厂都是这么做的,但是缺点也很明显:开发比较费时费力,需要IOS开发一遍再去Android开发一遍。特别对于一些非刚性需求比如用户家里有一两个监控摄像头,一个礼拜也不会打开看几次,你却要他下载和安装一个APP进行操作,用户安装意愿其实非常低。

随着前端摄像头输出音视频格式逐渐标准化和Web前端技术的迅速发展,我们打算探索在Web浏览器、微信上开发一些轻量级视频监控应用,虽然在Web上开发音视频应用也有很多方案,但是这些技术也都有优缺点和不同的适用场景,本文就是想总结下目前有哪些成熟的解决方案?这些方案的底层原理是什么?其次优缺点是什么?文章最后放了一些参考链接和Git地址,供大家研究和学习,由于本人并不是前端开发人员,勘误地方还望大家多多指正。


实现思路:

方案1:插件化方案

简介:

自从浏览器发明以来,想在Web浏览器上播放视频,基本都是插件化的解决方案,特别是Adobe的Flash技术将插件化技术普及到各种浏览器。插件化的技术基本分三类:基于IE的Active方案、基于Chome的NPAPI接口和基于Flash插件。但是这些插件化方案逐渐都要淘汰了,主要原因如下:

a. 微软IE式微,市场份额不断下降,微软已经在2015年宣布放弃IE浏览器,现在最新的微软浏览器Microsoft Edge将从EdgeHTML内核迁移为Chromium内核。

b. Chrome上的NPAPI也已经宣布放弃,目前要做需要基于PPAPI /NaCl接口,而且只能针对这款浏览器实现。

c. Flash这种技术也在2020年寿终正寝,所有浏览器就默认禁止在上面跑Flash插件了;

所以综上来看,想在Web上利用插件化播放视频这条路在已经走不通了,这种技术由于各种问题的确该抛弃了,作为程序员我们能做的就是给这种技术的淘汰添一把土,果断抛弃和转身吧。

演示效果:

方案2:跨平台的HLS\DASH方案

简介:

HLS是Apple首先提出的流媒体分发协议,目前在苹果家族的整个产品都得到了比较好的支持,后来谷歌在Chrome浏览器和移动端浏览器也进行了原生支持,所以目前无论你是在PC还是移动端的浏览器基本都原生支持HLS协议进行播放视频,算是一个在移动端比较好的跨平台方案,同时微信内嵌的浏览器也都是原生支持的。

缺点

延时比较大,由于HLS协议本身的切片原理,基本延迟都在10秒+,这对于一些低延时场景非常不友好,虽然HLS也在努力优化,但是想达到秒级延迟还是不现实的。

微信小程序演示效果:

方案3:基于HTML5 Video和Audio的MSE方案

MSE即Media Source Extensions是一个W3C草案,其中桌面对MSE的支持比较好,移动端支持缓慢。MSE扩展了HTML5的Video和Audio标签能力,允许你通过JS来从服务端拉流提供到HTML5的Video和Audio标签进行播放。

MSE在各个浏览器的支持情况如下,目前看在PC端的浏览器支持比较友好,但在移动端浏览器支持这个接口目前还处于刚开始。

MSE目前支持的视频封装格式是MP4,支持的视频编码是H.264和MPEG4,支持的音频编码是AAC和MP3,目前编码层的东西摄像机都支持比较友好,问题不大。封装格式的处理目前要么就是从服务端拉裸流过来,在Web前端合成MP4片段进行播放,要么在服务端提前转封装好直接喂给MSE接口,同时由于RTMP协议在CDN场景的大量使用,所以Web前端应该还支持解析FLV然后转成MP4片段,于是就产生了以下技术细类:

3.1方案:HTTP+FLV

简介:

服务端经摄像头拉流转成FLV,然后客户端过来拉流即可,拉过来的流解封装下FLV然后转成MP4片段,再喂给MSE即可。这个事情现在有个开源项目就是bilibili的flv.js已经帮你实现了,你直接利用这个开源项目简单改改,就基本支持起来了,我们已经在用。

缺点:

目前移动端的微信或者Chrome76我已经测试过,开始支持了,但是IOS的Safari浏览器没有支持,所以这个方案暂时在移动端完全支持起来有困难。

演示:

1.PC Web展示效果:

2. 手机微信7.0.4和Android Chrome76演示效果:

3.2方案:WebSocket+FLV

简介:

方案和3.1目前差不多,就是将拉流协议换成Web的原生WebSocket协议而已,拉过来的FLV码流还是可以靠flv.js来进行转封装为Mp4片段,喂给MSE即可,相应的MP4片段也可以在服务端生成,然后直接用WebSocket拉过来即可,也就是3.3方案。

3.3方案:WebSocket+MP4

缺点:

缺点就是要在服务端提前生成好MP4片段,转封装这块工作服务端需要处理好。

3.4方案:WebSocket+RTSP+H.264数据

简介:

因为现在视频监控类设备目前支持最好的拉流协议基本就是RTSP协议,基本都进行了标准支持,因为视频监控领域有一个国际标准就是ONVIF标准,这个标准使用的拉流协议就是RTSP,所以视频监控不支持RTSP,就无法支持ONVIF,在国际就没有市场。

所以要是Web能直接通过RTSP拉流,那就非常友好,想做到这点比较难,因为Web的W3C标准就不支持RTSP协议,曲线救国的方案就是将RTSP协议放到Websocket协议里面进行透传,然后在服务端做一个Websocket到RTSP协议的代理转换协议,这样就可以在Web支持RTSP协议了,对于视频监控领域用户比较友好,一看就是熟悉的味道,相同的道理也可以在Web前端支持RTMP协议,基本的原理如下:

缺点:

需要服务端做相应的协议转换代理,拉过来的码流Web还是要进行相应的转成MP4片段,这些都是不小的开发工作量;

这个也有相应的开源项目,其中Web这边有个html5_rtsp_player开源项目,实现了RTSP客户端功能,你可以利用此框架直接播放RTSP直播流。此播放器把RTP协议下的H264/AAC再转换为ISO BMFF供video元素使用。Streamedian支持Chrome 23+, FireFox 42+, Edge 13+,以及Android 5.0+。不支持iOS和IE。

演示效果如下:

 

 

方案4:WebRTC方案

简介:

WebRTC是一整套API,其中一部分供Web开发者使用,另外一部分属于要求浏览器厂商实现的接口规范。WebRTC解决诸如客户端流媒体发送、点对点通信、视频编码等问题。桌面浏览器对WebRTC的支持较好,WebRTC也很容易和Native应用集成。

WebRTC实现了浏览器P2P的实时通信,其中可以通过调用相应的Web API采集视频进行推流,如果放到视频监控,我们可以把这一段在嵌入式摄像头上实现,将摄像机的编码视频数据采集出来,然后直接发送出去即用摄像头模拟P2P的推流端,另外一端在Web浏览器上用相应接口解码和渲染。我们在自家摄像头预研过这套方案,目前看是可以的。延时非常小,播放非常稳定,同时WebRTC目前在跨平台方面支持比较好。

演示效果:

方案5:

WebSocket/HTTP + WebGL/Canvas2D + FFmpeg+WebAssembly

简介:

WebAssembly 是一种新的编码方式,可以在现代的网络浏览器中运行 - 它是一种低级的类汇编语言,具有紧凑的二进制格式,并为其他语言提供一个编译目标,以便它们可以在 Web 上运行。它也被设计为可以与 JavaScript 共存,允许两者一起工作。近几年已经被各主流浏览器所广泛支持,支持情况:

它的大概原理:

利用这种技术可以将C/C++库进行前端移植,比如WebAssembly 技术可以帮我们把 FFmpeg 运行在浏览器里,其实就是通过 Emscripten 工具把我们按需定制、裁剪后的 FFmpeg 编译成 Wasm 文件,加载进网页,与 JavaScript 代码进行交互。

这样Wasm 用于从 JavaScript 接收WebSocket或者HTTP-FLV 直播流数据,并对这些数据利用FFmpeg进行解码,然后通过回调的方式把解码后的 YUV 视频数据和 PCM 音频数据传送回 JavaScript,并最终通过 WebGL 在 Canvas 上绘制视频画面,同时通过 Web Audio API 播放音频。

缺点:

前端消耗性能还是比较大,Web前端播放H265的1080P视频还是比较吃力的,同时想在前端播放多路视频基本是不现实的,所以这个应用场景还是局限在特殊的应用场景,不能通用。

我们当时的实践是利用这种技术在Web界面播放鱼眼摄像头视频,这种摄像头视频是几路合成的,如果借助原始Web接口是无法播放的,所以播放器解码必须是我们自己C++写的,然后借助WebAssembly技术允许js接口调用解码播放。

效果演示:


总结:

目前在web浏览器上想播放音视频主要的技术大类就是上面四种:

1. 插件化的技术虽然可以实现各个浏览器的播放音视频,但是即将淘汰;

2. HLS/DASH浏览器虽然原生支持,跨平台比较好,但是延时太大,对于低延时领域不适用;

3. 基于MSE的技术,虽然可以大大降低延时,适用直播和点播,但是苹果系列产品目前还未完全支持,只能部分使用;

4. 基于WebRTC技术,非常适用于实时视频,但是开发量比较大,对于视频监控等低延时交互领域有点杀鸡焉用牛刀的感觉,而且技术处于快速发展阶段,很多还不成熟,对于小公司有一定的门槛;

5. 基于WebAssembly将C/C++音视频解码库前端移植化,这个在一些特殊应用场景可以使用比如浏览器要播放H265音视频,但是弊端是前端跑起来比较重,渲染不了几路视频,性能优化还有待提升,但是是可以突破浏览器和操作系统接口的隔阂。

所以目前来看想在Web上做音视频操作,浏览器的原生支持还远远不够,相比较开发APP还是缺乏一定的灵活性,不仅有一定的限制而且需要兼容处理的事情非常多,想一招解决你的需求还是有困难,所以还是需要上述几种技术综合搭配使用来解决Web播放音视频需求。不过后面相信浏览器会在这方面突破,毕竟5G要来了,浏览器厂商会加紧布局。


本篇文章参考网址和项目:

https://github.com/ty6815 

https://github.com/gwuhaolin/blog

https://github.com/Streamedian/html5_rtsp_player

https://github.com/bilibili/flv.js

https://mp.weixin.qq.com/s/EC8Yd74HEoIO2QxJe8-iNQ

https://blog.csdn.net/vn9PLgZvnPs1522s82g/article/details/96405736

https://www.jianshu.com/p/1bfe4470349b

-End-


推荐阅读

Android MediaCodec 硬编码 H264 文件

快手高性能移动端多媒体引擎架构

相关文章:

  • 如何把微信打造成一个学习利器|微信阅读与笔记技巧
  • 「圣诞特辑」纯前端实现人脸识别自动佩戴圣诞帽
  • LearnOpenGL 源码在 MAC 上的编译与调试
  • 在 iOS 中使用 OpenGL ES 实现绘画板
  • 技术开发故事会连载
  • OpenGL ES 学习资源分享
  • 【音视频连载-001】基础学习篇- SDL 介绍以及工程配置
  • GLSL加载纹理颠倒的六种解决方案
  • 内存都没了,还能运行程序?
  • 比 SharedPreferences 更高效?微信 MMKV 源码解析
  • 【音视频连载-002】基础学习篇-SDL 创建窗口并显示颜色
  • 【音视频连载-003】基础学习篇-SDL 消息循环和事件响应
  • Android JNI 之 Bitmap 操作
  • 游戏中的角色是如何“动”起来的?
  • Android JNI 中的线程操作
  • (三)从jvm层面了解线程的启动和停止
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • Angular 2 DI - IoC DI - 1
  • AzureCon上微软宣布了哪些容器相关的重磅消息
  • Codepen 每日精选(2018-3-25)
  • download使用浅析
  • ES6 ...操作符
  • JavaScript 奇技淫巧
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • magento 货币换算
  • mongo索引构建
  • PHP面试之三:MySQL数据库
  • SpringCloud集成分布式事务LCN (一)
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • vue-router 实现分析
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 阿里云购买磁盘后挂载
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 半理解系列--Promise的进化史
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 分类模型——Logistics Regression
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 软件开发学习的5大技巧,你知道吗?
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 通过npm或yarn自动生成vue组件
  • [Shell 脚本] 备份网站文件至OSS服务(纯shell脚本无sdk) ...
  • MyCAT水平分库
  • ​iOS安全加固方法及实现
  • ###项目技术发展史
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • ()、[]、{}、(())、[[]]命令替换
  • (C++17) optional的使用
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (Redis使用系列) Springboot 整合Redisson 实现分布式锁 七
  • (一)u-boot-nand.bin的下载