范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

抖音直播原理解析如何在Web中播放FLV直播流

  抖音相信大家都听说过,但是知道有 Web 版抖音 的人可能要少一些,和 TikTok 一样抖音也有 Web 版本,可以让我们在浏览器中就可以刷短视频和观看抖音直播。抖音是如何实现在浏览器中直播的呢?本篇文章来解析抖音直播的技术原理。 调试
  首先点击 https://live.douyin.com 进入抖音直播页面。
  然后随便进入一个直播间并打开开发者工具,查看播放器相关 DOM 结构,如下图所示。
  首先可以发现原来抖音也是使用的 xgplayer。另外还可以发现 video  元素的 src  属性是 blob:  开头的视频地址,和我们平时用 video  元素播放的视频有点不一样,要了解为什么视频地址是 blob:  开头的,就需要了解接下来介绍的 MSE API。 Media Source Extensions 介绍
  Media Source Extensions API(MSE)媒体源扩展 API 提供了实现无插件且基于 Web 的流媒体的功能,不同于简单的使用 video  元素,video  元素对于开发者来说完全是一个黑盒,浏览器自己去加载数据,加载完了自己解析,解码再播放,这个过程中开发者无法进行任何操作。利用 MSE API 开发者可以自定义获取流媒体数据并且还可以对数据做一些操作。
  MSE 的兼容性如下图所示。
  可以发现 MSE 的兼容性还算可以,IE 11 都支持。但是号称现代 IE 的 Safari 浏览器的 iphone 版,到现在都还不支持 MSE API,应该是苹果想推广自家的 HLS 协议吧,让你在 iphone 设备上播放流媒体只能用他家的协议。
  MSE API 主要有 MediaSource  和 SourceBuffer  两个对象,MediaSource  表示是一个视频源,它下有一个或多个 SourceBuffer ,SourceBuffer  表示一个源数据,比如一个视频分为视频和音频,我们可以创建两个 SourceBuffer  一个用于播放视频,一个播放音频,MSE 架构图如下所示。
  通过上图还可以发现 SourceBuffer  下面还细分了 TrackBuffer ,因为你还可以不创建两个 SourceBuffer ,只用一个 SourceBuffer  来播放视频和音频,让它内部自己分离音视频,用不同的解码器进行解码播放。
  使用 MSE 播放视频的流程如下图所示。
  首先我们使用 fetch 或 XHR 去下载数据,然后做些处理过后,将数据交给 MediaSource ,最后通过 video  元素进行播放,
  如何将 MediaSource  和 video  元素连接呢?这就需要用到 URL.createObjectURL  它会创建一个 DOMString  表示指定的 File  对象或 Blob (二进制大对象) 对象。这个 URL 的生命周期和创建它的窗口中的 document  绑定。这就是为什么上面调试中的 video  元素的 src  是一个 blob  开头的字符串。
  下面来看看使用 MSE 播放视频的最小代码。 const video = document.querySelector("video")const mediaSource = new MediaSource()  mediaSource.addEventListener("sourceopen", ({ target }) => {    URL.revokeObjectURL(video.src)    const mime = "video/webm; codecs="vorbis, vp8""     const sourceBuffer = target.addSourceBuffer(mime) // target 就是 mediaSource     fetch("/static/media/flower.webm")         .then(response => response.arrayBuffer())         .then(arrayBuffer => {             sourceBuffer.addEventListener("updateend", () => {                if (!sourceBuffer.updating && target.readyState === "open") {                     target.endOfStream()                     video.play()                 }             })             sourceBuffer.appendBuffer(arrayBuffer)         }) })  video.src = URL.createObjectURL(mediaSource)
  addSourceBuffer  方法会根据给定的 MIME 类型创建一个新的 SourceBuffer  对象,然后会将它追加到 MediaSource  的 SourceBuffers  列表中。
  我们需要传入相关具体的编解码器(codecs)字符串,这里第一个是音频(vorbis),第二个是视频(vp8),两个位置也可以互换,知道了具体的编解码器浏览器就无需下载具体数据就知道当前类型是否支持,如果不支持该方法就会抛出 NotSupportedError  错误。更多关于媒体类型 MIME 编解码器可以参考 RFC 4281。
  这里还在一开始就调用了 revokeObjectURL 。这并不会破坏任何对象,可以在 MediaSource  连接到 video  后随时调用。它允许浏览器在适当的时候进行垃圾回收。
  视频并没有直接推送到 MediaSource  中,而是 SourceBuffer ,一个 MeidaSource  中有一个或多个 SourceBuffer 。每个都与一种内容类型关联,可能是视频、音频、视频和音频等。 HTTP-FLV 介绍
  了解了 Web 环境是如何播放流媒体,现在来看看抖音直播是使用的什么流媒体协议吧。打开开发者工具的网络面板,如下图所示。
  可以发现抖音直播使用的是 HTTP-FLV 协议,其实不看也知道抖音使用的是 HTTP-FLV,因为国内直播平台全部都使用 HTTP-FLV!所以国内直播基础建设对 HTTP-FLV 支持比较好。但是在国外 HTTP-FLV 几乎没有人用,国外用的最多的是 HLS 和 DASH 协议。
  FLV(全称 Flash Video)是一种流媒体格式,由 Adobe 公司开发,并在 2003 年发布。它的出现有效的解决了视频文件在网络上传播放的问题,在当时它是实际意义的 Web 流媒体标准,非常多的流媒体平台都使用它来播放视频。
  但是随着技术的进步, HTML5 的 Video 元素,已经替换 Flash 视频播放,目前 Flash 技术已经被弃用,各大流媒体平台也切换到了 HLS 或 DASH 技术来实现 Web 流媒体播放。虽然 Flash 被弃用,在国外 FLV 也几乎没人使用,但是在国内它并没有被弃用,反而被广泛用于国内直播场景,所以了解 FLV 格式还是很有必要的。
  要在 Web 环境拉取 flv 直播流,不能使用 XHR,需要使用 fetch  API 去拉流,因为 HTTP-FLV 会用到 HTTP/1.1 的 chunked transfer encoding 功能流式去加载数据,是客户端和服务器建立起一个 HTTP 连接后保持连接不断开,服务器不断发送直播流数据给客户端,类似于 IM 中的长轮询。
  下面是使用 fetch  拉流的实例代码。 fetch("./a.flv")     .then((res) => {        const reader = res.body.getReader()        const pump = async () => {            const data = await reader.read();            if (!data.done) pump();                     }        pump()     })
  可能大家还听过 WS-FLV,这是使用 WebSocket 去拉 FLV 流,相比 HTTP-FLV 没啥优势,所以开始尽可能使用 HTTP-FLV。在我看来 WS-FLV 唯一的作用是兼容 IE 11 浏览器,因为 IE 11 是不支持 fetch  的,并且 IE 自带的 MSStream  又有很多问题,这时候只有用 WebSocket 去拉流。 FLV 格式
  接下来让我们再更深入了解下 FLV 文件格式,FLV 格式的文件构成是比较简单的,整个文件是由一个文件头和一个文件体组成,文件体是由一个个标签组成。 FLV 文件头
  FLV 文件由 9 个字节的文件头开始,FLV 文件头结构如下表所示。
  字段
  类型
  描述
  签名
  UI8
  字节 0x46  表示字符 F
  签名
  UI8
  字节 0x4C  表示字符 L
  签名
  UI8
  字节 0x56  表示字符 V
  版本
  UI8
  该 FLV 文件版本
  保留
  UB[5]
  5 个比特的保留段,必须为 0
  音频标识
  UB[1]
  1 比特,表示该文件是否存在音频
  保留
  UB[1]
  1 比特的保留段,必须为 0
  视频标识
  UB[1]
  1 比特,表示该文件是否存在视频
  数据偏移
  UI32
  表示文件体在整个文件的偏移,一般为 9,也就是文件头的大小 FLV 文件体
  FLV 文件头之后就是文件体,文件体是由上一个 FLV 标签大小和 FLV 标签循环组成,如下表所示。
  字段
  类型
  描述
  前标签大小
  UI32
  总是为 0,因为它之前没有 FLV 标签
  FLV 标签
  FLVTAG
  第一个 FLV 标签
  前标签大小
  UI32
  第一个 FLV 标签大小
  ...
  ...
  ...
  最后一个 FLV 标签
  FLVTAG
  最后一个 FLV 标签
  前标签大小
  UI32
  最后一个 FLV 标签大小
  需要注意的是,FLV 标签大小是标签它之前的 FLV 标签大小,所以第一个标签大小总是为 0 。
  一共有 3 种类型的 FLV 标签,FLV 标签如下表所示。
  字段
  类型
  描述
  标签类型
  UI8
  8  表示音频, 9  表示视频, 18  表示脚本数据
  数据大小
  UI24
  数据字段的大小
  时间戳
  UI24
  该标签数据表示的毫秒单位时间戳,如果是第一个标签则为 0
  高位时间戳
  UI8
  表示高位字节
  流 ID
  UI24
  总是为 0
  数据字段
  DATA
  该标签中的数据
  FLV 标签中的数据字段的结构会因为标签的类型不同而不同,音频标签数据字段为 AUDIODATA ,视频标签为 VIDEODATA ,脚本数据标签为 SCRIPTDATAOBJECT 。 FLV 音频标签
  音频 FLV 标签数据字段结构如下表所示。
  字段
  类型
  描述
  音频类型
  UB[4]
  该音频数据的类型
  2  为 MP3
  7  为 G711 A-law
  8  为 G711 mu-law
  10  为 AAC
  音频采样率
  UB[2]
  0  表示 5.5kHz
  1  表示 11kHz
  2  表示 22kHz
  3  表示 44kHz
  (对于 AAC 编码将一直是 3 )
  音频位深
  UB[1]
  0  表示 8Bit
  1  表示 16Bit
  音频声道
  UB[1]
  0  表示单声道
  1  表示立体声
  (对于 AAC 编码将总是 1 )
  音频数据
  DATA
  如果是 AAC 编码为 AACAUDIODATA ,否则音频数据根据音频编码不同而不同
  对于常用的 AAC 编码的音频数据,FLV 规范还定义了 AACAUDIODATA  数据结构,如下表所示。
  字段
  类型
  描述
  AAC 包类型
  UI8
  描述接下来 AAC 数据的类型
  0  为 AAC 配置
  1  为 AAC 帧数据
  AAC 数据
  UI8[n]
  如果 AAC 包类型是 0  为 AudioSpecificConfig ,1  为 AAC 帧数据 FLV 视频标签
  视频 FLV 标签数据字段结构如下表所示。
  字段
  类型
  描述
  帧类型
  UB[4]
  1  表示 I 帧
  2  表示非 I帧
  编码 ID
  UB[4]
  视频编码 ID,7  表示 AVC 编码
  视频数据
  DATA
  根据编码 ID 不同而不同,7  为 AVCVIDEOPACKET
  编码 ID 一般为 7  表示 AVC 编码,官方规范是不支持 HEVC 编码的,但是现在 HEVC 编码越来越流行,所以社区一般把编码 ID 12  定义为 HEVC 编码。
  AVCVIDEOPACKET  表示 AVC 视频数据结构,它的结构如下表所示。
  字段
  类型
  描述
  AVC 数据类型
  UI8
  0  表示视频配置 AVCDecoderConfigurationRecord
  1  表示一个或多个 NAL
  2  表示 AVC 序列结束
  CTS
  SI24
  有符号整数,毫秒,表示该帧 PTS 和 DTS 时间差
  AVC 数据
  UIB[n]
  AVC 数据类型为 0  表示 AVCDecoderConfigurationRecord  数据
  1  表示一个或多个 NAL 数据
  关于 AVCDecoderConfigurationRecord  数据结构,请查看 ISO 14496-15 的第 5.2.4.1 章节。 FLV 数据标签
  FLV 视频元数据存放在 FLV 数据标签里面,它的结构如下表所示。
  字段
  类型
  描述
  对象
  SCRIPTDATAOBJECT[]
  多个脚本数据对象
  结束
  UI24
  总是为 9 ,表示结束
  SCRIPTDATAOBJECT  描述的是一个对象,它由一个键值对组成,结构如下表所示。
  字段
  类型
  描述
  键
  SCRIPTDATASTRING
  对象键
  值
  SCRIPTDATAVALUE
  对象值
  键和值的数据结构如下表所示。
  字段
  类型
  描述
  类型
  UI8
  该键或值的类型是什么
  数组长度
  UI32
  如果是数组类型,这里是数组长度
  具体数据
  TYPE
  具体的数据,根据类型不同而不同
  数据终止符
  TYPE
  如果类型是 3  或 8 ,表示对象和数组的终止
  FLV 文件的元信息一般放在 onMetaData  字段中,解析完成 FLV 数据标签后将返回下面这个对象。 interface FLVScriptData {     onMetaData?: {         duration?: number;         width?: number;         height?: number;         videodatarate?: number;         framerate?: number;         videocodecid?: number;         audiosamplerate?: number;         audiosamplesize?: number;         stereo?: boolean;         audiocodecid?: number;         filesize?: number;     } }
  onMetaData  对象的字段含义如下。 duration  是视频的总时长,单位是秒。 width  是视频的宽度,单位是像素。 height  是视频的高度,单位是像素。 videodatarate  是视频的码率,单位是 kb 每秒。 framerate  是视频的帧率。 videocodecid  是视频的编码 ID,同 FLV 视频标签中的编码 ID。 audiosamplerate  是音频的采样率。 audiosamplesize  是音频的位深。 stereo  表示是否为立体声。 audiocodecid  是音频的编码 ID,同 FLV 音频标签中的编码 ID。 filesize  是文件的大小,单位是字节 FMP4 格式
  MP4 格式相信大家都听说过,MP4 或称 MPEG-4 第 14 部分是一种标准的数字多媒体容器格式,它被定义在 ISO 14496-14 中,是由苹果的 QuickTime 视频格式演化而来(也就是我们常见的 .mov  视频格式)。
  FMP4 是 fragmented MP4 的缩写,FMP4 更适合流媒体传输,它们的区别如下所示。
  这是一个普通的 MP4 文件,可以看到它有一个很大的 mdat  (实际电影数据)box ,所有视频元信息都存放在 moov  盒子,所有音视频数据都存放在 mdat  盒子,所以 mp4 格式并不适合流媒体传输。
  这是 fragmented MP4 的截图,它是由 ISO BMFF 初始化分片(ftyp  后跟单个电影标题盒子 moov ),加上一个个 moof  和 mdat  盒子组成的视频分片组成,它的元信息和音视频数据分散到一个个的 moof  和 mdat  盒子中,一次性只加载需要展示的部分,有点类似于前端的瀑布流分页的数据加载。
  因为 MP4 格式比 FLV 复杂的多,这里篇幅有限就不再详细介绍了,感兴趣的同学可以去看看 ISO 14496-12。 视频格式
  上面之所以介绍 FMP4 格式是因为 MSE API 并不是所有视频格式都支持(比如上面介绍的 flv,或者普通的 mp4 格式就不会支持)根据浏览器的不同,可能支持的视频格式也不同,但是 FMP4 格式所有的浏览器都支持,更多信息可以查看 ISO BMFF Byte Stream Format。
  上面介绍的 FLV、MP4、FMP4、MOV 这些全都是视频封装格式,他们就像一个盒子来存放真正的音视频流数据。
  所以要在浏览器中播放 flv 直播流,还需要将 flv 视频格式转换成 fmp4 视频格式。根据上面介绍的 flv 文件格式对 flv 进行解析,这个操作一般称为解封装(demux),解析出来音视频等信息数据后,再封装(remux)成 fmp4 视频格式,最后交给 MSE API 来播放。
  如上图所示,我们需要将 FLV 格式转换成 FMP4 格式,其中的音视频流是不变的,这个操作也称为转封装。 整体播放流程
  那么在 Web 中播放 HTTP-FLV 直播流的整体流程如下所示。 首先使用 fetch  去拉 flv 直播流。 使用 HTTP/1.1 的 chunked transfer encoding 功能,流式下载视频 chunk 片段。 使用 FlvDemuxer  流式解封装 flv 视频流。 对视频流进行修复做音视频同步。(一些音视频流可能会有问题) 使用 FMP4Remuxer  将视频流封装成 FMP4 格式。 最后将封装好的 FMP4 片段数据交给 MSE 播放。
  上面 FlvDemuxer  和 FMP4Remuxer  的代码需要自己根据 flv 和 fmp4 文件格式编写,将 flv 中的每一帧的音频、视频和元信息都解出来,然后再将它们封装成 fmp4 格式。 总结
  本篇文章讲解抖音直播的技术原理,它是使用 HTTP-FLV 来播放直播流,不光是抖音在使用 HTTP-FLV 直播方案,国内几乎所有的直播平台都在使用 HTTP-FLV 方案,所以看完这篇文章相当于了解了国内所有平台的直播技术直播原理。不过各个平台会在 HTTP-FLV 基础上加点自己的东西,例如斗鱼直播还使用了 P2P 技术来节省服务器流量。相比和其他平台用一样直播方案的抖音直播,抖音短视频播放原理其实更有意思,下次将分享抖音短视频技术原理。
  作者:羽月
  来源:微信公众号:羽月技术
  出处:https://mp.weixin.qq.com/s/6qDBhjHk0ejzAg_kCkDEWw

简单应对秋燥困扰,万物皆可凉白开霜降是秋季的最后一个节气,秋末入冬冷空气逐渐活跃起来,吹的多是更为干冷的偏北风,通常会越吹越干正式进入冬季之时,人体已经适应了干燥的环境,所以燥的感觉并没有秋末明显,但不知不觉间,健康科普洗澡禁忌要记清洗澡禁忌要记清西安交通大学医学院第一附属医院脑血管病防治中心教授白羽在接受记者采访时说,老年人自己也要注意合理的膳食结构,要想长期维持自己的生活自理能力,必须加强身体的锻炼,增强自安翰科技立冬后胃疾病多发,磁控胶囊胃镜助您舒适查胃孝经纬曰斗指乾,为立冬,冬者,终也,万物皆收藏也。又有老话说得妙,冬至吃饺子,不冻耳朵。让我们跟着本草纲目学菜谱,把养胃的好食材藏进饺子里,温暖了胃部,便能暖遍全身!第一道白菜猪肉入冬吃苦,来年不苦,建议少吃苦瓜,多吃4苦,舒服过冬立冬节气到来,意味着正式入冬了。老话常言,入冬吃苦,来年不苦,说的是入冬后,要多吃些苦味食物,这背后有什么讲究呢?这是因为在传统观点里,冬季肾经旺盛,肾主咸,心主苦,肾水克心火,多黄痰是热,干咳是燥,白痰是寒,3个中成药,清热散寒,润燥止咳嗓子有痰,黏黏腻腻的咯在喉咙处,还总是吐不完,有些人咳出来的是黄痰,有些人呢咳出来的是白痰,还比较稀还有些人呢总是干咳,没有痰。这是为什么呢?今天屈医生就从痰的颜色来给你讲清楚,并小羊入草原,内蒙古女篮出现两个有意味的变化先讨论一个问题杨舒予的篮球才华,会不会超过姐姐杨力维?从技术上来说,杨力维的穿插策应见缝插针善于抓住细微空档的能力,以及脚下速度反应,不但在国内,就算放到国际上,也是出类拔萃的。从14惨败纽卡ampampamp英超倒三!官方南安普顿主帅哈森许特尔下课直播吧11月7日讯官方消息,南安普顿主帅哈森许特尔下课。南安普顿官方表示,一线队教练鲁本塞莱斯将临时带队,出战周三的比赛。俱乐部将适时宣布新的正式主帅。昨天晚上,南安普顿主场14惨C罗怒了!连续4场首发,仅战弱旅刷1球,心急死球抱摔对手染黄在闹得沸沸扬扬的拒绝替补登场被罚禁赛停训之后,C罗最终还是大获全胜,在多方的协调之下,腾哈赫也只能做出让步,将状态和实力水准完全不配首发的C罗强行提上首发!北京时间2022年11月命中率2823,这是湖人头号战犯,浓眉球权少威少暗指主帅无能?很多球迷一觉醒来打开手机发现湖人又输了,输给东部现在的顶级强队骑士并不丢人,毕竟骑士打到现在只输了一场比赛,不过输球的方式却令球迷难以接受,湖人在上半场其实打得非常好,但到了下半场冲刺双十一,美团游戏化营销新思路又是一年双11,大促之战已经打响,各大平台和品牌纷纷开始用营销游戏抢人。淘宝的喵糖总动员京东的穿行寻宝记,各品牌旗舰店的签到小游戏,均是通过每日打卡浏览商品参与AR游戏等互动玩法,有个中国桌游团队把吃鸡游戏完美移植到了桌面上最近,一款在KS上结束众筹的桌游blacksite刚刚开始全球发货。这款桌游你在国内几乎上查不到任何信息,甚至连集石都没有收录,但它却是一款地地道道的国产原创桌游。它的设计团队叫沙
俗话说大碗喝酒,大口吃肉!排骨这4种做法,好吃到碗舔干净秋风微动,秋日的早晨空气清新,作为每日下厨的我,最喜欢的事情就是每天早晨去菜市场走一圈,最常去的就是猪肉摊,家里每天都必须要有一个荤菜,这才能满足我们全家的胃。俗话说大碗喝酒,大口钱志亮养出一个内心富足的孩子,不妨常把这5句话挂在嘴边每一个孩子都有一颗娇弱敏感的心,父母的语言,包括态度和语气,不仅决定了亲子关系的好与坏,也深深地影响了孩子内心的幸福。在日常生活中,记得常对孩子说这5句话,孩子内心一天比一天富足。30年前土埋的茅台酒,现在变成什么样了?挖出后众人沉默不语现在人们对于白酒的需求,可谓是各种各样,有些重大的纪念日或者宴会,大家都会提前准备陈年好酒,有的甚至提前几十年就开始准备,比如孩子的婚宴,好多人都会在刚出生的时候,就储存一瓶,真的荣耀X10换成荣耀X40,值不值得换?看看二者的差异就清楚了最近荣耀X40比较火,千元价位就有OLED曲面屏,而且在颜值上面也可圈可点,因此让一些老荣耀用户比较心动,想将手里的荣耀X10换成荣耀X40,对此有网友表示赞同,有网友认为这是反向华为nova10会不会是你的选择?到底值不值得?今天给大家带来新的一款手机,要是值得入手的!有没有这种小伙伴?想买华为手机价格却贵的很,动不动就五六千,一般人还是真的狠不下心来,可是还是想用。那么这一款手机或许是你最好的选择。这散文一夜桂花落如雨一夜雨落,天明初歇。怀揣心绪,走入风里,走上街头,去看看昨日欣逢的那株树,那株日日伫立街头又擦肩而过的树。金风细细,叶叶梧桐坠。叶落无声,坠入草丛,似蝶若掌,黄绿斑斓。点点雨珠,缀浙江广厦新赛季更名浙江东阳光未来五年主场落户黄龙浙江广厦将以浙江东阳光为队名出征即将开始的新赛季,未来五年球队的主场也将落户浙江省黄龙体育中心体育馆。广厦上赛季成功闯入中国男子篮球职业联赛(CBA)总决赛,但主将胡金秋赵岩昊的因山西侯马一座充满阳光的小城,安逸温暖悠哉2022年已经过去一大半,这几年,旅行成了奢望。但现实不能阻挡我们内心的渴望,压力重重的都市生活让人乏力厌倦。如果想要全身心放松,你可以选择在这座安逸的小城住下来,静享一段慢时光。走进朝鲜,绿皮火车上的美女乘务员让人眼前一亮,游客美丽大方走进朝鲜,绿皮火车上的美女乘务员让人眼前一亮,游客美丽大方。踏进朝鲜旅游,不同收入的游客可以选择多种交通工具进入朝鲜。不过对于心中有情怀的游客而言,进入朝鲜旅游必定乘坐的就是火车。走进绥阳太白带你探寻诗仙李白夜郎轶事,感受浓郁诗乡文化气息走进绥阳太白带你探寻诗仙李白夜郎轶事,阅尽大美秀丽山川,感受浓郁诗乡文化气息文刘伟地处黔北遵义的绥阳县是文化部命名的中国民间艺术诗歌之乡,乡有诗方为诗乡,诗有乡始具诗魂,走遍大地神凯特米德尔顿穿着阳光明媚的黄色连衣裙走出去即使是皇室成员也喜欢一笔好的买卖。威尔士王妃今天走出来,参加她自上个月伊丽莎白女王去世以来的首次单独活动,穿着英国品牌KarenMillen的秋季芥末黄色连衣裙。这位40岁的王妃访