前言

前不久抽空对目前比较火的视频直播,做了下研究与探索,了解其整体实现流程,以及探讨移动端HTML5直播可行性方案。

发现目前 WEB 上主流的视频直播方案有 HLS 和 RTMP,移动 WEB 端目前以 HLS 为主(HLS存在延迟性问题,也可以借助 video.js 采用RTMP),PC端则以 RTMP 为主实时性较好,接下来将围绕这两种视频流协议来展开H5直播主题分享。

一、视频流协议HLS与RTMP

1. HTTP Live Streaming

HTTP Live Streaming(简称 HLS)是一个基于 HTTP 的视频流协议,由 Apple 公司实现,Mac OS 上的 QuickTime、Safari 以及 iOS 上的 Safari 都能很好的支持 HLS,高版本 Android 也增加了对 HLS 的支持。一些常见的客户端如:MPlayerX、VLC 也都支持 HLS 协议。
HLS 协议基于 HTTP,而一个提供 HLS 的服务器需要做两件事:

  1. 编码:以 H.263 格式对图像进行编码,以 MP3 或者 HE-AAC 对声音进行编码,最终打包到 MPEG-2 TS(Transport Stream)容器之中;
  2. 分割:把编码好的 TS 文件等长切分成后缀为 ts 的小文件,并生成一个 .m3u8 的纯文本索引文件;

浏览器使用的是 m3u8 文件。m3u8 跟音频列表格式 m3u 很像,可以简单的认为 m3u8 就是包含多个 ts 文件的播放列表。播放器按顺序逐个播放,全部放完再请求一下 m3u8 文件,获得包含最新 ts 文件的播放列表继续播,周而复始。整个直播过程就是依靠一个不断更新的 m3u8 和一堆小的 ts 文件组成,m3u8 必须动态更新,ts 可以走 CDN。一个典型的 m3u8 文件格式如下:

#EXTM3U

#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=200000
gear1/prog_index.m3u8

#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=311111
gear2/prog_index.m3u8

#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=484444
gear3/prog_index.m3u8

#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=737777
gear4/prog_index.m3u8

可以看到 HLS 协议本质还是一个个的 HTTP 请求 / 响应,所以适应性很好,不会受到防火墙影响。但它也有一个致命的弱点:延迟现象非常明显。如果每个 ts 按照 5 秒来切分,一个 m3u8 放 6 个 ts 索引,那么至少就会带来 30 秒的延迟。如果减少每个 ts 的长度,减少 m3u8 中的索引数,延时确实会减少,但会带来更频繁的缓冲,对服务端的请求压力也会成倍增加。所以只能根据实际情况找到一个折中的点。

对于支持 HLS 的浏览器来说,直接这样写就能播放了:

<video src=”./bipbopall.m3u8″ height=”300″ width=”400″  preload=”auto” autoplay=”autoplay” loop=”loop” webkit-playsinline=”true”></video>

注意:HLS 在 PC 端仅支持safari浏览器,类似chrome浏览器使用HTML5 video
标签无法播放 m3u8 格式,可直接采用网上一些比较成熟的方案,如:sewise-playerMediaElementvideojs-contrib-hlsjwplayer

2. Real Time Messaging Protocol

Real Time Messaging Protocol(简称 RTMP)是 Macromedia 开发的一套视频直播协议,现在属于 Adobe。这套方案需要搭建专门的 RTMP 流媒体服务如 Adobe Media Server,并且在浏览器中只能使用 Flash 实现播放器。它的实时性非常好,延迟很小,但无法支持移动端 WEB 播放是它的硬伤。
虽然无法在iOS的H5页面播放,但是对于iOS原生应用是可以自己写解码去解析的, RTMP 延迟低、实时性较好。
浏览器端,HTML5 video
标签无法播放 RTMP 协议的视频,可以通过 video.js 来实现。

