直播全流程探索

2,313 阅读10分钟
原文链接: www.musicfe.cn
  • 近年来,直播兴起,QQ音乐也接入了直播能力,支持演唱会的直播和主播、明星直播,根据互动方式的不同,我们可以分为互动直播和推流直播,本人有幸参与了直播从无到有的过程;对直播这一块有了一个比较清晰的认识,本文主要对web部分的直播流程进行介绍;

直播现状

图片

上图列出的app都有涉足直播行业,可以看出目前的直播有多火;


我们按照整个视频内容的流动过程,将整个直播过程划分为三个阶段,生成阶段、传输阶段、呈现阶段

图片
下面将对这些阶段进行一一介绍;


生成阶段

生成阶段包括对音视频的采集和处理;

音视频的采集,采集阶段主要是对原始视频内容进行采集即直播内容的来源,根据应用场景的差别,我们可以分为五大类

  1. 电视内的直播主要是采集已有的视频源 比如电视剧 综艺节目等都是预先录制好的;

  2. 演唱会直播主要是通过摄像机和麦克风分别录制演唱会的画面和音频

  3. 端游直播,比如平常我们看到英雄联盟、吃鸡等游戏的直播, 主要是主播通过摄像头、话筒录制主播的直播画面 以及OBS等录屏软件录制游戏界面并合成直播画面

  4. 户外直播,目前户外直播也比较流行,类似于真人秀的模式,主播主要依赖手机自带摄像头和话筒来录制内容

  5. 手游直播,比如最近很火的王者荣耀,大仙、嗨氏等主播就是手游直播,android端主要是通过模拟器来录制,ios可以通过itools苹果录屏大师录制视频然后同步到obs上;

图片

音视频处理

DIY视频处理

图片

对于采集到的视频内容,需要做一些后期处理,主要包括两个方面

(1)对于录制好的视频画面可能达不到主播满意,还有一些主播想要加一些特效,需要对内容做美颜、磨皮、滤镜、加特效等处理,这个处理过程涉及到复杂的运算,运用到人脸识别、视频合成等方面的技术;

(2)有一些视频有版权方面的限制,需要加注水印,可以在这个环节处理,后面的转码阶段处理也可以

DIY音频处理

(1)原始声音可能比较杂,需要做降噪处理

(2)有一些直播场景,主播有一些混音、变音的处理,声音特效也是在这个环节处理;

编码处理

编码处理实际就是视频压缩处理的过程

我们先来做个计算

图片

一段6s720p的原始视频,不做任何处理大小为474M,在10M带宽下大概需要6分钟时间传输,这对于直播来说显然是不能忍受的;目前视频一般采用H.264标准编码,经过这个标准处理后大小可以直降到1M以下,传输时间可以降到800ms以下;

我们先来看下H.264协议,H.264标准基于MPEG格式进行封装,我们先来看MPEG的格式,将画面(即帧)分为I、P、B三种。 I是内部编码帧,P是前向预测帧,B是双向内插帧。 简单地讲,I帧是一个完整的画面,而P帧和B帧记录的是相对于I帧的变化。 没有I帧,P帧和B帧就无法解码,我们只需要保留关键的I帧,其他帧做一些关联信息的记录。

图片

压缩的过程就是去除冗余信息的过程,主要包括两个方面的压缩:

帧内压缩 1、人的视觉系统对某些细节不敏感,视觉冗余;

帧间压缩 1、图像相邻像素之间有较强的相关性,空间冗余; 2、视频序列的相邻图像之间内容相似,时间冗余。

举个栗子

图片

比如一段滑雪的视频,连续的帧其实大部分内容都是相同的,滑雪的同学是向前位移的,但实际上是雪景在向后位移,P 帧通过参考帧(I 或其他 P 帧)就可以进行编码了,编码之后的大小非常小,压缩比非常高。

另外音频内容也需要经过压缩,目前主要采用acc的编码方式;

整个生成阶段的流程如下

图片


传输阶段

传输阶段主要是是视频从采集端到用户端的过程

  1. 推流
    推流即我们平常说的上行,我们录制好的视频需要先推流到服务器,目前推流协议大部分采用的rtmp协议,rtmp全称是Real Time Messaging Protocol实时消息传输协议,具有以下几个特点

    (1)Abode私有协议,只要浏览器支持flashplayer的机器都支持rtmp协议 pc上基本都支持

    (2)长链接,不用重复握手 延迟可以控制在2s内,这个在直播过程中控制延时很关键

    (3)CDN 支持良好,主流的 CDN 厂商都支持

  2. 转码
    目前腾讯云提供的几种转码格式 直播流推送到服务器后 为了保证各个端的用户都能观看 基本能满足所有的观看场景 移动端native用的rtmp流 pc端 用的flv流 移动端H5用的hls流

图片

  1. 分发

    分发即我们平常说的下行,主要是服务端推流给用户,这一块主要需要运维同学关注在复杂的网络环境怎样更快速的让用户看到高质量的直播, 这一块涉及到传输质量监控、质量优化、鉴黄等部分的工作,网上也有很多这方面的专项文章,本文不做展开。


呈现阶段

内容分发后就来到用户播放阶段,怎样把一段视频更好的呈现给用户

  1. 播放协议
    目前移动端H5直播主要采用HLS协议播放,HLS最初是苹果公司针对iPhone、iPod、iTouch和iPad等移动设备而开发的流. 后续android3.0以上也支持,下表可以看出移动端基本都支持;

图片

图片

#EXTM3U m3u文件头,必须放在第一行

#EXT-X-ALLOW-CACHE 设置是否允许cache,当前是不允许

