前段时间看到腾讯云的分享:《WebRTC Insertable Stream 初探与 WebRTC “管道化”》。想不到国内也开始关注这个新特性了,作为一个经常关注WebRTC最新提交代码的人,去年初就关注到了WebRTC Insertable Streams相关代码提交,不过对我这样一个Native Code开发者来说,用途不大,毕竟自己也可以在源码层面实现,获取或者修改自己需要的任何数据。但是这一特性对Web开发者来说用途就大了,给了Web开发者更多的自由与操作性。 WebRTC Insertable Streams 以前WebRTC Web开发者无法操作WebRTC采集或者编码后的音视频数据,当然也无法使用自定义的音视频编解码器,很多人使用WebRTC可能只是想用到传输这一块功能。当然也有比较黑科技的做法,使用WebAssembly技术把WebRTC库编译成二进制文件给Javascript调用,不过这一做法难度颇大,很多人编译WebRTC都废了九牛二虎之力,更别说使用WebAssembly技术编译,而且自己改的不一定稳定。所以WebRTC Insertable Streams这项新特性就诞生了。 WebRTC Insertable Streams目前包含两项内容: Encoded Transform:操作编码后的数据以及解码前数据(Post-encoding/Pre-decoding) Mediacapture Transform:操作编码前数据以及解码后数据(Pre-encoding /Post-decoding) WebRTC Insertable Streams这项新特性增加了些新API,让Web开发者对媒体数据可以做如下的事: 允许用户不打破WebRTC正常处理pipeline,手动处理数据 允许使用WASM技术进行数据处理 允许使用Web Worker技术处理数据,避免阻塞主线程 允许端到端间进行数据加解密,避免安全以及隐私泄露风险(不信任SFU服务器,避免中间人攻击) 根据[1],这里列举几个应用场景: 视频特效 视频背景移除 语音处理 动态控制编解码器参数 各个媒体Tracks的自定义带宽分配 自定义编解码器(与WebCodecs结合) 是不是很有趣?不过截止今天,WebRTC也只是实现了Encoded Transform特性,只能操作编码后的数据。所以本篇文章就从源码层面分析下目前的Encoded Transform实现。 Encoded Transform 前面说到Encoded Transform处理的是Post-encoding/Pre-decoding的媒体数据。 该特性接口定义位于FrameTransformerInterface中。 FrameTransformerInterface 看下接口定义: [crayon-69e923e79b245896498024/] 上面代码中,FrameTransformerInterface注册完TransformedFrame相关回调后,在回调TransformedFrameCallback::OnTransformedFrame获取编码后的Payload数据,调用TransformableFrameInterface接口对Payload数据进行操作: 调用GetData获取Payload数据,调用SetData设置Payload数据,我们可以通过GetData获取原始编码后的媒体数据,处理后再调用SetData达到修改媒体数据目的。当然了,也可以获取音视频的其他信息,例如音频,可以获取音频的RTP报头信息。 接下来我们以音频为例看下目前Encoded Transform相关代码实现。 音频发送端 这里先看下发送端代码流程: [crayon-69e923e79b252625386931/] WebRTC对ChannelSend::SendData进行了修改,其中frame_transformer_delegate_(ChannelSendFrameTransformerDelegate)继承自TransformedFrameCallback。 [crayon-69e923e79b257557873919/] 处理完数据后通过ChannelSend::SendRtpAudio将数据返回到原来的的处理Pipeline。所以若初始化了ChannelSendFrameTransformerDelegate,处理流程变为: [crayon-69e923e79b25a841937939/] 这里FrameTransformerInterface由我们外部自己实现。所以我们需要修改Payload数据的话需要实现FrameTransformerInterface,在FrameTransformerInterface::Transform中通过TransformableAudioFrameInterface进行获取或者修改Paylod数据,最后通过注册的回调接口返回修改的Payload数据。。 音频接收端 这里先看下接收端代码流程: [crayon-69e923e79b25e532476525/] WebRTC对ChannelReceive::ReceivePacket处理流程进行了修改。 [crayon-69e923e79b261790619268/] 同前面发送端代码,其中frame_transformer_delegate_(ChannelReceiveFrameTransformerDelegate)也是继承自TransformedFrameCallback。最后处理完数据后通过ChannelReceive::OnReceivedPayloadData将数据返回到原来的处理Pipeline。具体代码类似发送端,就不再分析了。最后代码处理流程变为: [crayon-69e923e79b265127545759/] 在接收端我们也需要在外部实现FrameTransformerInterface,从而进行数据处理。 总结 本文简单介绍了Insertable Streams这个新特性,并从音频角度分析了其中一项内容的源码实现:Encoded Transform。等后续WebRTC官方更新了Mediacapture Transform实现代码,我也将做下分析。 参考 [1] webrtc-encoded-transform.https://github.com/w3c/webrtc-encoded-transform.