webrtc_android 视频美颜实战:给通话加磨皮只需 4 处改动
【免费下载链接】webrtc_androidwebrtc VideoCall VideoConference 视频通话 视频会议项目地址: https://gitcode.com/gh_mirrors/we/webrtc_android
做视频通话时,用户最常抱怨的就是"画面发黄""摄像头不行"。webrtc_android 视频美颜不用重写渲染链路,只要在视频帧编码发送前挂一个滤镜就能生效,本地和对方看到的画面会一起变。下面以仓库里现成的 temple1 示例模块为参照,走一遍最小改动集。
这张图讲一次 WebRTC 通话的建立:双方交换 SDP、中继候选者,最后拉通 P2P 通道——美颜改动不碰这条链路。
效果速览 🎯
| 你能得到 | 说明 |
|---|---|
| 实时磨皮 | GLSL 片段着色器实现,GPU 上跑,本地与远端画面同步生效 |
| 可调参数 | 磨皮强度、亮度都可在通话中随时改 |
| 滤镜自由增删 | 滤镜是一个列表,随时换掉或叠加自己的特效 |
| 侵入极小 | 只动发送方向,信令流程与接收渲染保持原样 |
两个必懂概念
- VideoProcessor:摄像头与编码器之间的"检查站",本地采集的每一帧都会流经它,你可以在这里把帧内容换掉。类似流水线上的质检员。
- ProxyVideoSink:把解码后的帧推上屏的"出口",位于接收方向,本项目不改它。
记住一句话就能抓住 webrtc_android 视频美颜的要点:改入口(视频源),不动出口(渲染)。
实战上手:最小可运行路径
改动一:把处理器挂进视频源
打开 RTCEngine.java,在createVideoTrack里建好 VideoSource 之后,补上这几行:
rtcVideoEffector = new RTCVideoEffector(); gpuImageBeautyFilter = new GPUImageBeautyFilter(); rtcVideoEffector.addGPUImageFilter(gpuImageBeautyFilter); mVideoEffectProcessor = new VideoEffectProcessor(mSurfaceTextureHelper, rtcVideoEffector); mVideoSource.setVideoProcessor(mVideoEffectProcessor);setVideoProcessor是唯一的挂接点:这行代码之后,本地相机帧会先经过处理器再到编码器手里。
这张图是 joinRoom、offer/answer、交换 Candidate 到建立 P2P 通道的完整时序,帮你定位"帧在哪个阶段被采集、处理器站在哪一段"。
改动二:读懂逐帧处理逻辑
VideoEffectProcessor.java 的核心就三行:
public void onFrameCaptured(VideoFrame frame) { VideoFrame newFrame = handleVideoFilter(frame); mSink.onFrame(newFrame); }handleVideoFilter只在帧是 I420 格式且 YUV 缓冲为 direct buffer 时才做滤镜处理,否则原样放行——这是兼容各种采集配置的保底写法。
改动三:运行时控制
RTCVideoEffector.java 负责维护滤镜列表与开关:
rtcVideoEffector.addGPUImageFilter(yourFilter); // 追加新滤镜 rtcVideoEffector.disable(); // 一键停用全部处理没有启用中的滤镜时,needToProcessFrame()直接返回 false,帧会原样进编码器,不为特效多花一毫秒。
改动四:记得释放资源
通话结束时调用mVideoEffectProcessor.dispose()释放 GPU 资源。注意仓库里RTCVideoEffector#dispose的空值判断是反的,实际落地前建议自查修正(见避坑指南)。
常用美颜参数对照
| 参数/写法 | 效果 |
|---|---|
setBeautyLevel(0.42f) | 磨皮强度,默认 0.42;拉到 0.7 以上会有明显塑料感 |
setBrightLevel(0.34f) | 整体提亮,默认 0.34,暗光环境可调到 0.5+ |
addGPUImageFilter(f) | 叠加任意 GPUImage 滤镜,可与美颜串联 |
addMediaEffectFilter(name) | 按名字加载内置特效,不用自己写着色器 |
disable()/enable() | 整条处理链路一键关断,适合弱网应急 |
GPUImageBeautyFilter.java 里三个参数都映射到 shader 的 uniform。想写自己的滤镜,照这个模板走:片段着色器 +onInit取 location + 对外 setter,即可替换进滤镜列表。
避坑指南 ⚠️
- 现象:本地预览磨皮了,远端还是原图。原因:处理器只挂在发送方向,对方看到的永远是对方采集的帧。解法:属正常表现;想改远端呈现得去动接收方向的渲染链路,两个方向互不影响。
- 现象:部分机型上滤镜没效果,或效果中途消失。原因:YUV 缓冲不是 direct buffer 时,
processByteBufferFrame会直接返回原帧。解法:检查采集分辨率与输出格式,确保走的是 direct buffer 路径。 - 现象:调了
dispose()但 GPU 资源没释放。原因:RTCVideoEffector#dispose中if (helper != null) return;在已初始化时反而提前返回。解法:统一在挂断清理处调用并先修正该判断,再上线。
一句话收尾
webrtc_android 视频美颜的本质是一个挂接点加一个滤镜列表:setVideoProcessor挂处理器,RTCVideoEffector堆滤镜,改动不到二十行,本地远端同时生效。
git clone https://gitcode.com/gh_mirrors/we/webrtc_android【免费下载链接】webrtc_androidwebrtc VideoCall VideoConference 视频通话 视频会议项目地址: https://gitcode.com/gh_mirrors/we/webrtc_android
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考