当前位置: 首页 > Web前端 > HTML5

H5直播技术起航

时间:2023-04-05 20:28:27 HTML5

作者:京东科技吴磊音视频基本概念视频格式俗称.mp4、.flv、.ogv、.webm等,简单来说,其实就是一个用于将实际视频流按一定顺序排列的框,以确保播放的顺序和完整性。视频压缩格式与视频格式的具体区别在于它将原始视频码流转换为可用的数字代码。因为原始视频流很大。比如你直接用手机录音,你会发现你几分钟的音频会比市面上的MP3音频大很多。这是压缩格式的主要作用。首先由原始数字设备提供相关的数字信号流,然后通过视频压缩算法将流的大小大大减小,然后交给视频盒,相应的dts和pts字段为标记,最后生成一个可以使用的视频文件。DTS(DecodingTimeStamp):解码时间戳。这个时间戳的意思就是告诉播放器什么时候解码这一帧的数据。PTS(PresentationTimeStamp):显示时间戳,用来告诉玩家什么时候显示这一帧的数据。视频编码Video其实就是一帧一帧的图片,拼接在一起播放。图像本身也可以进行压缩,比如去除重复像素、合并像素块等。但是还有另外一种压缩方式,运动估计和运动补偿压缩,因为必须有一大块相邻的图片是相似的,所以为了解决这个问题,可以在不同的图片之间进行去重。因此,一般来说,常用的编码方法分为三种:变换编码:消除图像的帧内冗余运动估计和运动补偿:消除帧间冗余熵编码:提高压缩效率熵编码是在编码过程中根据熵原理不丢失任何信息的编码。信息熵是源的平均信息量(不确定性的度量)。常见的熵编码包括:香农编码、霍夫曼编码和算术编码。目前常用的直播流协议有RTMP、HLS、HTTP-FLV。最常用的是HLS协议,因为支持度高,技术简单,但是延迟很严重。这对一些实时性要求高的场景非常不友好,比如体育赛事直播。这是每个协议的细分。协议对比协议优缺点延迟HLS支持宽延迟和10s以上的高延迟RTMP有很好的延迟。如果弹性量大,负载高于1s。HTTP-FLV具有良好的延迟。常用直播游戏只能在手机APP上玩2s以上HLSHLS的全称是HTTPLiveStreaming。这是苹果公司提出的直播协议。HLS由两部分组成,一个是.m3u8文件,一个是.ts视频文件(TS是视频文件格式的一种)。整个过程就是浏览器会先请求.m3u8索引文件,然后解析m3u8,找出对应的.ts文件链接,开始下载。他的使用方法是:可以直接把m3u8写入src,然后让浏览器自己解析。当然也可以使用fetch来手动解析获取相关文件。HLS详细版的内容比上面的简化版多了一个播放列表,也可以称为master。master中会根据网段设置不同的m3u8文件,比如3G/4G/wifi网速等。例如,一个主文件是:#EXTM3U#EXT-X-VERSION:6#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2855600,CODECS="avc1.4d001f,mp4a.40.2",RESOLUTION=960x540live/medium.m3u8#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=5605600,CODECS="avc1.640028,mp4a.40.2",RESOLUTION=1280x720live/high.m3u8#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1755600,CODECS="avc1.42001f,mp4a.40.2",RESOLUTION=640x360live/low.m3u8#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=545600,CODECS="avc1.42001e,mp4a.40.2",RESOLUTION=416x234live/cellular.m3u8只需要关注BANDWIDTH(带宽)字段,看看其他字段的内容就可以大致了解.如果这里选择的是high.m3u8文件,那么里面的内容就是:#EXTM3U#EXT-X-VERSION:6#EXT-X-TARGETDURATION:10#EXT-X-MEDIA-SEQUENCE:26#EXTINF:9.901,http://media.example.com/wifi/segment26.ts#EXTINF:9.901,http://media.example.com/wifi/segment27.ts#EXTINF:9.501,http://media.example.com/wifi/segment28.ts注意,以ts结尾的链接是直播时实际需要播放的视频文件。二级m3u8文件也可以称为媒体文件。这个文件实际上有三种类型:liveplaylist:dynamiclist。顾名思义,列表是动态的,里面的ts文件会实时更新,过期的ts索引会被删除。默认情况下,使用动态列表。事件播放列表:静态列表。它与动态列表的主要区别是不会删除原有的ts文件索引,列表会不断更新,文件大小会逐渐增大。它将直接在文件中添加#EXT-X-PLAYLIST-TYPE:EVENT作为标识符。VOD播放列表:完整播放列表。就是列出列表中所有的ts文件。如果,使用这个列表,那和播放整个视频没什么区别。就是用#EXT-X-ENDLIST来表示文件结束。https://developer.apple.com/l...HLS缺陷HLS的缺陷是延迟太大。HLS中的延迟包括:TCP握手m3u8文件下载m3u8文件下的所有ts文件下载这里假设每个ts文件播放5s,每个m3u8可以播放最多携带的ts文件个数为3~8个。那么最大延迟是40s。注意,只有一个m3u8文件下的ts文件全部下载完毕,才能开始播放。这不包括TCP握手、DNS解析、m3u8文件下载。因此,HLS的总延迟是非常无望的。有解决办法吗?是的,很简单,要么减少每个ts文件的播放时间,要么减少m3u8中包含的ts个数。如果超过了平衡点,每次请求新的m3u8文件都会增加一定的延时,所以需要根据业务指定合适的策略。RTMPRTMP的全称是:Real-TimeMessagingProtocol。它是基于FLV格式开发的,所以第一反应就是不能再用了!!!是的,在目前的设备中,由于缺乏对FLV的支持,RTMP协议在Web中基本不用。但是由于MSE(MediaSourceExtensions)的出现,在Web端直接访问RTMP也不是不可能。基本思路是直接基于WebSocket建立长连接,进行数据交换和监控。RTMP协议也可以根据层数的不同分为不同的层数:纯RTMP:通过TCP直连,端口为1935RTMPS:RTMP+TLS/SSL,用于安全通信。RTMPE:RTMP+加密。在RTMP原始协议上使用,Adobe自带的加密方式RTMPT:RTMP+HTTP。使用HTTP封装RTMP流,延迟比较高。RTMFP:RMPT+UDP。该协议常用于P2P场景,对时延有异常要求。RTMP内部使用TCP长连接协议传输相关数据,所以它的延迟很低。而且协议很灵活(所以,也很复杂),可以根据messagestreamID传输数据,也可以根据chunkstreamID传输数据。两者都可以起到分流的作用。流的内容也主要分为:视频、音频、相关协议包。HTTP-FLV协议和RTMP相比其实差别不大,只是落地部分有点不同:RTMP直接把流传输放在了RTMP协议之上,而HTTP-FLV在RTMP和客户端之间设置了一层转码的过程,由于每个FLV文件都是通过HTTP获取的,所以抓包获取的协议头需要使用chunked编码。Content-Type:video/x-flvExpires:Fri,10Feb201705:24:03GMTPragma:no-cacheTransfer-Encoding:chunked使用起来比较方便,但是相对于后端实现难度还是比较大直接用RTMP的。由于各大浏览器对FLV在前端音视频流的围攻拦截,FLV在浏览器中的生存堪忧。而FLV以其格式简单、处理效率高的特点,让各大视频背景的开发者不愿放弃。使用,如果一旦改变,现有的视频需要转码,比如转成MP4,这不仅对于播放来说有点沉重,而且对于流处理来说也是无法接受的。MSE的出现彻底解决了这个尴尬点,让前端可以自定义实现一个web播放器,确实很完美。(不过苹果认为没有这个必要,所以不能在IOS上实现。)MSEMSE的全称是MediaSourceExtensions。是一套视频流技术的简称,包括一系列的API:MediaSource、SourceBuffer等。在MSE出现之前,前端对视频的操作仅限于对视频的操作文件,无法对视频流进行任何相关操作。现在MSE提供了一系列的接口,让开发者可以直接提供媒体流。我们来看看MSE是如何完成对基本流的处理的。varvidElement=document.querySelector('video');if(window.MediaSource){varmediaSource=newMediaSource();vidElement.src=URL.createObjectURL(mediaSource);mediaSource.addEventListener('sourceopen',sourceOpen);}else{console.log("TheMediaSourceExtensionsAPIisnotsupported.")}functionsourceOpen(e){URL.revokeObjectURL(vidElement.src);varmime='video/webm;codecs="opus,vp9"';varmediaSource=e.target;varsourceBuffer=mediaSource.addSourceBuffer(mime);varvideoUrl='droid.webm';fetch(videoUrl).then(function(response){returnresponse.arrayBuffer();}).then(function(arrayBuffer){sourceBuffer.addEventListener('updateend',function(e){如果(!sourceBuffer.updating&&mediaSource.readyState==='open'){mediaSource.endOfStream();}});sourceBuffer.appendBuffer(arrayBuffer);});}上面的例子可以简单理解为:第一步异步拉取数据。第二步是通过MediaSource处理数据。第三步,将数据流发送给audio/video标签进行播放。中间传递的数据以Buffer的形式传递。中间有一点要注意,MS实例通过URL.createObjectURL()创建的url不会同步连接到video.src。换句话说,URL.createObjectURL()只是作为中介连接底层流(MS)和video.src。一旦两者连接在一起,对象就没有用了。MediaSourceMediaSource是表示媒体资源HTMLMediaElement对象的媒体源扩展API接口。MediaSource对象可以附加到HTMLMediaElement以在客户端播放。MS(MediaSource)只是一系列的视频流管理工具,可以将音视频流完全暴露给Web开发者进行相关操作和处理。因此,它本身不会导致过度的复杂性。MS只挂载了4个属性、3个方法和1个静态测试方法。4个属性:sourceBuffers:获取当前创建的SourceBufferactiveSourceBuffers:获取当前active的SourceBufferreadyState:返回当前MS状态,如:closed、open、ended。duration:设置当前MS的播放时长。3个方法:addSourceBuffer():根据给定的MIME创建指定类型的SourceBufferremoveSourceBuffer():在MS上移除指定的SourceBuffer。endOfStream():直接终止stream1静态测试方法:isTypeSupported():主要用于判断是否支持指定音频的MIME。最基本的就是使用addSourceBuffer方法获取指定的SourceBuffer。varsourceBuffer=mediaSource.addSourceBuffer('video/mp4;codecs="avc1.42E01E,mp4a.40.2"');资料:https://developer.mozilla.org...SourceBufferSourceBuffer接口是指将MediaSource对象传递给HTMLMediaElement并对播放的媒体进行分块处理。它可以由一个或多个媒体片段组成。一旦用MS创建了SourceBuffer,后续的工作就是将追加的流放入Buffer中进行播放。因此,SourceBuffer提供了appendBuffer和remove两个基本操作。之后就可以直接通过appendBuffer把ArrayBuffer放进去。其中,SourceBuffer还提供了一个紧急方法abort(),当流出现问题时可以直接丢弃指定的流。音视频的ArrayBuffer通过MediaSource和SourceBuffer的处理直接连接