整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

html5常见的音视频格式和解决方案

图网长期致力于web前端开发,难免会和各种视频、音频打交道,除了常见的mp4、mp3等格式,其实还有m3u8、oga等等其他没有那么常见的格式,那么你都了解了吗?下面介绍一下html5常见的音视频格式和解决方案。



万能播放插件js

1.ckplayerhttp://www.ckplayer.com/

2.Sewise Player

一款专业的免费网页HTML5视频、流播放器,它功能强大,体积小,跨平台,兼容性好,使用方便简洁。确定html5与flash播放的优先级。支持跨终端播放,不仅适用PC端播放,也适配ipad、iphone、android手机、平板电脑等移动终端。 支持多系统多平台,PC端支持Window、MacOS、Linux 等,移动端支持Android、IOS、Window Phone等。 兼容HTML5,确保98%的互联网用户可以看到您的视频。 支持多浏览器兼容,IE6/7/8/9/10、Chrome、Firefox、Safari、Opera等。 接收来自任何地方的音视频流 支持mp4、m3u8、oga、webm、theora、flv、f4v等视频格式播放。 支持Flash播放m3u8文件,以及AES-128解码播放。 支持播放地址AMF, AJAX, JOSNP类型请求。 支持PC与Mobile平台播放器自动识别功能。 支持浏览器HTML5与Flash特性检测。

3.hls

http://www.bootcdn.cn/hls.js/

仅支持hls(m3u8)地址,不支持flv,mp4,mov,f4v,3gp格式,做了跨平台的适配, 支持PC终端,Android安卓终端,iOS苹果终端,WP终端的正常播放。

m3u8是m3u的一种,是utf-8格式的,Apple 为了提高流播效率开发的技术,特点是将流媒体切分为若干 TS 片段(比如每10秒一段),然后通过一个扩展的 m3u 列表文件将这些 TS 片段集中起来供客户端播放器接收。可以做多码率的适配,根据网络带宽,客户端会自动选择一个适合自己码率的文件进行播放,保证视频流的流畅。

MP4是一套用于音频、视频信息的压缩编码标准,支持所有音频和视频以及高级内容(或它们的混合),编码格式:H.264格式高清

