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

抖音直播原理解析如何在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

女子110万买基金亏48万,获赔30万北京一女子在光大银行花110万元买基金,3年亏损48万元,于是索赔本金及利息,一审被驳回诉求,二审最终获赔30万元。事情是这样的,2015年4月份,北京一女子有110万元的存款,为毕马威中国林启华消费品零售企业积极践行ESG有助于品牌和差异化竞争优势的建立中证网讯(记者黄一灵)近日,毕马威中国发布第二届新国货50企业报告,通过研究和分析消费新潮及国货品牌在ESG领域的价值与前沿经验,助力企业追求长期价值,实现可持续发展。报告显示,产新学期购机三星Galaxy智能手机助你成为校园主角天气逐渐转暖,寒假即将过去,各大高校都将迎来开学季。不少同学也在近期开始为即将到来的新学期作准备。俗话说工欲善其事必先利其器,在新学期想要拥有新气象,为自己日常使用的装备进行升级是开学季换机怎么选?荣耀80SE线下体验后有答案随着开学季的临近,越来越多的网友开始关注起两千价位段机型,毕竟这一价位段机型可供挑选的机型有很多。就以最近热度较高的荣耀80SE来说,就不失为一款不错的机型,恰好我近期也是趁着假期真抓实干各地推进经济高质量发展央视网消息(新闻联播)新春伊始,各地真抓实干,拼经济抓发展,把新兴产业数字经济等方面作为发力点,开拓创新,推动经济高质量发展。新一年,培育发展战略性新兴产业集群成为各地高质量发展的CASETiFY推出情人节系列手机壳,个性表达在一起好配CASETiFY情人节系列已于品牌官网CASETiFY。cn,CASETiFY天猫官方旗舰店以及线下门店CASETiFYSTUDiO上海新天地(上海市黄浦区马当路245号B138BH610主板能配什么处理器?H610芯片组是12代平台中最入门的芯片组,大部分H610芯片组也十分便宜,价格基本在500800元之间,对比B660和Z690以及同为lGA1700的B760和Z790真是便宜了消息称OPPOFindX6系列暂定3月下半月发布IT之家2月7日消息,据数码博主数码闲聊站今日爆料,OPPOFindX6系列暂定3月下半月发布。新机爆料显示,OPPOFindX6玻璃版裸机厚度约为9。2mm,主摄位IMX890,新品发布FireFlyDrone无人机外场电源P602FireFlyDrone无人机外场电源P602满足无人机全天使用需求可为大疆经纬M300RTK充电12次可为大疆经纬M30系列充电22次可为大疆御3全系列充电75次可为游戏笔记本充经济工作方法论系列述评之八南昌把拼经济摆在最突出位置视频加载中市委经济工作会议鲜明提出,要把项目为先实干奋进,争分夺秒拼经济作为贯穿全年工作的主线,这既是贯彻落实中央省委关于经济工作的重大决策部署,又是针对当前时不我待催人奋进的发展GTX1660和2060系列停产,继任者30503060一言难尽,性能还倒退去年年底的时候,NV针对2016几个系列基本已经确定停产,即关于RTX2060S2060GTX1660S1660四个系列已经全面停掉了产线,直到消化库存截止。也就是说这几款显卡以后
是什么让老实人瞬间变身杀人恶魔他是我的老乡,杀人,死缓。简单的几个字,看起来很平淡,却是那么冷酷。人的一生很短,但是留给他的痛苦却很长。他是个小商贩,与老婆每天起早贪晚地经营着自己的生意,与世无争,与人无隙,生在洁净的时光里与往事对坐不知道为什么,最近常常想起我姥娘家那个小山村里的那条小溪。村里有河,河水很清,但是因为姥娘家在山脚下,离河挺远,所以平时洗衣服总是到家附近的小溪里去。记忆中的小溪流,从山上一路欢唱希望我所拼命争取的,最后都能如我所愿希望我所拼命争取的,最后都能如我所愿。心IhopeeverythingIvefoughtforwillturnouttobewhatIwant。心机是用来保护自己而不是拿去伤害别人文旅IP频出圈,济宁网红打卡地都有啥?最近,济宁不少文旅IP在社交媒体和短视频平台上火出圈围炉煮茶的环西北里历史感科技感并存的孔子博物馆沉浸式探寻儒家文化的尼山圣境桨声灯影人头攒动的运河夜游小众浪漫又安静的网红书店伴随首届红旗陶瓷艺术设计邀请展正式启动视频加载中中国德化2023。2。222月22日,首届红旗陶瓷艺术设计邀请展正式启动,以薪火红旗光耀瓷都为主题,由福建省美术家协会德化县陶瓷发展委员会共同主办,福建德化瓷都文旅投资有逃不了的年利率35。9!唐宁竟是这么为穷人放贷的?在宜人金科旗下的宜享花App上,读懂君获得了近几年价格最高的一笔贷款额度年利率35。9。不过,宜人金科也提供了多种降息方案,比如在极其显眼的位置一项名为省钱礼包的产品,勾选后年利率案例方太儒学治企的实践与创新方太将中式理念与西方方法融会贯通,用儒家的仁义之道审视和翻新了西方管理模式,使道术一体,知行合一。文钱丽娜IDBMR2004改革开放以来,中国企业逐渐走出了一条具有中国特色的发展之天狮集团天狮人的使命,健康人类,服务社会历经27年的发展历程,天狮集团始终率先践行一带一路倡议,成为横跨生物科技健康管理酒店旅游教育培训电子商务国际贸易高等教育等领域。业务遍及224个国家和地区在110个国家和地区设有分社保代缴员工托管,迪柯尼IPO意欲何为?多重压力之下,迪柯尼将何去何从?来源经理人传媒旗下经理人杂志全媒体记者何雯雯来源pexels近日,广州迪柯尼服饰股份有限公司(以下简称迪柯尼)更新了招股书,拟在深市主板上市。作为中一旦股票出现ampampquot仙人指路ampampquot形态,主力已洗盘完毕,股价将喷发式上涨作为大众投资理财方式之一的股票投资,已经得到广大投资者的认可,投资股票市场也已经成为一种时尚。投资者都想在股市中挣大钱,但作为一种投资,有赚就必然有赔,而且赔钱的比例往往比较大。也美股开盘道指纳指涨逾百点中概多数走高阿里巴巴涨近5金融界2月23日消息,投资者权衡GDP等经济数据并等待美联储官员讲话,同时企业业绩强劲及美联储纪要在一定程度上减轻了市场对于美联储未来货币政策担忧,美股集体高开,道指纳指涨逾百点,