You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebRTC Android推流至网页示例:摄像头切换功能实现求助

我之前正好在WebRTC项目里处理过基于VideoCapturerAndroid的摄像头切换需求,给你一套经过验证的可行方案,一步步来操作:

基于VideoCapturerAndroid实现WebRTC摄像头切换方案

1. 先保存核心对象引用

在你的Activity类中,声明全局变量来存储摄像头捕获、视频源、轨道等关键实例,这样切换时能方便地操作旧资源:

private VideoCapturerAndroid videoCapturer;
private VideoSource videoSource;
private VideoTrack localVideoTrack;
private PeerConnectionFactory peerConnectionFactory;
private PeerConnection peerConnection; // 如果已经建立了连接,需要这个对象
private boolean isUsingFrontCamera = true; // 默认使用前置摄像头

注意:你需要在初始化摄像头的代码中,把这些变量赋值(比如原来创建VideoCapturerAndroid、VideoSource的地方),举个初始化示例:

// 初始化摄像头的参考代码(替换你原有逻辑)
private void initCamera() {
    // 假设peerConnectionFactory已经完成初始化
    String frontCameraId = VideoCapturerAndroid.getNameOfFrontFacingDevice();
    try {
        videoCapturer = VideoCapturerAndroid.create(frontCameraId);
        videoSource = peerConnectionFactory.createVideoSource(videoCapturer);
        localVideoTrack = peerConnectionFactory.createVideoTrack("localVideoTrack", videoSource);
        // 绑定到本地预览(假设你用的是SurfaceViewRenderer)
        localVideoTrack.addSink(localSurfaceViewRenderer);
        // 启动捕获
        videoCapturer.startCapture(640, 480, 30); // 可根据需求调整分辨率、帧率
        isUsingFrontCamera = true;
    } catch (IOException e) {
        e.printStackTrace();
    }
}

2. 实现摄像头切换核心方法

编写切换逻辑,核心是停止旧捕获→释放资源→创建新捕获→更新轨道和预览:

private void switchCamera() {
    // 1. 停止并释放旧的摄像头资源
    if (videoCapturer != null) {
        videoCapturer.stopCapture();
        videoCapturer.dispose();
    }
    if (videoSource != null) {
        videoSource.dispose();
    }

    // 2. 切换摄像头标识,获取新摄像头ID
    isUsingFrontCamera = !isUsingFrontCamera;
    String targetCameraId = isUsingFrontCamera ? 
        VideoCapturerAndroid.getNameOfFrontFacingDevice() : 
        VideoCapturerAndroid.getNameOfBackFacingDevice();

    // 3. 创建新的VideoCapturer实例
    try {
        videoCapturer = VideoCapturerAndroid.create(targetCameraId);
    } catch (IOException e) {
        e.printStackTrace();
        return;
    }

    // 4. 重新创建视频源和轨道
    videoSource = peerConnectionFactory.createVideoSource(videoCapturer);
    localVideoTrack = peerConnectionFactory.createVideoTrack("localVideoTrack", videoSource);

    // 5. 更新本地预览
    localVideoTrack.addSink(localSurfaceViewRenderer);

    // 6. 如果已经和远端建立连接,替换PeerConnection中的本地轨道
    if (peerConnection != null) {
        // 找到旧的视频轨道Sender并移除
        peerConnection.getSenders().stream()
                .filter(sender -> sender.track() != null && sender.track().id().equals("localVideoTrack"))
                .findFirst()
                .ifPresent(peerConnection::removeTrack);
        // 添加新的视频轨道
        peerConnection.addTrack(localVideoTrack, MediaStream.DEFAULT_MEDIA_STREAM_ID);
    }

    // 7. 启动新摄像头的捕获
    try {
        videoCapturer.startCapture(640, 480, 30);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3. 绑定UI触发切换

给你的切换按钮添加点击事件,直接调用上面的方法即可:

@OnClick(R.id.btn_switch_camera)
public void onSwitchCameraClicked() {
    switchCamera();
}

关键注意事项

  • 确保已申请CAMERA权限,切换时无需重新申请,但首次启动必须有权限
  • 切换前务必停止旧的捕获,否则会出现摄像头被占用的错误
  • 如果你的预览组件不是SurfaceViewRenderer,替换成你实际使用的组件即可

内容的提问来源于stack exchange,提问作者Jaan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:41:24