11月11, 2018

H5直播开发相关笔记

在慕课网的实战课里面,有一门:手把手带你入坑 H5+小程序直播开发。在此记录一下学习过程中的笔记。

大前端

alt

那个老师提及光会左边,在现在看来,还远远不够,必须要另外多学一门或者几门右边的领域才行。

我深以为然,现在前端要学的东西真的太多太多。学的越多,越感觉自己无知。

直播原理

alt

格式兼容

alt

协议

  • HLS协议
  • RTMP协议
  • HTTP-FLV协议

HLS协议

alt

我们可以用safari浏览器打开这个地址:http://live.streamingfast.net/osmflivech5.m3u8。

就可以看到它是一个实时直播(左下角可以看到),打开网络面板:

alt

m3u8

一个m3u8文件包含的也可以是多个子m3u8文件,这是就分为master playlist 和 media playlist。在master中,会根据网络状况设置好不同的m3u8文件。

m3u8文件共有三种类型:

  • 动态列表(live playlist)
  • 静态列表(event playlist)
  • 全量列表(vod playlist)

比较常见的是动态(像直播)和全量(像回放)。

alt

alt

全量相比动态的,就多了我圈出来的那两行。

解析ts的过程

通过找到PAT表,从PAT表中找出对应存在的节目id,按照这些id找到这些节目的PMT表,从中获取这些节目总的相对的媒体数据id,然后在通过这些id,从ts文件里找到这些文件的es数据。

alt

RTMP协议

  • RTMP是Real Time Messaging Protocol
  • 该协议基于TCP,是一个协议族,包括RTMP基本协议及RTMPT/RTMPS/RTMPE等多种变种
  • RTMP是一种设计用来进行实时数据通信的网络协议,主要用来在Flash、AIR平台和支持RTMP协议的流媒体/交互服务器之间进行音视频和数据通信

alt

HTTP-FLV协议

虽然hls简单好用, 但实时性较差,延时无法降低到10s以下, 这就产生了http-hlv协议,结合了hls http请求的特性和rtmp协议的低延时特性。没有了复杂的状态交互,开发难度也下降了很多。

alt

  1. 可以在一定程度上避免防火墙的干扰(例如,有的机房只允许80端口通过)
  2. 可以很好的兼容HTTP 302 跳转,做到灵活调度
  3. 可以使用HTTPS做加密通道
  4. 很好的支持移动端(Android, IOS)

深入video标签

H5播放器

alt

最最简单的用法是:

<video src="">

src里面放入地址即可,但要知道的是这个地址可以是虚拟的,比如慕课网的这个地址:

alt

video的属性和方法

alt

controlslist

通过它我们可以让控制条不显示全屏或者下载按钮啥的,用法如下:

<video src="./test.mp4" width="400" height="225" controls controlslist="nodownload nofullscreen"></video>

自动播放

需要注意的是:必须要静音才能自动播放

音量控制

需要注意的是:

<video id="_volume" src="./test.mp4" width="400" height="225" controls volume=“0.5”></video>

上面的代码并不能让音量变成一半,它需要通过js来控制才行。

var v = document.getElementById('_volume');
v.volume = 0.5;

播放时间设置

 var v = document.getElementById('video标签的ID');
v.currentTime = 60;// 单位:秒

播放地址的切换

var v = document.getElementById('video标签的ID');
setTimeout(function() {
    v.src = '新地址';
}, 2000);

备用地址

<video id="_source" controls poster="./poster.jpg" width="400" height="225">
  <source src="./test3.mp4" type="video/mp4">
  <source src="./test4.mp4" type="video/mp4">
  <source src="./test5.mp4" type="video/mp4">
  <source src="./test-2.mp4" type="video/mp4">
</video>

test3.mp4挂了的话,会去找test4.mp4,如果test4.mp4也挂了,会继续往下找test5.mp4

这里有一个问题是:我们如何做监控是哪个地址挂了?

其实很容易:

var v = document.getElementById('_source');
v.currentSrc // 得到没挂的那个源

然后去遍历video里面的source,当有匹配到时,说明那个视频之前的URL都挂了。

video的事件

alt

