You need to enable JavaScript to run this app. Android AntMedia WebRTC 摄像头切换屏幕共享时出现源错误
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.05 01:06:04