webRTC中音频相关的netEQ(四):控制命令决策

本文深入探讨WebRTC中MCU模块如何根据网络状况、反馈报告等信息,决策发送给DSP模块的控制命令,包括正常播放、加速播放、减速播放、丢包补偿等,确保音频流畅性和质量。

上篇(webRTC中音频相关的netEQ(三):存取包和延时计算)讲了语音包的存取以及网络延时和抖动缓冲延时的计算,MCU也收到了DSP模块发来的反馈报告。本文讲MCU模块如何根据网络延时、抖动缓冲延时和反馈报告等决定发给DSP模块的控制命令, 好让DSP模块先对取出的语音包做解码处理(如果有的话)以及根据这些命令做信号处理。

 

MCU模块给DSP模块发的控制命令主要有正常播放(normal)、加速播放(accelerate)、减速播放(preemptive expand)、丢包补偿(PLC,代码中叫expand)、融合(merge),还有些次要的,如解码器重新初始化(decoder re-init)、packet buffer 重置(packet buffer reset)等。这里讲主要的控制命令是怎么决策的,次要的相对简单就略去不讲了,有兴趣的可以自己去看相关代码。DSP模块收到这些命令后会转化为自己的处理命令,下表列出了主要的控制命令和处理命令的映射关系。

 

MCU模块给DSP模块发什么样的控制命令首先取决于当前帧和前一帧的接收情况。当前帧和前一帧的接收情况主要分以下四种(对当前帧和前一帧做排列组合得到四种情况):

1,当前帧和前一帧都接收正常,数据包会进入正常的解码流程。MCU模块会发正常播放、加速播放、减速播放三种控制命令中的一个给DSP,解码后的数据会根据命令做相应的处理。

2,当前帧接收正常,但前一帧丢失。如果前一帧丢失,但当前帧接收正常,说明前一帧是通过丢包补偿生成的。为了使前一帧由丢包补偿生成的数据和当前没有丢包的帧的数据保持语音连续,需要根据前后帧的相关性做平滑处理。这种情况下MCU模块会发正常播放、融合两种控制命令中的一个给DSP。DSP模块先对当前帧解码,然后解码后的数据会根据命令做相应的处理。

3,仅当前帧发生丢包或延迟,这时就不需要解码了。MCU模块会发丢包补偿命令给DSP,DSP模块会进入丢包补偿单元来生成补偿数据。

4,当前帧丢失或延迟,前一帧同样丢失或延迟。MCU模块会连续的发丢包补偿命令给DSP,DSP模块也会连续的进入丢包补偿单元来生成补偿数据。不过越到后面生成的补偿数据效果越差。

 

在上面的四种情况中,有些情况下MCU模块只会发一种命令给DSP模块,比如当前帧丢失,只会发丢包补偿控制命令给DSP。但有些情况下MCU模块可能会发几种命令中的一种给DSP模块,比如当前帧和前一帧都接收正常,MCU模块会发正常播放、加速播放、减速播放三种控制命令中的一个给DSP。到底发哪种命令呢,这就取决于网络延时、抖动缓冲延时以及DSP发给MCU的反馈报告等因素了。这是本文的重点,下面具体讲。

 

在DSP发给MCU的反馈报告中有个变量playedOutTS,它表示已经播放到的PCM数据的时间戳。同时MCU中还有个变量availableTS,它表示packet buffer中能获得的有效包的起始时间戳,显然如果availableTS等于0表示packet buffer为空。如果playedOutTS等于availableTS,它说明语音包正常接收;如果playedOutTS小于availableTS,它说明有语音包的丢失或者延时,需要做丢包补偿(PLC)。上篇文章(webRTC中音频相关的netEQ(三):存取包和延时计算)中讲了网络延时值(optBufLevel)和抖动缓冲延时值(buffLevelFilt)的计算,MCU就是要根据时间戳(playedOutTS & availableTS)的关系和延时(optBufLevel & buffLevelFilt)的关系以及上一帧的播放模式等来决定发什么样的控制命令给DSP。先举个简单的例子,如果playedOutTS = availableTS并且buffLevelFilt > optBufLevel,这说明当前包正常接收,但是抖动缓冲延时大于网络延时,即缓冲的包多了增加了时延,需要做加速播放处理,所以MCU会发加速处理命令给DSP。下面给出各个控制命令的条件,即满足所列条件时MCU就会发相应的控制命令给DSP。

 