<link href=“http://vjs.zencdn.net/5.8.8/video-js.css” rel=“stylesheet”>
<video id=“example_video_1″ class=“video-js vjs-default-skin” controls preload=“auto” width=“640” height=“264” loop=“loop” webkit-playsinline>
<source src=“rtmp://10.14.221.17:1935/rtmplive/home” type=‘rtmp/flv’>
</video>
<script src=“http://vjs.zencdn.net/5.8.8/video.js”></script>
<script>
videojs.options.flash.swf = ‘video.swf’;
videojs(‘example_video_1′).ready(function() {
this.play();
});
</script>

3. 视频流协议HLS与RTMP对比

二、直播形式

目前直播展示形式,通常以YY直播、映客直播这种页面居多,可以看到其结构可以分成三层:
① 背景视频层
② 关注、评论模块
③ 点赞动画

而现行H5类似直播页面,实现技术难点不大,其可以通过实现方式分为:
① 底部视频背景使用video视频标签实现播放
② 关注、评论模块利用 WebScoket 来实时发送和接收新的消息通过DOM 和 CSS3 实现
③ 点赞利用 CSS3 动画

了解完直播形式之后,接下来整体了解直播流程。
三、直播整体流程
直播整体流程大致可分为:

  • 视频采集端:可以是电脑上的音视频输入设备、或手机端的摄像头、或麦克风,目前以移动端手机视频为主。
  • 直播流视频服务端:一台Nginx服务器,采集视频录制端传输的视频流(H264/ACC编码),由服务器端进行解析编码,推送RTMP/HLS格式视频流至视频播放端。
  • 视频播放端:可以是电脑上的播放器(QuickTime Player、VLC),手机端的native播放器,还有就是 H5 的video标签等,目前还是以手机端的native播放器为主。

(web前端学习交流群:328058344 禁止闲聊,非喜勿进!)

四、H5 录制视频

对于H5视频录制,可以使用强大的 webRTC (Web Real-Time Communication)是一个支持网页浏览器进行实时语音对话或视频对话的技术,缺点是只在 PC 的 Chrome 上支持较好,移动端支持不太理想。

  1. 使用 webRTC 录制视频基本流程
    ① 调用 window.navigator.webkitGetUserMedia()
    获取用户的PC摄像头视频数据。
    ② 将获取到视频流数据转换成 window.webkitRTCPeerConnection
    (一种视频流数据格式)。
    ③ 利用 WebScoket
    将视频流数据传输到服务端。

注意:


虽然Google一直在推WebRTC,目前已有不少成型的产品出现,但是大部分移动端的浏览器还不支持 webRTC(最新iOS 10.0也不支持),所以真正的视频录制还是要靠客户端(iOS,Android)来实现,效果会好一些。

WebRTC支持度
  1. iOS原生应用调用摄像头录制视频流程
    ① 音视频的采集,利用AVCaptureSession和AVCaptureDevice可以采集到原始的音视频数据流。
    ② 对视频进行H264编码,对音频进行AAC编码,在iOS中分别有已经封装好的编码库(x264编码faac编码ffmpeg编码)来实现对音视频的编码。
    ③ 对编码后的音、视频数据进行组装封包。
    ④ 建立RTMP连接并上推到服务端。

五、搭建Nginx+Rtmp直播流服务

  1. 安装nginx、nginx-rtmp-module
    ① 先clone nginx项目到本地:
brew tap homebrew/nginx

② 执行安装nginx-rtmp-module

brew install nginx-full –with-rtmp-module

2. nginx.conf配置文件,配置RTMP、HLS

查找到nginx.conf配置文件(路径/usr/local/etc/nginx/nginx.conf),配置RTMP、HLS。

① 在http节点之前添加 rtmp 的配置内容:

② 在http中添加 hls 的配置

3. 重启nginx服务

重启nginx服务,浏览器中输入 http://localhost:8080,是否出现欢迎界面确定nginx重启成功。

nginx -s reload

六、直播流转换格式、编码推流