事件名 描述
onabort 在退出时运行的脚本
oncanplay 当文件就绪可以开始播放时运行的脚本(缓冲已足够开始时)
oncanplaythroug 当媒介能够无需因缓冲而停止即可播放至结尾时运行的脚本
ondurationchange 当媒介长度改变时运行的脚本
onemptied 当发生故障并且文件突然不可用时运行的脚本(比如连接意外断开时)
onended 当媒介已到达结尾时运行的脚本(可发送类似“感谢观看”之类的消息)
onerror 当在文件加载期间发生错误时运行的脚本
onloadeddata 当媒介数据已加载时运行的脚本
onloadedmetadata 当元数据(比如分辨率和时长)被加载时运行的脚本
onloadstart 在文件开始加载且未实际加载任何数据前运行的脚本
onpause 当媒介被用户或程序暂停时运行的脚本
onplay 当媒介已就绪可以开始播放时运行的脚本
onplaying 当媒介已开始播放时运行的脚本
onprogress 当浏览器正在获取媒介数据时运行的脚本
onratechange 每当回放速率改变时运行的脚本(比如当用户切换到慢动作或快进模式)
onreadystatechange 当就绪状态改变时运行的脚本(就绪状态监测媒介数据的状态)
onseeked 当 seeking 属性设置为 false(指示定位已结束)时运行的脚本
onseeking 当 seeking 属性设置为 true(指示定位是活动的)时运行的脚本
onstalled 在浏览器不论何种原因未能取回媒介数据时运行的脚本
onsuspend 在媒介数据完全加载之前不论何种原因终止取回媒介数据时运行的脚本
ontimeupdate 当播放位置改变时(比如当用户快进到媒介中一个不同的位置时)运行的脚本
onvolumechange 每当音量改变时(包括将音量设置为静音)时运行的脚本
onwaiting 当媒介已停止播放但打算继续播放时(比如当媒介暂停已缓冲更多数据)运行脚本

video标签在不同平台上的事件表现差异分析

HTML5——视频/音频加载过程中发生的事件

  • 当浏览器开始寻找指定的音频/视频时,即开始加载视频时,发生 loadstart 事件。
  • 当指定音频/视频的时长数据发生变化时,会发生 durationchange 事件。当音频/视频加载后,时长将由 "NaN" 变为音频/视频的实际时长。
  • 音频/视频的元数据包括:时长、尺寸(仅视频)以及文本轨道。当指定的音频/视频的元数据已加载时,会发生 loadedmetadata 事件。
  • 当当前帧的数据已加载,但没有足够的数据来播放指定音频/视频的下一帧时,会发生 loadeddata 事件。
  • 当浏览器正在下载指定的音频/视频时,会发生 progress 事件。
  • 当浏览器能够开始播放指定的音频/视频时,会发生 canplay 事件。
  • 当浏览器预计能够在不停下来进行缓冲的情况下持续播放指定的音频/视频时,会发生 canplaythrough 事件。
var v = document.getElementById('video元素的ID');
console.log('v.duration', v.duration);
// loadstart
v.addEventListener('loadstart', function(e) {
  console.log('loadstart', v.duration);
});
// durationchange
v.addEventListener('durationchange', function(e) {
  console.log('durationchange', v.duration);
});
// loadedmetadata
v.addEventListener('loadedmetadata', function(e) {
  console.log('loadedmetadata');
});
// loadeddata
v.addEventListener('loadeddata', function(e) {
  console.log('loadeddata');
});
// progress
v.addEventListener('progress', function(e) {
  console.log('progress');
});
// canplay
v.addEventListener('canplay', function(e) {
  console.log('canplay');
});
// canplaythrough
v.addEventListener('canplaythrough', function(e) {
  console.log('canplaythrough');
});
// play
v.addEventListener('play', function(e) {
  console.log('play');
});
// pause
v.addEventListener('pause', function(e) {
  console.log('pause');
});
// seeking
v.addEventListener('seeking', function(e) {
  console.log('seeking');
});
// seeded
v.addEventListener('seeked', function(e) {
  console.log('seeded');
});
// waiting
v.addEventListener('waiting', function(e) {
  console.log('waiting');
});
// playing
v.addEventListener('playing', function(e) {
  console.log('playing');
});
// timeupdate
v.addEventListener('timeupdate', function(e) {
  console.log('timeupdate');
});
// ended
v.addEventListener('ended', function(e) {
  console.log('ended');
});
// error
v.addEventListener('error', function(e) {
  console.log('error', e);
});

