Android AntMedia WebRTC 摄像头切换屏幕共享时出现源错误
AntMedia 框架 WebRTC 摄像头与屏幕共享切换实现方案
故障核心原因
你遇到的屏幕共享推流2-3秒就中断、订阅端报source error、服务器收不到后续视频分片的问题,是AntMedia Android WebRTC框架切换采集源时的高频踩坑点,常见触发原因有以下几类:
- 屏幕采集器没有正确关联从
onActivityResult拿到的合法MediaProjection授权,系统权限校验不通过后会主动终止采集流程 - 切换前没有释放之前的摄像头采集资源,导致EGL上下文、SurfaceTexture资源冲突,采集线程异常退出
- 没有对MediaProjection实例做强引用持有,对象被系统回收后采集立刻中断
- Android 10以上系统要求屏幕采集必须绑定常驻前台服务,缺失服务配置时系统会在数秒后自动收回采集权限
正确的切换实现流程
切换前的前置资源释放
不要直接新建屏幕采集器就替换推流Track,必须先把正在运行的摄像头采集资源完全停止、释放,避免资源冲突:
// 停止当前摄像头采集 if (videoCapturer != null) { try { videoCapturer.stopCapture(); } catch (InterruptedException e) { e.printStackTrace(); } videoCapturer.dispose(); videoCapturer = null; } // 释放关联的SurfaceTextureHelper if (surfaceTextureHelper != null) { surfaceTextureHelper.dispose(); surfaceTextureHelper = null; } // 解绑旧视频Track与发送端的绑定 if (localVideoTrack != null) { peerConnectionClient.localVideoSender.setTrack(null, false); PeerConnectionFactory peerConnectionFactory = peerConnectionClient.factory; peerConnectionFactory.disposeVideoSource(localVideoTrack.getSource()); localVideoTrack = null; }
屏幕采集器初始化与绑定
基于合法的MediaProjection授权创建屏幕采集实例,完成后直接动态替换推流Track,不需要重建PeerConnection、不需要重新走SDP协商:
public void MakeScreenCaptureReady(int resultCode, Intent data) { final EglBase.Context eglBaseContext = eglBase.getEglBaseContext(); PeerConnectionFactory peerConnectionFactory = peerConnectionClient.factory; // 通过MediaProjectionManager获取合法投影实例,全局强引用持有,避免被GC回收 MediaProjection mediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data); // 初始化屏幕采集器,传入系统停止采集的回调 videoCapturer = new ScreenCapturerAndroid(mediaProjection, new MediaProjection.Callback() { @Override public void onStop() { // 系统强制停止屏幕共享时,自动切回摄像头采集 runOnUiThread(this::switchBackToCamera); } }); surfaceTextureHelper = SurfaceTextureHelper.create("ScreenCaptureThread", eglBaseContext); // 创建屏幕视频源,传入screencast标记 VideoSource videoSource = peerConnectionFactory.createVideoSource(videoCapturer.isScreencast()); localVideoTrack = peerConnectionFactory.createVideoTrack("118", videoSource); videoCapturer.initialize(surfaceTextureHelper, context, videoSource.getCapturerObserver()); // 按照设备实际屏幕分辨率启动采集,不要硬编码固定分辨率 DisplayMetrics metrics = context.getResources().getDisplayMetrics(); videoCapturer.startCapture(metrics.widthPixels, metrics.heightPixels, 30); // 动态替换发送端绑定的视频Track peerConnectionClient.localVideoSender.setTrack(localVideoTrack, true); }
注意:不需要在切换时重复创建音频Track,WebRTC连接建立时初始化的音轨已经保持激活状态,重复创建反而会引发音轨冲突导致连接异常。
切回摄像头的处理
屏幕共享结束需要切回摄像头时,重复上面的资源释放流程,再重新初始化摄像头采集器即可,全程不需要重建PeerConnection。
关键避坑点
- 最常见的2-3秒断流诱因:Android 10及以上版本如果没有为屏幕采集绑定常驻前台服务,系统会在3秒左右自动收回屏幕采集权限,这也是很多开发者遇到该问题的核心原因
- 屏幕采集的分辨率要匹配设备实际输出尺寸,硬编码非原生分辨率很容易触发系统采集保护机制
- 动态替换Track后不需要发送新的Offer/Answer,AntMedia框架内部的Sender会自动更新推流的媒体源
- 不要在采集线程做耗时操作,避免采集线程被阻塞导致码流中断
内容的提问来源于stack exchange,提问作者Vijay E
相关产品推荐
相关产品推荐