当服务器端接收到采集视频录制端传输过来的视频流时,需要对其进行解析编码,推送RTMP/HLS格式视频流至视频播放端。通常使用的常见编码库方案,如x264编码faac编码ffmpeg编码等。
鉴于 FFmpeg 工具集合了多种音频、视频格式编码,我们可以优先选用FFmpeg进行转换格式、编码推流。

1.安装 FFmpeg 工具

brew install ffmpeg

2.推流MP4文件

视频文件地址:/Users/gao/Desktop/video/test.mp4
推流拉流地址:rtmp://localhost:1935/rtmplive/homertmp://localhost:1935/rtmplive/home

//RTMP 协议流
ffmpeg -re -i /Users/gao/Desktop/video/test.mp4 -vcodec libx264 -acodec aac -f flv rtmp://10.14.221.17:1935/rtmplive/home
//HLS 协议流
ffmpeg -re -i /Users/gao/Desktop/video/test.mp4 -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -q 10 rtmp://10.14.221.17:1935/hls/test

注意:
当我们进行推流之后,可以安装VLC、ffplay(支持rtmp协议的视频播放器)本地拉流进行演示
3.FFmpeg推流命令
① 视频文件进行直播

ffmpeg -re -i /Users/gao/Desktop/video/test.mp4 -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -q 10 rtmp://192.168.1.101:1935/hls/test
ffmpeg -re -i /Users/gao/Desktop/video/test.mp4 -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -q 10 rtmp://10.14.221.17:1935/hls/test

② 推流摄像头+桌面+麦克风录制进行直播

ffmpeg -f avfoundation -framerate 30 -i “1:0″ \-f avfoundation -framerate 30 -video_size 640x480 -i “0” \-c:v libx264 -preset ultrafast \-filter_complex ‘overlay=main_w-overlay_w-10:main_h-overlay_h-10′ -acodec libmp3lame -ar 44100 -ac 1 -f flv rtmp://192.168.1.101:1935/hls/test

更多命令,请参考:
FFmpeg处理RTMP流媒体的命令大全
FFmpeg常用推流命令

七、H5 直播视频播放

移动端iOS和 Android 都天然支持HLS协议,做好视频采集端、视频流推流服务之后,便可以直接在H5页面配置 video 标签播放直播视频。

<video controls preload=“auto” autoplay=“autoplay” loop=“loop” webkit-playsinline>
<source src=“http://10.14.221.8/hls/test.m3u8″ type=“application/vnd.apple.mpegurl” />
<p class=“warning”>Your browser does not support HTML5 video.</p>
</video>

八、总结

本文从视频采集上传,服务器处理视频推流,以及H5页面播放直播视频一整套流程,具体阐述了直播实现原理,实现过程中会遇到很多性能优化问题。

① H5 HLS 限制必须是H264+AAC编码。
② H5 HLS 播放卡顿问题,server 端可以做好分片策略,将 ts 文件放在 CDN 上,前端可尽量做到 DNS 缓存等。
③ H5 直播为了达到更好的实时互动,也可以采用RTMP协议,通过video.js
实现播放。