那个也许有人会好奇怎么测试error的事件,chrome的调试面板有提供offline的功能。当我们打开某个直播视频时,打开network面板,勾选offline,然后过会儿直播就没法请求下一帧了,就可以进入error了。

alt

video的属性、方法及事件,对于我们做自定义的播放器是相当有用的。

直播源制作

有两种方案:

  • nginx + ffmpeg
  • 集成服务

在课程中,那个老师没有分享flv的nginx配置,说那一块有点复杂。只是说了rtmpm3u8。在集成环境是有三种的:rtmpm3u8flv

我出于偷懒,所以flv那一块就不去尝试了。有兴趣的可以看一下这个资料: 支持HTTP-FLV方式直播的开源模块nginx-http-flv-module

nginx + ffmpeg

流程

  • 安装Nginx
  • 安装ffmpeg
  • 配置nginx
  • 准备视频
  • 利用ffmpeg推流

安装nginx

N久之前,我是这样安装的:

brew install nginx

但这次得加上编译参数,而且要装nginx-full

brew install nginx-full --with-rtmp-module

需要注意的是:

如果有报错,说找不到nginx-full模块,需要先执行一下brew tap denji/nginx

mac homebrem 安装Nginx 完整版本出错

安装完的验证这里就略过了。

安装ffmpeg

brew install ffmpeg

alt

nginx配置

http {
    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }
        # hls相关配置
        location /hls {
           types {
               application/vnd.apple.mpegurl m3u8;
               video/mp2t ts;
           }
           root /usr/local/var/www;
           add_header Cache-Control no-cache;
        }
    }
}
rtmp {
    server {
        listen 1935;
        chunk_size 4000;
        # RTMP 直播流配置
        application rtmplive {
            live on;
            max_connections 1024;
        }
        # hls 直播流配置
        application hls {
            live on;
            hls on;
            hls_path /usr/local/var/www/hls;
            hls_fragment 5s;
        }
    }
}

注意hls_path和上面的http的配置,其实是关联起来的,所以如果一处修改了,另一处也要改。

利用ffmpeg推流

我们可以随意下载一个视频,比如:模特走秀

ffmpeg -re -i test.mp4 -vcodec libx264 -acodec aac -f flv rtmp://localhost:1935/rtmplive/rtmp

alt

alt

随后我们打开VLC软件

alt

alt

alt

上面只是验证了ftmp,那么再来验证一下hls吧:

ffmpeg -re -i test.mp4 -vcodec libx264 -acodec aac -f flv rtmp://localhost:1935/hls/stream

然后打开safari浏览器,输入http://localhost/hls/stream.m3u8,这里的stream对应上面的,并不是写死的,可以修改。

alt

集成服务

流程

  • 下载服务
  • 安装服务
  • 准备源视频
  • 开启服务
  • 利用ffmpeg推流

server

服务的话,讲师是有给了一个server文件,有需要的话,可以直接email我,我可以发该文件发给你。

然后就先打开那个server文件:

open server

alt

相关命令

ffmpeg -re -i test.mp4 -c copy -f flv rtmp://localhost:1935/live/movie

验证地址:

  1. hls:http://127.0.0.1:7002/live/movie.m3u8
  2. flv:http://127.0.0.1:7001/live/movie.flv
  3. rtmp:rtmp://localhost:1935/live/movie

H5直播演练

播放器选型

代码演练

(略)

这里不得不提的是:videojs借助插件也可以实现hls的播放。但是文件体积会变大,而且UI界面定制性不高。如果只是hls播放,然后UI需要自己做定制,那么就用hls.js这个吧。

结语

跟着讲师学这个,真的学到了好多。以前只知道一个简单的src,现在都能简单地做一个直播流了。

另外大家可以关注一下这个讲师的github地址:cucygh。他提及在未来会开源一款播放器,会比之前的几个更加的牛逼,还能省流量。所以可以期待一下。

本文链接:www.my-fe.pub/post/live-broadcast-note.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。