#EXT-X-MEDIA-SEQUENCE 接下来请求的第一个TS分片的序号,

#EXT-X-TARGETDURATION 每个分片TS的最大的时长,当前为9s,

#EXTINF 分片TS的信息,如时长等**

HLS的请求流程是:

1 播放器发起一个http请求,拿取m3u8的配置信息。

2 服务端返回一个m3u8的播放列表,列表的信息如上图。这里的分片长度和列表数量反应了时延长度,比如列表长度为5,分片时长为9s,则整个时延为45s;

3 播放终端解析m3u8的播放列表,依照顺序获取ts数据流,播放完毕的时候拉取下一个。

图片

  1. H5播放的过程中 也遇到了很多问题

(1)移动端播放问题-伪全屏

我们有很多场景下视频是全屏播放的且有互动部分的信息需要展示,如果是系统的全屏 整个播放界面不可控,这里需要用伪全屏,即css样式来设置视频大小,铺满全屏达到全屏效果,

图片

这里伪全屏需要注意的是ios上面需要设置内嵌播放,不然会被系统接管 ,在video标签上加上对应的属性即可,ios9以下设置是无效的,目前无解,ios9-ios10 webkit-playsinline ,ios10以上playsinline,需要所在的webview环境支持这种形式 ios微信 手Q 音乐app内均支持webviewallowsInlineMediaPlayback=YES即可;android端 客户端 手Q 微信 都是基于x5内核的 支持内嵌播放,但是在qq浏览器会接管直播 这里如果要改成内嵌的 需要找浏览器的同学加下白名单 如下图效果 正常效果是右图,QQ浏览器中会如左图效果

图片

图片
(2)自适应全屏

由于视频大小不一,在屏幕高宽度固定的情况下,让视频自适应屏幕很关键;

具体步骤

图片
1、计算视频的高宽度

2、视频高宽比和屏幕高宽比做比较

3、值偏大 以屏幕宽度为基准,进行等比缩放,值偏小,以屏幕高度为基准进行等比缩放;

举个例子

1、如下图左

2、屏幕是93169(宽/高) ,视频大小252192,252/192>93/169 ,以屏幕宽度为基准 则缩放比为252/93 如图2,

3、然后将视频居中存放到容器中,如图三;

图片

图片

图片

(3)播放协议自适应终端

目前直播流协议用的HLS,ios端均支持,android端不同的机型、不同的系统版本、不同的webview环境支持HLS协议不尽相同,对于不支持的再做降级处理,可以通过canPlayType来看支持程度,该方法会返回三个值

"probably" - 浏览器最可能支持该音频/视频类型

"maybe" - 浏览器也许支持该音频/视频类型

"-" (空字符串)浏览器不支持该音频/视频类型

function chooseWay(){

	var h5Able = {'probably': 1, 'maybe': 1};
	var videoDom = document.createElement("video");

	if( videoDom.canPlayType && ( videoDom.canPlayType("application/vnd.apple.mpegURL" ) in h5Able )){

		$('#js_video').attr('src','http://3260.liveplay.myqcloud.com/live/3260_17c84703049011e791eae435c87f075e.m3u8');
		console.log("支持HLS");

	}else{

		console.log("不支持HLS");

	};
}

(4)播放是否在继续

判断直播状态即直播是否在进行也是一个比较麻烦的事,由于android上对canplay canplaythrough playing事件支持程度不一样,触发时机也不尽相同,我们可以用一些hack技术,比如根据timeupdate进度的实时变化来判断是否有在播放

$('#js_video').on('timeupdate',function(){

		playtimeupdate = new Date().getTime();

});


setInterval(function(){//检测有没有在播放
	
	if( lastplaytimeupdate && lastplaytimeupdate == playtimeupdate ){

			console.log("异常");

	}else{

		lastplaytimeupdate = playtimeupdate;
	}

},3000)

(5)pc调用系统全屏 自定义ui遇到的坑   
全屏时默认系统会有一个ui,如果想自定义ui  需要想办法把video自带的影子节点隐藏或者盖住,

图片

在调用全屏时

图片
浏览器会为全屏的节点加上z-index ,是一个无限大的值,如果我们直接对video全屏 会将video和影子节点的层级设到无限高,即使设置了自定义ui的z-index 也会导致点击失效,需要在video和自定义ui节点的 父节点上做全屏;


自研sdk

目前音乐也推出了自研视频sdk,轻量、兼容性好,欢迎使用

H5部分 点播功能已经全量,支持后退/快进/进度拖动/全屏,直播正在接入中

pc部分 点播功能已经灰度,在H5基础上新增/音量控制/自定义全屏ui/清晰度切换,直播正在接入中

demo页 
y.qq.com/m/demo/demo…

H5基于zepto 引用 
y.gtimg.cn/music/qmv/q…

pc基于jquery 引用 
y.gtimg.cn/music/qmv/q…

var params = {
	title: "QMV播放列表",
	container: ".js_videoplayer",
	source:["x00248tvbgv","t0024928s1j","g00133xte6r"],
	quality:true,
	autoplay:false,
	mode:0,// 0 顺序 1 随机 当列表数量大于2时有效
	useConnectionPlay: false,
};
var qmv = new QMV(params); 

参考资料

HLS介绍

https://github.com/ossrs/srs/wiki/v2_CN_DeliveryHLS

帧内压缩和帧间压缩区别

https://www.zhihu.com/question/20237091

H5视频直播扫盲

http://km.oa.com/group/19674/articles/show/266140?kmref=search&from_page=1&no=1

移动端HTML5 video 标签深入实践

http://km.oa.com/articles/show/261332?kmref=search&from_page=1&no=4