前端开发:H5直播起航的更多相关文章

  1. h5直播开发之旅总结

    前言 关于直播,有很多相关技术文章,这里不多说. 作为前端,我们比较关心我们所需要的. 直播的大致流程: APP端调用摄像头 -> 拍摄视频 -> 实时上传视频 -> 服务器端获取视 ...

  2. 用vue开发一个app(4,一个久等了的文章)H5直播平台登录注册(1)

    我上一篇关于vue的文章和这一篇时间隔了有点久了.最近终于写完了. 因为我一直想写个有点实绩的东西,而不是随便写一个教程一样东西.结合最近在项目中学到的经验和我的一点创意. 首先介绍下这是个什么! H ...

  3. EasyNVR H5直播流媒体解决方案前端构建之:如何播放自动适配RTMP/HLS直播播放

    之前在进行EasyNVR多屏开发的时候,由于多屏功能不需要在手机端展示出来(pc多播放为RTMP,手机端播放为HLS),因此只注意到了引用videojs来进行rtmp的播放.由于不同项目需求不同,对h ...

  4. EasyNVR网页H5无插件播放摄像机视频功能二次开发之直播通道接口保活示例代码

    背景需求 随着雪亮工程.明厨亮灶.手机看店.智慧幼儿园监控等行业开始将传统的安防摄像头进行互联网.微信直播,我们知道摄像头直播的春天了.将安防摄像头或NVR上的视频流转成互联网直播常用的RTMP.HT ...

  5. 基于node.js 的 websocket的移动端H5直播开发

    这一篇介绍一下基于node.js 的 websocket的移动端H5直播开发, 下载文章底部的源码,我是用vscode打开, 首先在第一个终端运行 npm run http-server 这个指令是运 ...

  6. 学h5前端开发前必知的三大流行趋势

    学h5前端开发前必知的三大流行趋势 随着互联网时代的飞速发展,各种互联网的Web应用程序层出不穷,很多人对于HTML5前端开发的过程充满了好奇,但是却没有了解到前端开发的未来发展趋势.下面,云慧学院专 ...

  7. H5直播避坑指南

    本文来自"小时光茶社(Tech Teahouse)"公众号 作者简介: 文赫,2015年加入腾讯,作为前端开发工程师参与过手Q游戏公会,游戏中心,企鹅电竞等项目,具有丰富的移动端开 ...

  8. h5直播

    直播开发之旅 ① 状态控制: 目前我们先考虑直播的三种状态: 直播前,直播中,结束. 针对每个状态我们肯定会有不同的显示,这三种状态可以是三个页面,相互切换,或者一个页面,控制页面相关隐藏和显示. 可 ...

  9. HTML5视频直播及H5直播扫盲

    章来源:http://geek.csdn.net/news/detail/95188 分享内容简介: 目前视频直播,尤其是移动端的视频直播已经火到不行了,基本上各大互联网公司都有了自己的直播产品,所以 ...

随机推荐

  1. Linux下Birt、JTreeChart中文乱码问题解决办法

    Linux下JTreeChart,Birt等报表工具显示中文乱码解决 1) 现象: 在Windows上生成的报表图片展示正常,但是在Linux上显示(怪异的小方块“口”): 2)问题定位: 这是lin ...

  2. MongoDB 复制篇

    mongoDB 复制篇 复制集简介 Mongodb复制集由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,Mongodb Driver(客户端)的所有数据都写 ...

  3. .NetCore之下载文件

    本篇将和大家分享的丝.NetCore下载文件,常见的下载有两种:A标签直接指向下载文件地址和post或get请求后台输出文件流的方式,本篇也将围绕这两种来分享:如果对您有好的帮助,请多多支持. 允许站 ...

  4. 关于MySQL 事务,视图,索引,数据库备份,恢复

      /*创建数据库*/ CREATE DATABASE `mybank`;/*创建表*/USE mybank;CREATE TABLE `bank`(    `customerName` CHAR(1 ...

  5. latex使用笔记

    1.图片自动浮动到最后一页单独占用一页 将表格中的 \begin{table}[h]\end{table} 改成 \begin{table}[H]\end{table} 即可 2.公式内容中字母之间空 ...

  6. ArrayList ConcurrentModificationException

    1.ConcurrentModificationException ConcurrentModificationException 出现在使用 ForEach遍历,迭代器遍历的同时,进行删除,增加出现 ...

  7. JAVA 反射(1)

    getDeclaredField是可以获取一个类的所有字段. getField只能获取类的public 字段.

  8. 【Spring】高级装配

    前言 前面讲解了bean的核心装配技术,其可应付很多中装配情况,但Spring提供了高级装配技术,以此实现更为高级的bean装配功能. 高级装配 配置profile bean 将所有不同bean定义放 ...

  9. 2008-2009 ACM-ICPC, NEERC, Southern Subregional ContestF

    Problem F. Text Editor Input file: stdin Output file: stdout Time limit: 1 second Memory limit: 64 m ...

  10. http://codeforces.com/problemset/problem/545/D

    D. Queue time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...