安卓上WebRtc

在 Android 上使用 WebRTC,可分为「官方 SDK」和「自己编译源码」两条路线。

多数业务场景直接依赖官方发布的 AAR 即可,下面给出一套从 0 到 1 的落地步骤(基于官方 AAR)。


一、准备工作

  1. Android Studio ≥ 4.0
  2. minSdkVersion ≥ 21(建议 23+)
  3. 真机或模拟器(模拟器需支持 Camera2)

二、在工程里引入 WebRTC

app/build.gradle

java 复制代码
implementation 'org.webrtc:google-webrtc:1.0.32006'   // 官方最新稳定版
implementation 'org.java-websocket:Java-WebSocket:1.5.3' // 仅示例,用 WebSocket 做信令

三、Manifest 权限与特性

xml 复制代码
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>

<uses-feature android:name="android.hardware.camera" android:required="true"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>

动态权限申请代码略(可用 EasyPermissions / RxPermission)。


四、初始化 WebRTC(一次性在 Application 或 Activity 中做)

java 复制代码
PeerConnectionFactory.InitializationOptions init =
        PeerConnectionFactory.InitializationOptions.builder(context)
                .setEnableInternalTracer(true)
                .setFieldTrials("WebRTC-H264HighProfile/Enabled/")
                .createInitializationOptions();
PeerConnectionFactory.initialize(init);

五、创建 PeerConnectionFactory

java 复制代码
// EGL 上下文,用于硬件加速编解码 & 渲染
EglBase rootEgl = EglBase.create();

// 视频编解码工厂
VideoEncoderFactory encoderFactory =
        new DefaultVideoEncoderFactory(rootEgl.getEglBaseContext(), true, true);
VideoDecoderFactory decoderFactory =
        new DefaultVideoDecoderFactory(rootEgl.getEglBaseContext());

// 音频模块
AudioDeviceModule adm = JavaAudioDeviceModule.builder(context).createAudioDeviceModule();

PeerConnectionFactory factory = PeerConnectionFactory.builder()
        .setAudioDeviceModule(adm)
        .setVideoEncoderFactory(encoderFactory)
        .setVideoDecoderFactory(decoderFactory)
        .setOptions(new PeerConnectionFactory.Options()) // 可关闭加密/网络监控
        .createPeerConnectionFactory();

六、采集本地音视频

  1. 视频源
java 复制代码
SurfaceTextureHelper surfaceHelper =
        SurfaceTextureHelper.create("CaptureThread", rootEgl.getEglBaseContext());

CameraEnumerator enumerator = new Camera1Enumerator(true);  // Camera2Enumerator 亦可
String camName = enumerator.getDeviceNames()[0];            // 默认后置
VideoCapturer capturer = enumerator.createCapturer(camName, null);

VideoSource videoSource = factory.createVideoSource(capturer.isScreencast());
capturer.initialize(surfaceHelper, context, videoSource.getCapturerObserver());
capturer.startCapture(1280, 720, 30);

VideoTrack localVideoTrack = factory.createVideoTrack("ARDAMSv0", videoSource);
  1. 音频源
java 复制代码
AudioSource audioSource = factory.createAudioSource(new MediaConstraints());
AudioTrack localAudioTrack = factory.createAudioTrack("ARDAMSa0", audioSource);

七、本地渲染(SurfaceViewRenderer)

xml 复制代码
<org.webrtc.SurfaceViewRenderer
    android:id="@+id/localRenderer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
java 复制代码
SurfaceViewRenderer localRenderer = findViewById(R.id.localRenderer);
localRenderer.init(rootEgl.getEglBaseContext(), null);
localVideoTrack.addSink(localRenderer);

八、创建 PeerConnection & 信令交换

  1. 配置 ICE 服务器
java 复制代码
List<PeerConnection.IceServer> iceServers = new ArrayList<>();
iceServers.add(PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer());
// 有 TURN 账号也可加
  1. 创建 PeerConnection
java 复制代码
PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);
PeerConnection pc = factory.createPeerConnection(rtcConfig, new PeerConnectionObserver() {
    @Override public void onIceCandidate(IceCandidate iceCandidate) {
        // 通过信令通道发送给对方
        sendIceCandidateToRemote(iceCandidate);
    }
    @Override public void onAddTrack(RtpReceiver rtpReceiver, MediaStream[] mediaStreams) {
        VideoTrack remoteVideoTrack = (VideoTrack) mediaStreams[0].videoTracks.get(0);
        remoteVideoTrack.addSink(remoteRenderer); // 远端渲染
    }
});
// 把本地轨道加入
pc.addTrack(localVideoTrack, Collections.singletonList("ARDAMS"));
pc.addTrack(localAudioTrack, Collections.singletonList("ARDAMS"));
  1. 信令流程(伪代码)
  • 收到 room 中新成员通知 → createOffer → setLocalDescription → 发送 Offer
  • 收到 Answer → setRemoteDescription
  • 收到 ICE candidate → addIceCandidate

信令通道可用 WebSocket、Socket.IO、FCM 任意实现。


九、远端渲染

与本地渲染完全一样,再准备一个 SurfaceViewRenderer 即可。


十、释放资源

java 复制代码
capturer.stopCapture();
capturer.dispose();
pc.close();
factory.dispose();
rootEgl.release();

十一、常见坑排查

现象 可能原因
黑屏 未调用 startCapture/addSink,或 EGL 线程冲突
听不到声音 未动态申请 RECORD_AUDIO,或 AudioTrack 未 addTrack
连不上 防火墙拦截 UDP,需要 TURN
崩溃 so not found 64 位 so 未打入,检查 Gradle abiFilters

十二、进阶方向

  • 多人会议:SFU(Janus/mediasoup)
  • 数据通道:DataChannel 传文件 / 白板
  • 编译源码:定制编解码器、裁剪包大小
  • 性能调优:硬件编解码、带宽估计、抖动缓冲

至此,即可在 Android 上完成一次完整的 WebRTC 点对点通话。

相关推荐
REDcker16 小时前
Android WebView 版本升级方案详解
android·音视频·实时音视频·webview·js·编解码
麦兜*16 小时前
【springboot】图文详解Spring Boot自动配置原理:为什么@SpringBootApplication是核心?
android·java·spring boot·spring·spring cloud·tomcat
le16161616 小时前
Android 依赖种类及区别:远程仓库依赖、打包依赖、模块依赖、本地仓库依赖
android
lxysbly16 小时前
psp模拟器安卓版带金手指
android
云上凯歌17 小时前
02 Spring Boot企业级配置详解
android·spring boot·后端
hqiangtai17 小时前
Android 高级专家技术能力图谱
android·职场和发展
aqi0017 小时前
FFmpeg开发笔记(九十七)国产的开源视频剪辑工具AndroidVideoEditor
android·ffmpeg·音视频·直播·流媒体
stevenzqzq17 小时前
Android Koin 注入入门教程
android·kotlin
炼金术18 小时前
SkyPlayer v1.1.0 - 在线视频播放功能更新
android·ffmpeg
用户2760381578118 小时前
鲲鹏+昇腾:开启 AI for Science 新范式——基于PINN的流体仿真加速实践
android