前置知识
RTC在会议中具备的挑战
自有开麦
每位用户都可以自由的上下麦和开关媒体设备,且参会人数支持大规模会议需求,但是最好也可以设定一个极限值,因为RTC的发布/订阅流模型的算法复杂度是和上麦人数正相关,其值为O(n²),短时间内的高频上下麦操作会导致服务器的信令风暴,因此需求加一些上限设置,如一万、几万等;
自有布局
视频会议或者直播需要提供多种视图布局以供参会方选择,如11全屏、22四宫格、33九宫格、77四十九宫格,当然也需要有一些其他布局的调整;
但是在选择布局时,需要考虑到分辨率的问题,避免出现分辨率过剩、分辨率过小、参会者设备性能等情况的出现,即每一种布局都需要有个最合适的分辨率;
- 自有布局下的分辨率建议值
- 2*2宫格:360P --- 540P
- 3*3宫格:180P --- 270P
- 中高端手机全屏:360P --- 540P
复杂环境下的视频体验
主要是指暗光、逆光、测光等情况下继续保持合适的频率和清晰度的输出,从而避免出现效果差的情况;
其主要用到了AE算法和FaceAE算法;
AE算法是指根据自动测光系统获得当前图像的曝光量,再自动配置镜头光圈、sensor快门及增益来获得最佳的图像质量,平衡整体图片的亮度;
FaceAE算法是指当检测到人脸时,使用基于人脸的AE算法进行优化,用于解决特殊场景中的过曝和欠曝问题;
当然上述的技术还需要依赖一系列的设备系统能力,如相机技术:包括自动对焦、自动曝光等基础的相机技术;在某些特定的场景下,需要以画面中的人像为主题,此时就不能依赖于常规摄像头的平均测光逻辑,而是需要在AE算法的基础上增加人脸检测算法,当检测到人脸时就将平均测光优化为根据人脸检测结果做曝光处理,解决画面过曝、欠曝等问题; 当然了这些技术最优的方式就是完全依赖于系统底层的能力,不使用额外的算法进行逻辑处理,从而不会引入额外的性能开销;也可以结合相机美颜技术进行锦上添花;
共享屏幕时的清晰模式和流畅模式间的自动切换
屏幕共享也需要在不同场景下进行对应的特殊处理,如共享PPT等文字场景下需要保持高清晰度,对于一些非文字场景下又需要保持高流畅度,因此在程序设计时需要根据特定场景进行自动切换的逻辑兼容;但是也不是完全可以依赖代码逻辑去识别到用户共享的内容,如一些特殊的场景共享视频、共享变动较多的网页等,此时就需要额外的处理逻辑了;可以通过RTC自动识别用户传入的视频内容类型,从而不断的调整最佳的策略;
直播中的其他“必要”逻辑
主要是指
美颜、特效和虚拟背景;但是这些又会对设备性能有较大乃至极大的损耗,因此需要选择适合的正确的方案进行添加处理;常规的有如下方式:
- 由用户端加载和运行这些逻辑;
- 存在的问题是会将这些“负面”的压力给到用户端,导致对用户设备CPU性能、网络带宽和最终的安装包体积都会造成较大影响;另外对于一些复杂的逻辑会出现因为用户端极限和兼容性等问题导致运行失败的情况出现;
- 虚拟摄像头方案
- 如一些主播直播场景,会有大量的外接设备进行直播支持,其中就有自带美颜、虚拟背景的设备。因此通过这种设备采集到的流数据本身就是处理过的,不需要进行额外的处理了,但是存在的问题就是违背了「免安装即用」的设计理念
- 结合优秀的RTC技术实现
边缘渲染- 其原理就是发布者在采集到流数据之后,先发送到RTC边缘服务,由边缘服务进行云端美颜和渲染,然后再发回到发布端进行本地预览,这种情况下缺点就是会对边缘服务有一定的压力,增加了服务端的逻辑,可以参考
MCU模式的直播逻辑,此外还有就是会在原有的基础上增加了部分延时;当然逻辑处理得当是可以达到几十毫秒的,基本可以实现延时忽略的结论
- 其原理就是发布者在采集到流数据之后,先发送到RTC边缘服务,由边缘服务进行云端美颜和渲染,然后再发回到发布端进行本地预览,这种情况下缺点就是会对边缘服务有一定的压力,增加了服务端的逻辑,可以参考
底层接口浅析
- 媒体流有两大类,音频和视频
- 音频中有两种典型的场景,需要3A(回声消除、自动增益、噪声抑制等,应该设置为true)的(例如通话、演讲)和不需要3A的(语音识别、音乐应该设置为false)
- 拓展:WebRTC中
音频技术方面的两大核心技术- NetEQ:
- NetEQ = JitterBuffer + decoder + PCM信号处理
- 该模块主要包括MCU和DSP两大单元
- MCU(micro control unit, 微控制单元):负责控制从网络接收到的语音包在JitterBuffer里的插入和提取,同时控制DSP模块用哪种算法处理编码后的PCM数据
- MCU单元主要负责把从网络侧收到的语音包经过RTP解析后往packet buffer里插入(insert),以及从packet buffer 里提取(extract)语音包给DSP单元做解码、信号处理等,同时也算网络延时(optBufLevel)和抖动缓冲延时(buffLevelFilt),根据网络延时和抖动缓冲延时以及其他因素(上一帧的处理方式等)决定给DSP单元发什么信号处理命令(该命令用对了可以提高音质,相反会降低音质)
- DSP(digital signal processing, 信号处理单元):负责解码以及解码后的PCM信号处理(信号处理算法有加速(accelerate)、减速(preemptive)、丢包补偿(PLC)、融合(mergee)和背景噪声生成(BNG)等)
- 从packet buffer提取出来的码流解码成PCM数据放进decoded_buffer中,然后根据MCU给出的命令做信号处理,处理结果放在algorithm_buffer中,最后将algorithm_buffer中的数据放进speech_buffer待取走播放。Speech_buffer中数据分两块,一块是已播放过的数据(playedOut),另一块是未播放的数据(sampleLeft), curPosition就是这两种数据的分割点
- MCU(micro control unit, 微控制单元):负责控制从网络接收到的语音包在JitterBuffer里的插入和提取,同时控制DSP模块用哪种算法处理编码后的PCM数据
- 音频的前后处理-3A算法(AEC、ANS、AGC等)
- NetEQ:
- Audio Content Hints类型
- ""没有指定时,只能去猜,可以通过当前Track是如何打开的或通过内容来猜测
- "speech":指定音频为演讲,可以适当使用噪声消除或提升源的可理解性等
- 回声消除和自动增益为true
- "speech-recognition":指定音频源为语音识别,可以适当提高输入信号的清晰度以进行转录并关闭用于人类消费的音频处理组件
- 音频的3A(回声消除、自动增益、噪声抑制)都应该设置为false
- "music":指定音频源为音乐,可能需要调整或关闭用于处理语音数据的音频处理组件,以防止音频失真
- 音频的3A(回声消除、自动增益、噪声抑制)都应该设置为false
- 拓展:WebRTC中
- 视频中也有两种典型的场景,关注内容(帧率小一点可以接收入PPT)和关注运动(如运动的视频、帧率要保证,模糊一点比低帧率更能接收)
- Video Content Hints类型
- ""没有指定时,只能去猜,可以通过当前Track是如何打开的或通过内容来猜测
- "motion":指定为运动,在必须做出妥协的低比特率期间,比边缘质量和细节花费更多的努力来保持帧速率
- 为运动时,应该降低分辨率以保持帧率
- "detail":指定为细节,此操作通常会优化生成的单个帧中的细节,而不是平滑播放
- 为细节时,应该降低帧率保持分辨率
- 会议系统屏幕共享一般默认为细节模式,但是在分享视频等内容时,体验会较差,需要提供流畅模式(指定运动模式保证帧率)
- "text":指定为文本,此操作通常会优化生成的单个帧中的细节,而不是平滑播放,并且可能会使用针对文本渲染进行优化的编译工具,如果有的话
- 为文本时,降低帧率保持分辨率
- Video Content Hints类型
- 音频中有两种典型的场景,需要3A(回声消除、自动增益、噪声抑制等,应该设置为true)的(例如通话、演讲)和不需要3A的(语音识别、音乐应该设置为false)
MediaStream API
MediaStream有两个重要组成部分:MediaStreamTrack和MediaStream
- MediaStreamTrack:代表单一类型的媒体流
- 其产生自客户端的media source,也就是音频(audio track:音频轨)或视频(video track:视频轨),但只能是其中一种
- 一个Track由source和sink组成,source为Track提供数据
- 在浏览器中存在从source到sink的媒体管道,其中source负责产生媒体资源,包括静态的多媒体文件、Web资源和鼎泰的设备采集到的音视频资源;而sink则负责消费source产生的媒体资源,即通过video等标签进行展示播放或通过RTCPeerConnection将source通过网络传输到远端;
- RTCPeerConnection即可以充当source和sink两种角色;作为sink可以将获取到的source降低码率、缩放、调整帧率等,然后传输到远端,作为source则将获取到的远端码流传递到本地渲染
- MediaStream用于将多个MediaStreamTrack对象打包到一起,即一个MediaStream可以包含包含多个audio track与video track,类似于平时的多媒体文件,可包含音频和视频;
- MediaStream中的所有MediaStreamTrack对象在渲染时必须同步,体现在音视频文件中的
音视频的同步;
简单来说:source和sink构成一个Track,多个Track构成MediaStream
- MediaStream中的所有MediaStreamTrack对象在渲染时必须同步,体现在音视频文件中的
- 设备监听(实现实时监控媒体设备的热插拔)
- devicechange实现
navigator.mediaDevices.addEventListener('devicechange',(event) => { updateDeviceList() })- ondevicechange实现
navigator.mediaDevices.ondevicechange = (event) => { updateDeviceList() }
视频质量调整策略 → DegradationPreference
- 策略一:MAINTAIN_FRAMERATE
- 保帧率,降低分辨率
- 该模式的使用场景为视频模式
- 策略二:MAINTAIN_RESOLUTION
- 保分辨率,降低帧率
- 该模式的使用场景为屏幕共享或者文档模式,对清晰度要求较高的场景
- 策略三:BALANCED
- 平衡保帧率与分辨率,默认关闭
- 通过
WebRTC-Video-BalancedDegradation开启
- 使用方式
- 通过设置
MediaStreamTrack的contentHint属性就可以,底层函数会将ContentHint转换成DegradationPreference
- 通过设置
需要考虑的内容有
- webrtc网络结构选择
- 常见的网络结构有Mesh、MCU和SFU网络结构,其中Mesh结构成本最低,但是没有对多人实时互动场景提供很好的支持;MCU支持多人实时互动,但是对服务器要求较高,成本也就最高了,其延时也是三种结构中最高的;SFU可以理解为折中方案,其不需要在服务端进行流媒体的编解码,服务端压力相对较低,并且SFU也可以支持多人实时互动;
- 普遍的方案是Mesh和SFU结合的技术选型方案,人数较少的时候采用Mesh方案,人数较多时选取SFU方案,大多以SFU方案为主;
- 视频编码格式
- 在WebRTC应用中,可以使用的主流编码格式有VP8、VP9、H264、H265和AV1;目前大多数WebRTC应用都选择了H264作为默认的视频编码格式,H264在兼容性方面仅次于VP8,且H264和H265支持硬件加速,在使用过程中,比VP9和VP8更加省电,设备不容易发热;
- 信令系统
- 基于WebRTC的应用在建立通话时,必须进行SDP信息的交换与协商,这就决定了不论选取哪种网络结构,信令系统的搭建是必不可少的;
- 信令系统仅作为数据交换通道,需要结合具体的业务逻辑进行技术选型和系统搭建,通常使用WebSocket技术协议
- 媒体服务器的选取
- 当使用MCU方案时,推荐使用OWT,当需要在服务器端对媒体流进行处理时,如增加人脸识别时推荐使用Kurento
- 当构建通用的WebRTC平台时,Janus基于插件的模式更为合适
- 当希望打造单一的视频通话应用,则推荐使用Mediasoup
- Mediasoup特点分析
- Mediasoup的性能好,在多核CPU系统上,每核运行一个Worker实例,每个Worker实例可以支撑500可消费者
- Mediasoup服务端和客户端都支持使用TS,易于全栈开发
- Mediasoup不能作为一个独立的服务器使用,是以Node模块的形式存在,这样做的好处是可以整合到更大的应用程序中,不受自身的限制
- 在Node模块中,Mediasoup可以分为两个独立的组件:
- JS层,提供了适用于NOde的现代ES API
- 处理媒体层(ICE/DTLS/RTP等)的C/C++子进程Worker
- 这两个进程通过进程互相进行通信,但是在常规的开发中只注重JS API层即可
- Mediasoup将每个实例称为一个子进程,通常在每核CPU上启动一个子进程,在子进程内部有多个Router,每个Router相当于一个房间,每个房间里可以有多个参与者,每个参与者在Mediasoup中由一个Transport代理
- Mediasoup中有三类Transport
- WebRTCTransport:用于与WebRTC类型的客户端进行连接,如浏览器、WebRTC移动端等
- PlainRtpTransport:用于传统的RTP类型的客户端连接,通过该Transport可以播放多媒体文件、执行媒体录制等
- PipeTransport:用于实现Router之间的连接,也就是一个房间中的音视频流通过PipeTransport传到另一个房间,由于一个Router只能运行在单核上,因此借助PipeTransport可以充分利用多核CPU的特性,支持多人同时在线
- 每个Transport可以包含多个Producer和Consumer,即流媒体的生产者和消费者,这两种又可以分为音频和视频的生产者和消费者
- Mediasoup特点分析
- Mediasoup信令交互
- Mediasoup的信令交互本质上与原生WebRTC的信令交互是一致的,Mediasoup在其提供的客户端及服务器端库中封装了WebRTC的原生API,如createOffer()、createAnswer()等方法都在Mediasoup中进行了封装实现
- Mediasoup信令交互图解
- 客户端通过信令服务器获取到服务器端的RTP能力
- 客户端调用Mediasoup.Device.load()方法传入服务器端的RTP能力
- 客户端向信令服务器发送创建WebRTC传输通道的指令,服务器调用router.createWebRtcTransport()方法创建传输通道,返回服务端的传输通道信息TransportInfo
- 客户端创建的是发送通道,随后流程为
- 客户端使用TransportInfo作为参数,调用Mediasoup.Device.createSendTransport()方法创建客户端的发送通道Transport
- 客户端在刚刚创建的Transport上监听connect事件,当该事件被触发时,客户端通过信令服务器向服务器发送连接WebRTC传输通道的指令,服务器端随后调用transport.connect()方法建立连接
- 客户端在刚刚创建的Transport上监听produce事件,客户端通过信令服务器向服务器发送创建生产者的指令,服务器端调用Transport.produce()方法创建服务器端的生产者。 → 当客户端调用Transport.produce()方法发布媒体流时才会触发produce事件
- 当服务器端收到创建生产者的指令时,还会发送newConsumer事件通知房间中其他参与者,其他参与者则在接收通道里接收新发布的媒体流
- 客户端创建的是接收通道,随后流程为
- 客户端使用TransportInfo作为参数,调用Mediasoup.Device.createRecvTransport()方法创建客户端的接收通道Transport
- 客户端在刚刚创建的Transport上监听connect事件,当该事件被触发时,客户端通过信令服务器向服务器发送连接WebRTC传输通道的指令,服务器端随后调用transport.connect()方法建立连接
- 当客户端收到了newConsumer事件时,则会调用Transport.consume()方法接收新发布的媒体流,通过consume.track获取媒体轨道
服务器端的实现
- 具体要实现的功能
- 管理房间的参与者
- 调用Mediasoup服务器端的API
- 与客户端进行信令交互,建立WebRTC连接
- 对外提供管理接口
- 在服务器端负责管理房间和参与者的模块浅析
- Socket.IO服务器
- 负责监听Socket.IO客户端的连接,从连接中获取roomId(房间标识)、peerId(对等端标识)。
- 根据获取到的roomId进行房间的查找或创建操作
- peerId对应peer对象,在客户端连接进来的时候,peerId可能已经存在,此时表示
断网重连情况,需要找到对应的peer对象,替换掉底层的Socket.Io句柄即可;当没有找到peer对象时表示是第一次加入房间,这时创建新的peer对象,加入房间即可;
- Room类
- 所谓房间(Room)就是将同时参与视频通话的各方圈在一起,进行统一的管理
- Room类可以使用一个Map管理多个Peer对象,键值是peerId
- Room类负责处理房间内的信息交换、信令处理、对Mediasoup Router进行配置等
- Peer类
- 一个Peer对象代表一个WebRTC的对等端,包括多个Transport(传输通道)、多个Produce(生产者)和多个Consumer(消费者),当Peer从房间中离开时会销毁这些对象,已释放资源
- Peer对象对应着一个Socket.IO链接,使用该连接进行消息交换
- 负责监听Socket.IO客户端的连接,从连接中获取roomId(房间标识)、peerId(对等端标识)。
- 拓展
- TypeORM是一个优秀的NodeJS ORM框架,采用TS编写,支持TS和JS进行开发,支持对MySQL、PostgreSQL、SQLite、SQL Server、Oracle、MongoDB等常见数据库的相关操作
- 成熟的WebRTC视频会议应该有以下几点
- 可以适应网络变化,始终提供稳定 、可靠、高质量的音视频通话
- 可以适应大规模的并发场景,支持多人、多房间同时通话
- 除了基本的音视频通话外,还需要有例如共享桌面、共享媒体、白板、聊天等辅助功能
- Socket.IO服务器
直播中的弱网问题浅析
视频的清晰度、流畅度、音频的高质量、不卡顿,都是直播软件开发中需要考虑到的问题,上述问题的影响因素之一就是弱网
在移动网络下,通常会遇到网络不稳定、连接被重置、断线重连等情况(网络异常、网络错误、网络协议不规范等),一方面频繁重连,建立连接需要开销。另一方面尤其是发生GPRS/2G/3G/4G切换时,宽带可能会出现瓶颈,当宽带不够,帧率较高/码率较高的内容较难发送出去,此时就需要在不同的网络状况下执行不同的策略编码推流,以此让观众可以看到最优质的直播视频;
- 弱网检测的方式
- 主动网络探测:
- 主要是指当直播软件开发中的某些条件被触发后,系统会主动进行网络探测,并且根据既定的检测标准判断系统是否处于弱网状态下
- 被动网络采集:
- 主要是指系统会记录每一次的网络请求细节,并按照既定的要求将相关信息进行上报,上层根据系统的既定条件进行弱网状态的判断
- 主动网络探测:
- 直播音视频弱网定义
- 直播网络异常原因
- 网络带宽低于视频直播的码率
- 网络丢包高,导致频繁重传,消耗了本来不充裕的带宽
- 网络抖动,网络带宽波动较大,网络拥塞
- 网络信号弱,频繁断网重连
- 满足上述4个条件之一,就可以称为是音视频弱网
- 解决办法
- 终端自适应码率:
- 播放器在不同的网络模型下,根据所处网络状况,从服务器端下载不同码率的流,弱网情况下从服务端下载低码率的流,通过减少网络中传输的数据,来提升用户的观看体验;即
动态调整码率 - 直播流的分发有两种方式:
- 通过分片进行分发,即分片下载,采用的是短连接,如DASH、HLS等
- DASH/HLS实现相对容易,在索引文件把所有码率的分片索引都带上,客户端根据实际的网络情况,选择合适的分片进行下载;切换不同的分片下载比较方便,换一个分片地址就可以,不需要额外的变更
- 但是需要注意的是不同的码率之间的切片的时间戳需要对齐,以便在切换码率过程中,不能出现画面跳跃或者出现渲染失败的情况
- 分片模式实现自适应码率的逻辑,其关键是索引文件MPD。索引文件下载和分片下载可以复用一个链接,以降低握手的开销,其具体结构如下
- DASH/HLS的延迟一般较大,虽然可以通过减小分片来降低一些延迟,但是会受到索引文件、GOP等因素的限制
- GOP(Group of Pictures):即画面组,一个GOP就是大量帧的合集。直播的视频数据流其实就是一系列的视频帧率组件、包括I帧、P帧等,一个GOP就是以一个I帧,多个p帧开始。
- 减少GOP帧的数量,就可以减少播放器加载GOP帧所用的时间,其原理就是用户在第一次观看的时候,播放器需要找到I帧才可以开始播放,而播放器会到服务器找最近的I帧反馈给用户
- 通过长连接的方式:在单个链接里面,下发所有的音视频数据,如FLV、RTMP等
- 自适应码率切换实现动态调整码率
在FLV/RTMP长连接中,不同码率的地址是按照固定的规则生成的,通过pts进行对齐,都是从关键帧开始下发。P帧和B帧,解码都是需要依赖其他帧的,不可单独渲染 ,所以需要在关键帧的位置进行切换;
不同码率的流,帧率有可能不一致,时间戳不一定可以完全对齐,实现较为复杂;
不同码率的流使用的是不同的链接,可以通过HTTP2技术实现复用链接- 需要解决两个问题:
- 边界对齐:从而实现在切换时画面可以平滑过度,无感知切换效果;可以在切片的时候加入额外的信息进行标识;
- 合理的码率切换策略
- 想要设计合理的码率切换算法,既要考虑带宽和缓冲区长度,又要考虑码率切换频率和切换幅度,最后可能还要考虑直播内容。
- 快手实现方案
- 需要解决两个问题:
- 自适应码率切换实现动态调整码率
- 通过分片进行分发,即分片下载,采用的是短连接,如DASH、HLS等
- 播放器在不同的网络模型下,根据所处网络状况,从服务器端下载不同码率的流,弱网情况下从服务端下载低码率的流,通过减少网络中传输的数据,来提升用户的观看体验;即
- 通过降低画质
- 丢掉部分视频数据
- 提高视频数据的压缩率等
- 降低观看端所需要的数据量,降低网络负荷
- 终端自适应码率:
- 直播网络异常原因
- 衡量网络质量的指标
- RTT(往返时延):RTT越小越好,越稳定越好,RTT越小,数据传输的越快
- RTT = 2*Tp(传播时延) + Tb(确认信号时间)
- RTT:即数据发送完(完成最后一个比特推送到数据链路上)到收到确认信号的事件
- 宽带:宽带越大,单位时间内传输的数据越多
- 丢包率(Fraction Lost):丢包率越小,重传概率越低,数据传输成功率越高
- 吞吐量:单位时间内传输的数量越大,网络质量越好
- 抖动(Jitter)
- RTT(往返时延):RTT越小越好,越稳定越好,RTT越小,数据传输的越快
- 专业术语浅析
- QoE:表示用户在接收端的主观体验
- QoS:指通过一些量化指标衡量网络的传输质量并提供优质网络服务
- HDS(Http Dynamic Streaming):
- 是Adobe公司模仿HLS协议提出的另一个基于Http的流媒体传输协议。其模式和HLS类似,但又要比HLS协议复杂一些,也是索引文件和媒体切片文件结合的下载方式;
- HLS协议(Http Live Streaming)是Apple的动态码率自适应技术,主要用于PC和Apple终端的音视频服务,包括一个
m3u8的索引文件(用来控制播放)、TS媒体分片文件(视频编码格式是H264、音频编码格式是MP3、AAC或AC-3)和key加密串文件- HLS协议的直播视频时延无法下到10秒以下,而RTMP协议的时延最低可以达到3/4秒左右,因此对直播时延比较敏感的服务器请慎用HLS
- HLS协议的小切片方式会产生大量的文件,存储和处理这些文件会造成大量的资源浪费,当需要实现数天的时移,索引量将会是一个巨额数字,并且明显的影响索引数字,因此HLS协议对存储I/O要求相当苛刻;
- 针对上述问题,新型的
点播服务系统独创了内存缓存数据实时切片技术,颠覆了这种传统的实现方式,从根本上解决了大量切片的碎片问题,使得单台服务器的切片与打包能力不再是瓶颈- 上述技术的原理是:不将TS切片文件存储到磁盘,而是存在内存当中,这种技术使得服务器的磁盘上不再会有"数以吨计"的文件碎片,极大减少了磁盘的I/O次数,延长了服务器磁盘的使用寿命,极大的提高了服务器运行的稳定性,同时使用这种技术使得终端请求数据时直接从服务器的内存中获取,极大提高了对终端数据请求的反应速度,优化了视频观看体验
- 常见的
流媒体协议主要有HTTP渐进下载和基于RTSP/RTP的实时流媒体协议,这两种基本是完全不同的东西;目前比较方便和好用的是HTTP渐进下载的方法,HLS协议就是基于HTTP的流媒体网络传输协议,HLS可以穿过任何允许HTTP数据通过的防火墙或代理服务器,也很容易通过使用内容分发网络来传输媒体流
- HLS协议(Http Live Streaming)是Apple的动态码率自适应技术,主要用于PC和Apple终端的音视频服务,包括一个
- 是Adobe公司模仿HLS协议提出的另一个基于Http的流媒体传输协议。其模式和HLS类似,但又要比HLS协议复杂一些,也是索引文件和媒体切片文件结合的下载方式;
- javascript如何进行网络检测
- 常规的网络状况判断标准
- 拓展补充 → offline
- navigator.connection显示主要数据:
rtt:0;downlink:0;effectiveType:'4g'
- navigator.connection显示主要数据:
- slow-2g:当用户只有0~50Kbps的互联网时,页面加载非常慢,不建议显示任何媒体内容,如图片、视频、音频等
- 2G:当用户只有50~70Kbps的互联网速度时,看起来有点类似于slow-2g,但可以显示小图像
- navigator.connection显示主要数据:
rtt:1900;downlink:0.35;effectiveType:'2g'
- navigator.connection显示主要数据:
- 3G:正常的70~700Kbps互联网速度,用户可以加载图像、视频或音频
- navigator.connection显示主要数据:
rtt:550;downlink:1.3;effectiveType:'3g'
- navigator.connection显示主要数据:
- 4G:大于700Kbps的互联网传输速度,适用于任何媒体内容
- navigator.connection显示主要数据:
rtt:50;downlink:10;effectiveType:'4g'
- navigator.connection显示主要数据:
- 拓展补充 → offline
- 通过
navigator检测网络window.navigator.onLine来检测网络是否可用(返回Boolean,true表示已连接,false表示未连接)navigator.connection.downlink可以访问用户当前网络环境的网络宽带- connection.downlink返回的并不是用户当前环境的展示的网络传输速度,而是当前网络的带宽,官方说法是:返回以Mb/s为单位的有效带宽,并保留该值为25kb/s的最接近的整数倍
- navigator.connection中有一个RTT的字段,是只读属性,返回当前连接的估计有效往返时间,四舍五入到最接近的 25 毫秒倍数。 该值基于最近活动的连接中观察到的应用层 RTT 测量值, 它不包括与私有地址空间的连接。 如果没有最近的测量数据可用,则该值基于底层连接技术的属性。
- navigator.connection中有一个saveData的字段,用来表示当前设备是否开启了节省流量的开关
- 可以通过
navigator.connection.addEventListener('change',(e)=>{})或navigator.connection.onchange = (e) => {}来监听网络类型的变化监听,包括断网和网络类型级别变化监听 - IE和Safari不支持此API,并且也不靠谱
- 使用
window.ononline和window.onoffline事件监听浏览器的网络状况- 可以通过上述两种事件监测网络变化状态
兼容方案window.addEventListener('offline',() => { alert('断网了') }) // window.onoffline = () => { // alert('断网了~~') // } window.addEventListener('online',() => { alert('来网了') })<script type="text/javascript"> var el = document.body; if (el.addEventListener) { window.addEventListener("online", function () { alert("网络连接恢复");}, true); window.addEventListener("offline", function () { alert("网络连接中断");}, true); } else if (el.attachEvent) { window.attachEvent("ononline", function () { alert("网络连接恢复");}); window.attachEvent("onoffline", function () { alert("网络连接中断");}); } else { window.ononline = function () { alert("网络连接恢复");}; window.onoffline = function () { alert("网络连接中断");}; } </script> - 通过
模拟Ajax请求检测网络
$.ajax({ url: 'https://sug.so.360.cn/suggest', dataType:'jsonp', success: function(result){ alert('网络正常') }, error: function(result){ alert('网络异常') } }); - 常规的网络状况判断标准
音视频可视化的实现 → AudioContext
要实现音视频可视化,需要借助Web Audio API提供的一些方法,即AudioContext
- AudioContext接口表示由链接在一起的音频模块构建的音频处理图,每个模块由一个
AudioNode表示,音频上下文控制它包含的节点的创建和音频处理或解码的执行。 - 在使用
AudioContext之前,都需要创建一个AudioContext对象,因为所有事情都是在上下文中发生的,建议创建一个AudioContext对象并复用它,而不是每次都初始化一个新的AudioContext对象,并且可以对多个 不同的音频源和管道同时使用一个AudioContext对象。 - 具体实现步骤
- 准备Audio和canvas标签
<audio class="audio" ref="audio" :src="tune" @ended="ended"></audio> <canvas ref="canvas" width="300px" height="300px"></canvas>- 创建并返回一个新的AudioContext对象
const ctx = new AudioContext()- 创建一个新的
MediaElementAudioSourceNode对象- AudioContext接口的
createMediaElementSource()方法用于创建一个新的MediaElementAudioSourceNode对象,输入某个存在的HTML<audio>或<video>元素,对应的音频即可被播放或者修改;
- AudioContext接口的
const audioSrc = ctx.createMediaElementSource(this.audioElement)- 创建AnalyserNode对象
audioContext的createAnalyser()方法可以创建一个AnalyserNode,可以用来获取音频时间和频率数据,以及实现数据可视化;
const analyser = ctx.createAnalyser()- 设置fftSize属性
- AnalyserNode接口的fftSize属性的值是一个无符号长整型的值,表示(信号)样本的窗口的小,当执行快速傅里叶变化(Fast Fourier Transfor(FFT))时,这些信号样本被用来获取频域数据;
- fftSize属性的值必须是从32到32768范围内的2的非零幂,其默认值为2048
analyser.fftSize = 512- audioSrc和Analyser进行链接
- AudioNode接口的connect方法使你能将一个节点的输出连接到一个指定的目标,这个指定的目标是另一个AudioNode(从而将音视频数据引导到下一个指定节点)或一个AudioParam,以便上一个节点的输出数据随着时间流逝自动的对下一个参数值进行改变;
audioSrc.connect(analyser)- Analyser和ctx.destination进行链接
AudioContext的destination属性返回一个AudioDestinationNode表示context中所有音频(节点)的最终目标节点,一般是音频渲染设备,比如扬声器;
analyser.connect(ctx.destination)