1,正常播放控制命令 / 加速播放控制命令 / 减速播放控制命令的条件

正常播放控制命令为BUFSTATS_DO_NORMAL。加速播放控制命令为BUFSTATS_DO_ACCELERATE,加速播放的原因是要播放的数据正常到达,但是抖动缓冲延时大于网络延时,增加了时延,因此要加速播放。减速播放控制命令为BUFSTATS_DO_PREEMPTIVE_EXPAND,又称为优先扩展控制命令。减速播放的原因是要播放的数据正常到达,但是抖动缓冲延时小于网络延时,会引起播放时声音的断续,降低音质,因此要减速播放,拉长时间,使不会出现断续。这三种控制命令都有一个必要条件,那就是playedOutTS = availableTS, 所以把这三种控制命令放在一起讲。在“playedOutTS = availableTS”条件下,只有三种控制命令可供选择,要么正常播放,要么加速播放,要么减速播放。把加速播放和减速播放的条件搞清楚了,剩下的就是正常播放条件了。下图更直观的说明了正常播放、加速播放和减速播放的关系,去掉加速和减速的就是正常播放的了。

先看加速播放的条件。它的第二个条件是上一帧播放模式不为丢包补偿(第一个条件为playedOutTS = availableTS),第三个条件是下列两个之一:

1) 加速播放第三个条件之一

其中sample_rate为采样率,如8000/16000。samples_per_packet为每个包的采样点数,以16KHZ/每包20ms为例,samples_per_packet就为320。 timescaleHoldOff初始化为32,且每发生一次加速或减速播放就右移一位。此参数是为了防止连续的加速或减速播放恶化人耳的听觉感受。

2)加速播放第三个条件之二

 

再看减速播放的条件。它的第一个条件与第二个条件与加速播放一样,第三个条件如下:

说实话我没有完全理解上面三个加减速的数学表达式的判据,尤其是系数值的选取。我知道不能简单的认为“buffLevelFilt > optBufLevel"就加速“buffLevelFilt < optBufLevel"就减速,要真的这么判断的话效果肯定是不好的。如果哪位朋友理解了,麻烦给讲讲,先谢谢了!

除加减速播放这些条件外,剩下的就是正常播放了。可以写成如下的伪代码:

If(playedOutTS == availableTS)

{

    If(上一帧播放模式不为丢包补偿)

    {

        If(加速播放第三个条件是下列之一 || 加速播放第三个条件是下列之二)

            return 加速播放;

        If(减速播放第三个条件)

            return 减速播放;

    }

    return 正常播放;

}

 

2,丢包隐藏控制命令的条件

丢包隐藏控制命令为BUFSTATS_DO_EXPAND,又称为扩展控制命令。丢包隐藏的原因是要播放的包已丢失或者还没到(延时)。发生丢包隐藏的场景有:

1)availableTS = 0,即packet buffer为空,显然这时需要做丢包补偿。

2)playedOutTS < availableTS,即要播放的包丢失或者延时到,但是packet buffer里有缓冲包,需要满足下面两个条件之一即可:

a)  上一帧播放模式不为丢包补偿

b)  上一帧播放模式为丢包补偿,且前面几帧均为丢包补偿,这是连续丢包的场景,这时要看连续丢包补偿的次数。netEQ设定最多可以补偿100ms的数据,以每包20ms为例,最多可以补偿5个包,其实100ms后的补偿效果也不好了。所以连续丢包补偿的次数小于5的话,还会继续丢包补偿,否则就不做丢包补偿了。

 

3,融合控制命令的条件

融合控制命令为BUFSTATS_DO_MERGE,主要用于丢包隐藏后产生的PCM数据与从packet buffer里取出的数据的衔接过程。所以产生融合控制命令的条件是:

1)playedOutTS < availableTS (此式也表示packet buffer不为空,为空时availableTS = 0)

2)上一帧的处理模式为丢包补偿

 

以上就是主要的控制命令的条件。可能不同版本之间可能有差异,我是根据我用的版本来讲的。就像上面我说的,有些我也没有完全理解,只是把它照本宣科的讲出来。苦于没有文档呀,网上也没有相关的论述,目前只能先这样了,后面如果完全理解了再补充。