MP4是遵循MPEG-4(ISO 14496-14)的官方容器格式定义的广义文件扩展名。它可以流媒体化并支持众多多媒体的内容(多音轨(multiple audio)、视频流(video)、字幕(subtitlestreams)、图片(pictures)、可变桢率(variable-framerates)、码率(bitrates)、采样率(samplerates)等)和高级内容(advanced content)(官方称之为“Richmedia”(超媒体)或“BIFS”(Binary Format for Scenes/二进制格式场景),类似2D和3D图形,动画、用户界面、类DVD菜单,上述这些AVI搞不定的东西。

其他相关的扩展名:

– .m4v:是.mp4文件的错误扩展名,由apple提出,支持视频+音频,m4v扩展名可以安全地更名为.mp4

– .m4a:是.mp4文件的错误扩展名,由apple提出,只支持音频,m4a扩展名可以安全地更名为.mp4

– .m4p:随iTunes发售的DRM(Digital Rights Management/数字版权保护技术)产权保护的文件,使用Apple开发的DRM sheme

– .m4e:由.sdp修改扩展名的来的文件,Envivio用其于流媒体播放。

– .m4v, -.mp4v, -.cmp, -.divx, .-xvid, .264:raw的mpeg-4视频流(并非内含于mp4)。

– .3gp, -.3g2:手机中使用的格式,其中储存的内容同样在.mp4未被定义(H.263, AMR(Adaptive Multi Rate/自适应多码率))。

OGG OGGVobis(oggVorbis)是一种音频压缩格式,类似于MP3等的音乐格式。Ogg是完全免费、开放和没有专利限制的。OggVorbis文件的扩展名是”.ogg”。Ogg文件格式可以不断地进行大小和音质的改良,而不影响旧有的编码器或播放器。

OGV是html5中的一个名为Ogg Theora的视频格式,起源于ogg容器格式。

webm由Google提出,是一个开放、免费的媒体文件格式。WebM标准的网络视频更加偏向于开源并且是基于HTML5标准的,WebM 项目旨在为对每个人都开放的网络开发高质量、开放的视频格式,其重点是解决视频服务这一核心的网络用户体验。

MOV(QuickTime)它是Apple公司开发的一种音频、视频文件格式,用于存储常用数字媒体类型。QuickTime用于保存音频和视频信息,包括Apple Mac OS,MicrosoftWindows95/98/NT/2003/XP/VISTA,甚至WINDOWS7在内的所有主流电脑平台支持。

WMV微软推出的一种采用独立编码方式并且可以直接在网上实时观看视频节目的文件压缩格式。WMV格式的主要优点包括:本地或网络回放、可扩充的媒体类型、部件下载、可伸缩的媒体类型、流的优先级化、多语言支持、环境独立性、丰富的流间关系以及扩展性等。

MPG/MPEG(.mpg, .mpeg)

Realmedia(.rm, .rmvb)

AVI(.avi)

Flv/swf

本文由专业的WEB前端外包公司-切图网原创,转载请保留版权( WEB前端开发外包www.qietu.com )切图网始于2007年,提供高品质的前端开发服务、前端外包、切图外包。欢迎来电咨询!

照相机、留声机诞生,解决了人们记录影像、声音的需求以来,人们就不断地追求着在有限的条件下尽可能地提高这些记录的品质,而从模拟时代过渡到数字时代以后,这方面的追求有一部分变成了在尽可能小的空间中提供尽可能好的内容质量,这就催生出了一系列不断演进着的媒体压缩技术。

不过这期课堂的主题尚未来到媒体编码的历史,在讲音视频图像的压缩算法进化之路前,我们先来了解一下这些媒体内容的载体——容器格式的进化历程。

首先需要区分清楚的,就是容器格式与媒体编码格式。

何为容器(Container)

对于数字媒体数据来说,容器就是一个可以将多媒体数据混在一起存放的东西,就像是一个包装箱,它可以对音视频数据进行打包装箱,将原来的两块数据整合到一起,也可以单单只存放一种类型的媒体数据。它就像电影胶片一样,中央是一帧一帧的图像,而两旁则印有对应的音轨。



举个简单的例子,常见的MP4就是一种媒体容器格式而不是编码格式,它里面的视频编码可以是现在最常见的AVC/H.264,也可以是它的前任H.263或者下一任——HEVC,音频编码可以是常见的AAC也可以是AC-3。

另一个生僻点的例子:最常见的图片格式——JPEG,它其实只是一种压缩方式,而它的存放方式其实叫做JFIF(JPEG File Interchange Format),虽然在JPEG标准中定义了一种名为JIF(JPEG Interchange Format)的容器格式,但是因为其缺乏某些关键要素,造成了使用的不便而被后来第三方开发出来的JFIF容器给取代了,今天我们能够看到的JPEG文件几乎都是装在JFIF容器中的。

虽然今天我们能够直接拿到的MP4文件里面装的几乎都是AVC+AAC的组合,但还是不能混淆了两者的概念,容器就是个容器,它没得灵魂。

AVI: 老而弥坚

AVI可能是和笔者年龄相仿的朋友最早接触的一个格式。确实,它推出的时间相对较早,也是许久以前最为常见的一种容器格式。它全称叫做音频视频交错( Audio Video Interleave),顾名思义,它就是简单地将视频与音频交错在一起,几帧视频之后就是对应的音频段,这样重复,直到结束。



AVI文件的结构示意图

它由三部分组成,头部、主体以及位于文件尾部的索引。头部中含有文件的元数据(metadata),比如视频的分辨率、码率总帧数等信息。主体部分是媒体数据的存放区,它使用了块(chunk)的概念,将原本的视频流和音频流分成块状进行交错放置,就是上面讲的一段视频一段音频交错放置,而尾部则是用来放置索引,它用来记录每个数据块在文件中的偏移位置。



红框标注为对轨道的标识

讲到AVI,还可以联动一下WAV和苹果那边的AIFF,这些容器格式其实是同源的,来自于EA(对,就是现在那个做游戏的EA)为了让不同公司开发出来的软件之间进行数据交换而在1985年开发出来的IFF(Interchange File Format)格式。苹果在IFF的基础上开发出了AIFF,而微软与IBM将IFF格式使用的大端序改成小端序就成了RIFF(Resource Interchange File Format),也就是AVI、WAV这两个容器的基本原型。




AVI虽然老,但是因为它以帧为单位把数据切成块来存放的特性,使得它几乎支持市面上几乎所有的音视频编码。而它的缺点也有很多,首先因为索引在文件尾部的关系,所以它并不适合用来流传输;另外在容器中也没有时间戳,只能通过帧数和帧率信息来进行计算,在索引里面并没有写明时间戳—媒体位置的数据,所以要在播放AVI时进行快速跳转还需要额外的技术手段;而媒体数据分块存放也使得它对很多使用运动预测特性的视频编码的支持并不是太好,因为这些帧,比如P帧和B帧,都是通过I帧进行计算得到的,这就需要访问当前帧以外的数据了。

MPEG-PS:VCD、DVD的功臣

用电脑播放过VCD的朋友一定还记得会在目录里寻找那个最大的.DAT文件来播放,而DVD则是找那个最大的.VOB。其实这两个格式都是MPEG-PS容器规范的一种,此PS非彼Photoshop,而是指Program Stream,是MPEG组织在1993年发布的一个容器标准,并且随后写入ISO/IEC国际标准,除了以上两种后缀名之外,还有.mpg也用的是这个标准。

MPEG-PS标准中引入了包的概念,整个文件由一个个包组成,每个包的大小并不相等,包里面含有这个包的时间码以及对应的音视频数据。

MPEG-PS已经随着时代的进步被废弃了,它只能存放MPEG-1、MPEG-2、MPEG-4这些出自同门的视频编码,限制性较大。但因为VCD和DVD的广泛流行,实际上它还是被用的相当多的。

MPEG-TS:专为流传输而生

MPEG组织不仅仅为音视频文件的存储制定了容器标准,还早早地顺应时代潮流,为它们的传输准备了相应的容器。我们的数字电视和IPTV用的就是MPEG组织在1995年制定的Transport Stream,也就是TS容器,当然它也并不限于这两个场景,在现在的低延时直播系统中,MPEG-TS仍然占据了绝对主流的地位,原因就是它的整个结构就是为了流传输而设计的。



从IP层到TS包内部的结构

一个TS文件中可以容纳多个TS流,不同的流上面可以带有不同的音视频数据,这样通过接收一个TS文件,用户方面可以自由地在这个TS文件中的多个子TS流之间进行切换,非常适合用于传输电视节目。而它同时针对复杂的传输环境进行了针对性的优化,TS流的基础单位是一个个大小仅为188字节的包,每个包都有自己的独立时基,并且由于采用了固定大小,所以在传输过程中即使遭遇丢包也很快就可以恢复正常播放。

发展到今天,TS仍然在网络流传输时代中发挥着自己重要的作用,在苹果主导的HLS(Http Live Streaming)协议中使用的就是TS流,它比MPEG-DASH更加通用,因为后者对于MP4文件进行了一定的修改,在老平台上面支持不太好,而HLS使用的TS仍然是规范中的,可以被大多数设备兼容。

不过也因为TS分包较多的特性,会产生一些数据冗余,所以在存储场景中一般不会使用TS作为容器。

M2TS:专为高清时代而生

M2TS多见于Blu-ray光盘和高清录像(AVCHD)中,它由MPEG-TS修改而来,加入了对于高清时代新的音视频编解码支持。



一张Blu-ray视频光盘中的M2TS

并且由于TS文件的特性,每一个小片上都有自己的独立时间戳,这使得文件中一部分数据即使遭到破坏也不会影响到其他部分的正常播放,而且可以从中随意的进行切片操作。

ASF:先进却早夭

见过ASF格式视频的朋友我想应该不会太多,但是见过WMV和WMA这两个微软以前主推的媒体编码格式的朋友肯定有很多。其实WMV和WMA就是存放在ASF容器之中的,它全称高级系统格式(Advanced Systems Format),微软原本计划是用它来作为AVI容器的后继者的,它具有诸多先进的特性,比如说它可以包含视频除了规格以外的元数据,如导演、电影名这些,它也可以提供数字版权管理(DRM),还有非常好的流传输支持——仅需要加载文件的最小部分即可开始播放,这点小编感受过一次。




ASF文件开头会用这32个字节来标识自己是个ASF文件

ASF身上的这些特性在当时还算是比较先进的,但不过这于事无补,微软建立它那套封闭媒体格式体系的做法并没有得到太多厂商和用户的支持,大家仍然更喜欢用其他更为开放一点的标准,比如MP3就是一个很好的例子。ASF容器也随着微软媒体格式的衰亡而渐渐消失了,我们今天已经几乎看不到WMV、WMA这两个曾经还很常见的格式的影子了。

RM:昔日王者,如今不见踪影



与ASF差不多同时代流行的就是RM和RMVB了,在那个AVC尚未开始普及,DivX和XviD应用较少的年代中,RMVB在国内的各大下载站中都占据了绝对主流的地位,很多视频站也大多使用RM来提供“网络视频点播”的服务。



RM容器的内部结构

不过RM容器本身并不出彩,索引仍然位于文件尾部,不过由于数据段里面有加入时间戳,所以在流传输时还是可以应付用户的跳转操作的。因为这个容器本身与RM编码息息相关的原因,它本身也只能容纳RM编码的视频流,所以在RM编码没落之后我们就很少再看到这些昔日王者了,一个容器格式想要长存,要么在设计上有其独到之处,要么就是要开放,在众多平台上面提供支持。而RM两个理由都不占,效果又比不过新兴的AVC,所以它的没落也是必然了。

FLV:前高清时代的宠儿

还记得十年前的土豆网吗?彼时它还被称为“国内的Youtube”,当时视频网站普遍都还在用Flash写播放器实现流视频播放,而自然而然地,Adobe制定的Flash Video格式就成了这些视频网站主要使用的容器格式,也就是我们熟知的FLV。



FLV格式是在Flash Player 6中引入的,当时更多的是被存放在SWF文件的内部,不过后来因为体积越来越大而直接独立了出来,它的结构相对而言比较简单,主要分为两块,位于文件头部的元数据信息和后面的音视频数据。不过在数据的存放上面,FLV是将数据分为多个标签进行存储的,每个标签都带有自己的时间戳,所以这就保证了流传输时的音画同步。

由于FLV结构简单但是功能足够用,并且被Flash Player天然支持,所以在当时的视频网站上面普遍都使用它作为容器,直到今天还有很多网站没有放弃它,虽然其中的视频编码早已升级,它也有衍生出来的F4V作为后继者,虽然后者的血统已经不是Flash家族的了。

F4V:换了血的继任者

小编还记得土豆网在2009、2010年左右在国内率先开始使用H.264编码,当时如果将清晰度切换到“高清”就会播放这些用H.264编码的视频。而用飞速土豆加速会缓存到一些.f4v扩展名的文件,乍一看还以为它就是FLV,但其实不然,F4V其实是MP4所在的ISO标准容器家族的,但也是Adobe搞出来的FLV的后继者。关于后者的详情,请往下看。

MOV:苹果向业界作出的贡献

MOV格式的正式名字叫QuickTime File Format。看到这个QuickTime第一反应肯定是“哦,这是苹果的东西”。确实,QuickTime File Format是由苹果在1998年推出的,它引入了原子(atom)的概念,在QTFF格式中,atom是基本的数据单元,它可以用来容纳实际的音视频数据,也可以放置元数据和字幕等文本信息,atom中所容纳的数据类型和大小在每个atom的头部进行描述,经过一层层的嵌套之后,整个数据文件呈现了一种树状的结构,并且保留了强大的可扩展性。



MOV和MP4这些ISO标准容器格式的开头都有一个ftyp用于标记格式

MOV作为苹果QuickTime编码的成员,在目前仍然被苹果设备广泛使用着,并且对于它的支持非常好。1998年推出QTFF的同时,苹果将这个格式交给了ISO组织,后者将它标准化为国际通用容器格式,而基于这个标准衍生出来的容器,又可以叫做ISO/IEC base media file format,同时被MPEG组织采纳,写入MPEG-4 Part 12标准中。

ISO标准容器格式

ISO标准容器格式是一个规范,它代表符合这个规范的容器类型,而不是特指某个格式。它是由苹果的QuickTime File Format发展而来的,在MPEG-4 Part 12中被最终确定并被ISO/IEC组织写入标准。它虽然没有具体实现,但是它定义了基于时间码的多媒体文件的通用结构,并由此成为了MP4、3GP等格式的基础。



3GP、MP4与ISO标准容器格式的关系

MP4:标准,泛用

MP4肯定是现在最通用最流行的媒体容器,甚至可以说没有之一。但其实现在的MP4和早期的并不是同一个标准,目前常见的MP4标准是在2003年完整的的MPEG-4 Part 14规范中制定的,到今天为止也经过了多次的修订。它其实与MOV之间并没有太大的区别,基本上就是把MOV的atom改了个名字,叫成box,然后加了一点别的佐料。



MP4的内部结构

苹果建立iTunes Store卖数字音乐的时候选择了AAC-LC作为他们的音频编码格式,而容器格式上面他们并没有选择与AAC-LC处于同一时代(MPEG-2)的ADTS,而是选择了比AAC-LC大一辈的MPEG-4标准容器,也就是MP4,不过因为它只含音频所以我们看到的扩展名就是.m4a,iTunes Store还卖一种只有视频没有音频的MV,它用的也是MP4,扩展名为.m4v,本质上它们就是同一种东西。

目前很多视频网站已经从FLV切换到MP4上面了,而且还有一种新的MPEG-DASH格式就是借助于MP4可分割的特性实现的,它将一整段视频切成许多段小块,方便浏览器进行加载,减少HTTP长连接对服务器的压力。

这里说一句题外话,当年某站刚上HTML5播放器的时候,因为他们原来的视频几乎全部都用的是FLV存储的,而HTML5标准并不支持它,所以要进行一个容器转换,某站当时一位非常年轻的程序员写出了一个在浏览器内实时将FLV文件转成MP4并喂给浏览器的媒体播放器的脚本,名为flv.js,这个脚本可能给某站省下了非常大的格式转换成本。不久之后这位程序员因为受不了某站的低薪而离职。这件事曾经引起了很多社区的热烈讨论,因为今天是程序员日所以特地写了这么一段。

3GP:精简小巧,手机最爱

3GP是MP4的同族兄弟,一样是基于ISO标准容器格式,用过3GP的兄弟肯定还记得这格式最多出现的地方是哪里——以诺基亚为代表的前智能手机时代,手机录像出来的文件大多都是3GP格式的。

3GP这个容器格式标准其实不是由以往的MPEG啊这类专注于多媒体编码的组织搞出来的,而是3GPP,对没错就是制定通信行业标准的那个组织制定的。它在容器支持的格式上进行了精简,只面向于手机可以进行的编码,比如MPEG-4 Visual、H.263这些比较老的视频编码和AMR、AAC这两种前智能手机时代使用较多的音频编码。

因为前智能手机时代的手机性能并不强大,一般也不需要支持很多种格式,不用像MP4那么全面,所以3GP最终成为了一种被广泛支持的格式,不过也因为它支持的格式过于有限,最终在智能手机时代被同门大哥MP4给取代了。

MPEG-DASH

面对时下流行的流媒体,MPEG组织对MP4文件进行了魔改,由于MP4天生可以进行无损切割的特性,DASH方式将原本媒体文件中完整的文件头的元数据信息和片段Box中的信息抽取出来单独写在一个文件(MPD)中,同时还包含了片段的URL等信息,播放器可以自适应选择需要的片段进行播放,在自适应程度上面比HLS更强一些。(其实MPEG-DASH也可以用TS作为容器,但用MP4更多一些)



目前MPEG-DASH已经成为了一项国际标准,人们比较熟悉的应用平台就是Youtube和Netflix,在这些平台上面你会发现浏览器在不断地加载一些小的视频文件,但是视频的播放是连续的。

MKV:强大无需多言,免费让它受爱

说到MKV,喜欢收藏高清电影的朋友肯定不会陌生,这种容器格式大概是和高清时代一起发展起来的,但其实它在2002年底就已经完成制定了,不过推广的很缓慢,到了高清时代和UHD时代人们才开始发现这种容器的强大,并用的越来越多,连微软都在Windows 10的初始版本中加入了对它的支持。



MKV的内部结构

MKV全名Matroska,它身上最大的特点就是开放标准、免费使用,而且它可能是目前地球上最强大的数字媒体容器格式,一个文件中可以放音频、视频、字幕、字体还有章节信息等等等等,前面东西都是不限数量任你放多少都可以吃得下的,而且它是目前唯一一个支持封装ASS字幕的格式。

值得一提的是,这玩意儿是俄罗斯组织матрёшка搞出来的,其实本身是用于盗版的,俄罗斯的网络情况跟我们挺像的,网络上盗版横行,而MKV也帮助了文件的传播,目前来看,MKV可能是众多容器格式里面最好用的,无论是编辑元数据还是抽取轨道重新封装都有GUI工具支持,不过可惜的是众多视频编辑剪辑软件还是没有提供对它的支持。

总结

其实读到最后你会发现,这些容器格式内部对于音视频数据的处理都是大同小异的,区别点其实并不大。更多的差距在于它们对于不同编码格式的支持程度、元数据的详细程度以及对于是否能够支持音视频以外的数据。

而发展到至今,MP4仍然够用,在互联网时代扮演着非常重要的角色;MKV在下载党那里被奉为圭臬;而TS格式仍然在数字电视系统中被广泛使用。但在他们之前的格式也不是说非常弱或者不好,只不过可能是他们支持的那些格式没落了顺带着把它们也带没了,真正像AVI那样确实在技术规格上落伍的容器并不多。

而对于各种容器之间无损互转的事情,小编这里推荐mp4box、mkvtoolnix和强大的ffmpeg这些工具。下一篇系列课堂,我们会转向在如今多媒体领域中扮演无可替代角色的视频编码的变迁史,并且会看一看未来的AV1和VVC这两种对于大众来说还很陌生的下一代视频编码。

本文章主要对在浏览器环境中实现直播相关的技术介绍,其中包括了对音视频的格式以及推送、播放技术的探索。分享过程中还会对目前自己已经实现的一套Web直播方案进行分析。最后还会简单介绍现在比较热门的WebRTC技术。

什么是音视频串流

音视频串流从广义角度来说,就是能够实现设备A将音视频画面同步传输给设备B进行播放,例如电视投屏、会议投屏。而今天所介绍的Web音视频串流主要是实现允许用户在浏览器环境就能完成串流。

一个完整的Web媒体串流应当具备3种角色,推流客户端(主播侧),媒体服务器(MediaServer)和拉流客户端(观众侧)。其中推流和拉流客户端其实都是在网页中进行处理的,而MediaServer位于服务端,并且要能够完成同时接收来自不同推流客户端的流数据,并对这些流进行区分,向拉流客户端提供获取对应流的渠道。

需要知道的音视频概念

音视频编码格式

在封装格式里的视频可以用不同的编码格式,编码格式简单的理解就是用特定的压缩技术把视频做些处理。不过容器其实也可以做些压缩处理。所以视频是可以在编码格式、容器格式中做两次压缩。

常见的编码格式有:mpeg-2、mpeg-4、h.263、h.264、RV40

音视频封装格式 封装格式就是把已经编码封装好的视频、音频按照一定的规范放到一起 同一种封装格式中可以放不同编码的视频,不过一种视频容器格式一般是只支持某几类编码格式的视频。我们能够最直观判断封装格式的方法就是文件后缀。 常见的容器格式有: MP4、rmvb、rm、flv、AVI、mov、WMV、mk

浏览器支持的格式

对于video标签来说,浏览器支持视频播放的封装格式有:MP4、WebM和Ogg。其中我们就MP4来说,必须使用h.264编码的视频和aac编码的音频,才能被浏览器正确解析,否则是没有办法播放的。

下面列出了另外两种封装格式下浏览器能直接解码的音视频编码组合:

  • WebM :使用 VP8 视频编解码器和 Vorbis 音频编解码器
  • Ogg:使用 Theora 视频编解码器和 Vorbis音频编解码器

浏览器支持的格式

对于video标签来说,浏览器支持视频播放的封装格式有:MP4、WebM和Ogg。其中我们就MP4来说,必须使用h.264编码的视频和aac编码的音频,才能被浏览器正确解析,否则是没有办法播放的。

下面列出了另外两种封装格式下浏览器能直接解码的音视频编码组合:

  • WebM :使用 VP8 视频编解码器和 Vorbis 音频编解码器
  • Ogg:使用 Theora 视频编解码器和 Vorbis音频编解码器

C++音视频开发学习资料:点击领取→音视频开发(资料文档+视频教程+面试题)(FFmpeg+WebRTC+RTMP+RTSP+HLS+RTP)

适合媒体串流中的封装格式

由于在媒体串流的过程中,客户端是需要源源不断接受来自外界传输的音视频,并且需要播放已经接受到的部分,后文中把这种特殊的媒体简写为流媒体

而不论是MP4还是WebM还是Ogg都是需要等待完整的数据传递完成后才能够开始播放,并且不能将多个音视频进行无缝连接播放,所以这三种格式统统无法没流媒体利用,凉凉。

因此我们需要其他更加适合串流的媒体封装格式,这里主要介绍下面两种,为后文作铺垫。

FLV(Flash Video)

FLV格式的流中, 每一个音视频数据都被封装成了包含时间戳信息头的数据包。在传输时,只需要当播放器拿到这些数据包解包的时候能够根据时间戳信息把这些音视频数据和之前到达的音视频数据连续起来播放。

而MP4,MKV等等类似这种封装,必须拿到完整的音视频文件才能播放,因为里面的单个音视频数据块不带有时间戳信息,播放器不能将这些没有时间戳信息数据块连续起来,所以就不能实时的解码播放。

TS(Transport Stream)

就如TS(传输流)的命名,似乎天生就是为了流媒体而生的一种封装格式,其特点是多个TS片段可以被播放器无缝拼接进行播放,无需等待重新载入。不过TS的实现相对FLV要复杂许多,在此不再说明,这里我们简单知道它的特点就可以了。

Web音视频串流的协议

RTMP(Real Time Messaging Protocol 实时信息控制协议) RTMP是 Adobe Systems 公司为 Flash 播放器和服务器之间音频、视频和数据传输开发的开放协议, 该协议在国内直播平台中较为普及。 RTMP 是一种基于TCP进行实时流媒体通信的网络协议,主要用来在 Flash 平台和支持 RTMP 协议的流媒体服务器之间进行音视频和数据通信。RTMP协议下可以用来拉流,也可以进行退流。在浏览器中并不支持RTMP协议,只能通过Flash插件进行处理。RTMP传输是所支持的媒体格式为FLV。 主播 ==> MediaServer ==> 观众

HTTP-FLV

这种协议主要是为了让原本只能在RTMP中进行传输的FLV音视频流也能够在HTTP下进行传输。主要是用于FLV能够在浏览器页面中进行播放,由于HTML的Video不直接支持Flv格式的音视频,所以在早期需要在网页中加入Flash插件才能够播放。目前大量的流媒体服务器 Media Server都支持了将FLV格式流通过HTTP-FLV的形式对外界进行开放。

HLS

HLS(HTTP Living Stream) 是一个由苹果公司提出的基于 HTTP 的流媒体网络传输协议。 HLS 的工作原理是把整个流分成一个个小的基于 HTTP 的文件来下载,每次只下载一些。当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。在开始一个流媒体会话时,客户端会下载一个包含元数据的 extended M3U (m3u8) playlist文件,用于寻找可用的媒体流。

来解释一下这张图,从左到右讲,左下方的inputs的视频源是什么格式都无所谓,他与server之间的通信协议也可以任意(比如RTMP),总之只要把视频数据传输到服务器上即可。这个视频在server服务器上被转换成HLS格式的视频(既TS和m3u8文件)文件。细拆分来看server里面的Media encoder的是一个转码模块负责将视频源中的视频数据转码到目标编码格式(H264)的视频数据。转码成H264视频数据之后,在stream segmenter模块将视频切片,切片的结果就是index file(m3u8)和ts文件了。图中的Distribution其实只是一个普通的HTTP文件服务器,然后客户端只需要访问一级m3u8文件的路径就会自动播放HLS视频流了。

说说m3u8文件

m3u8的命名来源是m3u文件 + utf-8编码而来,两者的文件内容是完全一样的。下文中直接称为m3u

m3u (移动图像专家组音频层3统一资源定位器)

m3u实际上就是一个索引文件,其中可以记录TS文件地址,客户端会按照下载的顺序进行连续播放。

对于一个记录了TS的文件M3U的文件内容如下

#EXTM3U // 声明文件为M3U,必须写在第一行
#EXT-X-PLAYLIST-TYPE:VOD // 当前播放类型为点播
#EXT-X-TARGETDURATION:10 //每个视频分段最大的时长(单位秒)
#EXTINF:10, //下面ts切片的播放时长
2000kbps-00001.ts //ts文件路径
#EXTINF:10,
2000kbps-00002.ts
#ZEN-TOTAL-DURATION:20
#ZEN-AVERAGE-BANDWIDTH:2190954
#ZEN-MAXIMUM-BANDWIDTH:3536205
#EXT-X-ENDLIST // m3u结束指令

不光如此,m3u还可以记录二级m3u的文件的地址。

下面是一个记录了文件地址的m3u8内容

#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2128000
drawingSword(1080p).m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1064000
drawingSword(720p).m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=564000
drawingSword(480p).m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=282000
drawingSword(360p).m3u8
#EXT-X-ENDLIST 

bandwidth指定视频流的比特率,PROGRAM-ID表示资源的ID,每一个#EXT-X-STREAM-INF的下一行是二级index文件的路径,可以用相对路径也可以用绝对路径。例子中用的是相对路径。这个文件中记录了不同比特率视频流的二级index文件路径,客户端可以当前环境的网络带宽,来决定播放哪一个视频流。也可以在网络带宽变化的时候平滑切换到和带宽匹配的视频流。

HLS目前的不足 由于HLS需要将采集到的音视频进行分片、客户端也需要对接受到的分片后的音视频进行合并处理,因此相对来时会存在比较大的延迟,大概会达到 10s左右。

HLS在浏览器中的兼容情况

事实上,HLS 在 PC 端仅支持safari浏览器,而其他大部分PC浏览器使用HTML5 video标签由于无法解析TS所以不能直接播放(需要通过hls.js)。移动端不论是安卓还是IOS统统都原生支持HLS。这点主要是由于HLS是由Apple公司推广的,苹果自家的浏览器上都是支持的,而安卓也进行了跟进。所以如果想要在PC浏览器上使用到HLS,仍然需要使用其他技术手段才能实现。

各协议总结:

Web音视频串流实践方案(WebSocket + RTMP)

这里简单介绍一种在网页中进行音视频串流的方案: 把RTMP推流的工作放到中间服务层(此次以Node为例)去,而拉流通过流媒体服务器开放的HTTP-FLV,并在播放前使用Flv.js将转换后的流数据喂给Video去解析播放。

FFmpeg:一款处理音视频非常有效的工具, 这款工具提供以命令行的方式去对视频进行转码、转封装格式、增加水印等等功能其中还包括了RTMP推流的功能。同时FFmpeg也为Node提供了一些控制的Bridge,在后文中,我会在中间层使用Node来控制FFmpeg进行音视频的推流。

STEP1:推流客户端 => Node中间处理层

这里有包括两种推流的音视频源,一种是实时录制自己的摄像头进行推流。另外一种是使用本地的视频文件进行发送。这里我们分开来讲

对于推流客户端推送实时录制的音视频数据时,其核心操作就用过浏览器来调用摄像头数据,并通过MediaStreamRecorder.js去捕获音视频二进制数据(Blob)注意此处每个时间片返回一个blob,获得当前时间片的Blob后通过WebSocket将blob数据传递给Node中间层。

而对于推流客户端推送视频格式的文件时,需要做的就是将视频文件按照每段时间的视频量进行分片。例如对于一个100s的视频,如果按照每段blob需要发送4s的数据量,那就需要分为25段blob,这些可以通过前端去进行分片,分片发送的中间Node层。后面的操作就和摄像头推流一致了。

STEP2:Node中间处理层 => 流媒体服务器

在Blob数据抵达Node中间层后会被转化为Buffer,在Node层我们需要做的这些分段的视频格式转化为ts格式的片段,再将ts片段(这里就利用到了TS能够无缝拼接进行播放的特性,能够让ffmpeg推送持续的流媒体)通过ffmpeg将持续不断接受到的TS格式的流媒体转化为Flv流并通过RTMP推流到流媒体服务器上。

C++音视频开发学习资料:点击领取→音视频开发(资料文档+视频教程+面试题)(FFmpeg+WebRTC+RTMP+RTSP+HLS+RTP)

流媒体服务器是在Node.js环境下通过node-media-server第三方包进行搭建。Node-media-server许多不同协议的推流和拉流的方法。其中它支持外界通过RTMP的方式进行推流拉流(端口1935),也支持将RTMP流转换为HTTP-FLV协议的流对外开放(端口8000)。通过Node-media-server建立一个流媒体服务步骤也很简单,只需要如下代码:

const NodeMediaServer = require('node-media-server');

const config = {
  rtmp: {
    port: 1935,
    chunk_size: 60000,
    gop_cache: true,
    ping: 30,
    ping_timeout: 60
  },
  http: {
    port: 8000,
    allow_origin: '*'
  }
};

const nms = new NodeMediaServer(config)
nms.run();

在Node-media-server中,提供了通过使用不用的URL路径来对流进行区分。这里贴上一个官方提供的URL格式

rtmp://hostname:port/appname/stream
http://hostname:port/appname/stream.flv

例如对于音视频流A,它的URL是这样的: rtmp://47.110.88.142:1935/live/root_14465 可以看出对于这个流,appName这里被命名为了live, 而stream被命名为了root_14465。对应的,如果想通过HTTP-FLV进行拉这条流,可以通过下面这条URL: http://47.110.88.142:8000/live/root_14465.flv 在完成流媒体服务器的搭建后,不同用户会生成对应不同的推流URL,只要为观众发放正确对应的拉流URL就会播放正确的流数据。实现了并行串流的目的。 本地演示:

  1. 起流媒体服务器
  2. 通过ffmpeg推流
  3. 通过http-flv拉流

STEP3: 流媒体服务器 => 拉流客户端

通过Http-flv进行传输,浏览器的video标签通过http获取到flv流后,使用Flv.js【后文中介绍】进行转换封包格式后为MP4后便能够持续播放。

Flv.js

在实现过程中,我们用到了flv.js, 这是B站开源的一款媒体流转码插件,该插件能够利用Js将接受到的HTTP-FLV实时转码为Video能够接受的MP4格式。

得益于浏览器提供了Media Source Extensions API(MSE),使得flv.js能够通过JavaScript来对流数据格式进行转换,并分片为

这里我们贴一段flv.js的简单的使用代码

<script src="flv.min.js"></script>
<video id="videoElement"></video>
<script>
    if (flvjs.isSupported()) {
        var videoElement = document.getElementById('videoElement');
        var flvPlayer = flvjs.createPlayer({
            type: 'flv',
            url: 'http://example.com/flv/video.flv'
        });
        flvPlayer.attachMediaElement(videoElement);
        flvPlayer.load();
        flvPlayer.play();
    }
</script>

Flv.js不足

MSE目前在PC端浏览器上支持较好,但是一些较低版本的移动端流览器就不是那么理想了如图:

由于Flv.js是基于MSE制作的,所以一些低版本移动端流览器中是无法正常播放的,因此在考虑兼容性的情况下需要慎用。 关于WebRTC和音视频会议 我们不难发现市场已经出现了一种新兴的平台 - Web视频会议,用户直接通过PC浏览器即可加入音视频会议。

我们知道移动端的浏览器由于种类繁多并不能较好的适配,因此不被推荐直接在移动端浏览器中使用web视频会议

音视频会议的思考

那让我们从音视频串流的角度来考虑,视频会议就是让传统的单向直播变化为了双向直播,即每个参与者即需要推流,也需要拉流。例如下图,3位参会者,服务器就需要接受3条推流和6条拉流,显然这样对流媒体服务器的压力过于庞大,并且还有不可忽视的延时问题。

大部分主流浏览器为开发者开放了可以开箱即用WebRTC - API,可以通过执行API就能呼叫指定的Peer并建立连接。但需要注意使用WebRTC技术虽然音视频数据不经过服务端传输,但是仍然需要服务端去交换一些连接的必要信息。我们在开头所说的两款Web音视频会议产品就是通过WebRTC实现的。

WebRTC技术的工作流

WebRTC更适合用来做Web视频会议的原因就是它能够实现浏览器和浏览器之间进行音视频的传输

这其中的传输过程如图。这里面的PeerN指的是连接的浏览器客户端,在多个Peer连接之前,每个Peer需要和信令服务器(Signaling Server)进行连接,这里面提到的信令服务器需要由开发者自行搭建。 可以看到Peer与 信令服务器的连接是双向的,这是因为连接的各方需要通过信令服务器交换一些关键信息,这些信息都会以信令的信息发送和接受。 Peer之间主要需要交换下面3种类型的信息

  • 初始化和关闭通信,及报告错误;
  • 用户WebRTC的的IP和端口号
  • 当前浏览器支持播放的音视频编码及封装格式,以及能播放的最高分辨率等信息。

其中需要重点关注第二点,因为需要交换各个Peer之间的IP来进行Peer之间的连接,所以要保证Peer之间是要能够正确访问到对方ip的,如果所有的Peer都是在同一个局域网下没有问题,但是如果参会的Peer来自不通的局域网,那么他们交换的IP是无法访问到的。 所以在这里还需要增加一个借助另一种服务器(称为STUN server)实现NAT/Firewall穿越。主要做的工作就是将用户交换IP的过程中需要把根据局域网IP生成一个公网IP,这样就实现了公网环境的传输。

最后

我们在文章中了解了Web传统的音视频串流、初窥了新兴的WebRTC技术,这两项技术能力其实也对应着两种不同的应用场景。前者辅以CDN更符合面向观众的直播场景,后者适合中小型的音视频会议的场景,短期来看WebRTC无法代替传统音视频串流。