### WebRTC 的技术原理 WebRTC 是一种支持浏览器之间进行实时音视频通信以及数据传输的技术,其核心目标是实现低延迟、高质量的实时通信。WebRTC 的实现依赖于多个关键技术组件: - **媒体捕获与处理**:通过 `getUserMedia` API,WebRTC 可以访问用户的摄像头和麦克风设备,捕获音视频流。这些原始数据可以进一步通过 `MediaStream` 和 `MediaTrack` 进行处理,例如应用滤镜、调整音量等[^4]。 - **编解码器**:WebRTC 使用高效的音视频编解码器,如 VP8、VP9 用于视频编码,Opus 用于音频编码,以确保在不同带宽条件下都能提供良好的通信质量[^1]。 - **网络传输**:WebRTC 使用 `RTCPeerConnection` API 来建立点对点的连接,通过 ICE(Interactive Connectivity Establishment)协议来协商连接路径。ICE 会尝试利用 STUN(Session Traversal Utilities for NAT)服务器获取公网 IP 地址,并在 NAT 或防火墙环境下尝试直接连接。如果直接连接失败,则会通过 TURN(Traversal Using Relays around NAT)服务器进行中继传输[^2]。 - **数据通道**:除了音视频通信,WebRTC 还支持通过 `RTCDataChannel` 实现点对点的数据传输,适用于实时文本聊天、文件共享等场景[^2]。 --- ### WebRTC 的使用场景 由于 WebRTC 提供了无需插件即可实现实时通信的能力,因此其应用场景非常广泛: - **视频会议**:WebRTC 被广泛用于构建在线会议系统,如 Zoom、Google Meet 等,支持多方音视频通话与屏幕共享功能[^1]。 - **在线教育**:远程教学平台可以通过 WebRTC 实现实时互动教学,包括教师与学生之间的音视频交流、白板协作等[^1]。 - **远程医疗**:医生可以通过 WebRTC 与患者进行远程视频问诊,查看患者状态并提供诊断建议[^1]。 - **游戏直播与互动**:一些实时互动游戏平台和直播服务使用 WebRTC 来降低延迟,提高用户体验[^1]。 - **客服系统**:企业客服系统可以集成 WebRTC 实现视频客服、远程协助等功能[^3]。 --- ### WebRTC 的常见问题与解决方案 尽管 WebRTC 功能强大,但在实际部署中仍面临一些挑战: - **NAT 和防火墙穿透问题**:许多用户处于 NAT 或防火墙之后,直接建立 P2P 连接可能失败。此时需要部署 STUN/TURN 服务器来协助连接[^2]。 - **跨浏览器兼容性**:虽然 WebRTC 已成为 W3C 标准,但不同浏览器对其支持程度略有差异。开发者应使用适配层(如 adapter.js)来确保兼容性[^4]。 - **网络波动与带宽管理**:WebRTC 提供了自动带宽评估和码率控制机制,如使用 `RTCRtpSender.setParameters()` 动态调整编码参数,以应对网络波动带来的影响[^3]。 - **安全性问题**:WebRTC 默认使用 SRTP(Secure Real-time Transport Protocol)进行媒体加密,并通过 DTLS(Datagram Transport Layer Security)保护数据通道。开发者应确保信令过程也采用加密手段(如 HTTPS、WSS)防止中间人攻击[^2]。 - **信令机制的实现**:WebRTC 本身不规定信令方式,开发者需要自行实现基于 WebSocket、SIP 或其他协议的信令交换机制,用于交换 SDP(Session Description Protocol)信息和 ICE 候选地址[^2]。 --- ### 示例代码:建立基本的 WebRTC 连接 以下是一个简单的 JavaScript 示例,展示如何使用 WebRTC 建立点对点连接: ```javascript // 获取本地媒体流 navigator.mediaDevices.getUserMedia({ video: true, audio: true }) .then(stream => { const localVideo = document.getElementById('localVideo'); localVideo.srcObject = stream; // 创建 RTCPeerConnection 实例 const configuration = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }; const peerConnection = new RTCPeerConnection(configuration); // 添加媒体轨道 stream.getTracks().forEach(track => peerConnection.addTrack(track, stream)); // 处理 ICE 候选 peerConnection.onicecandidate = event => { if (event.candidate) { // 发送候选信息到远端 sendCandidate(event.candidate); } }; // 创建 Offer peerConnection.createOffer() .then(offer => peerConnection.setLocalDescription(offer)) .then(() => { // 发送 Offer 到远端 sendOffer(peerConnection.localDescription); }); }); ``` --- ###
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值