当前位置: 首页 > article >正文

【WebRTC】Android SDK使用教学

文章目录

  • 前言
  • PeerConnectionFactory
  • PeerConnection

前言

最近在学习WebRTC的时候,发现只有JavaScript的API文档,找了很久没有找到Android相关的API文档,所以通过此片文章记录下在Android应用层如何使用WebRTC

本篇文章结合:【WebRTC】适合新手宝宝的WebRTC入门教学一起食用更佳

PeerConnectionFactory

负责管理和创建WebRTC所需组件,例如:音视频轨道、PeerConnection,是WebRTC使用的起点

// 1. 初始化Factory,此步骤用于初始化日志、加载JniLib、对Jni进行初始化
PeerConnectionFactory.initialize(
    PeerConnectionFactory.InitializationOptions.builder(WebRtcApp.instance)
    .createInitializationOptions()// 2. 创建factory实例,通过builder可以设置编解码器工厂、AudioDeviceModule(音频设备管理模块)
peerConnectionFactory = PeerConnectionFactory.builder()
    .setOptions(PeerConnectionFactory.Options())
    .setAudioDeviceModule(audioDeviceModule)
    .setVideoDecoderFactory(defaultDecoder)
    .setVideoEncoderFactory(defaultEncoder)
    .createPeerConnectionFactory()
    
// 3. 创建peerConnection、音视频轨道等
localPeerClient = peerConnectionFactory.createPeerConnection()
videoSource = peerConnectionFactory.createVideoSource(false)
localVideoTrack = peerConnectionFactory.createVideoTrack(WebRtcConstant.VideoTrackID, videoSource)

PeerConnection

这是WebRTC API中最重要的类,负责点对点连接的建立,音视频推流等

1. PeerConnection.RTCConfiguration

WebRTC连接参数,必须通过ICE服务器(PeerConnection.IceServer)列表进行构建

val rtcConfig = PeerConnection.RTCConfiguration(peerIceServers)
rtcConfig.apply {
    bundlePolicy = PeerConnection.BundlePolicy.MAXBUNDLE
    sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN
    continualGatheringPolicy = PeerConnection.ContinualGatheringPolicy.GATHER_CONTINUALLY
    keyType = PeerConnection.KeyType.ECDSA
    rtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.REQUIRE
    tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.ENABLED
    suspendBelowMinBitrate = true
}

2. 交换SDP

PeerConnection提供了SDP Offer的创建和发送相关方法

// 1. 创建offer
localPeerClient.createOffer(object : KinesisVideoSdpObserver() {
    override fun onCreateSuccess(sessionDescription: SessionDescription) {
        // 1.1 创建offer成功回调
        super.onCreateSuccess(sessionDescription)
        // 2. 创建成功后需要将offer设置为LocalDescription
        localPeerClient.setLocalDescription(KinesisVideoSdpObserver(), sessionDescription)
        
        // 3. 此时应该通过信令服务器将offer发送给远端
    }}, AwsEngine.getSdpMediaConstraints())

// 4. 当收到远端响应的answer时,设置为RemoteDescription
localPeerClient.setRemoteDescription(KinesisVideoSdpObserver(), sdpAnswer)

// 5. 当收到远端的offer时,此时先设置RemoteDescription然后需要响应answer
localPeerClient.createAnswer(object : KinesisVideoSdpObserver() {
        override fun onCreateSuccess(sessionDescription: SessionDescription) {
            // 5.1 创建answer成功
            super.onCreateSuccess(sessionDescription)
            // 5.2 设置为LocalDescription
            it.setLocalDescription(KinesisVideoSdpObserver(), sessionDescription)
            
            // 5.3 通过信令服务器发送回远端
        }
    }, MediaConstraints())
}

3. 设置ICE候选地址对

ICE候选地址对的来源有两个,一个是由localPeerClient在创建后根据PeerConnection.IceServer返回的,这些地址需要同发送给远端。另一个来源是远端设备,远端设备在与ICE通信后会得到它的候选地址对,此时远端会通过信令服务器通知本设备。

peerConnectionFactory.createPeerConnection(rtcConfig,
    object : KinesisVideoPeerConnection() {
        override fun onIceCandidate(iceCandidate: IceCandidate) {
            // 1. 由WebRTC自动探测出的候选地址对回调
            super.onIceCandidate(iceCandidate)
            // 1.1 通过信令服务器告诉远端
            signalingClient?.sendIceCandidate(message)
        }
    }
)


// 2. 来自信令服务器的回调
override fun onReceiverIceCandidate(event: Event) {
    // 2.1 收到远端的候选地址对后,添加到本地的WebRTC中,等待WebRTC自行尝试连接
    val iceCandidate = Event.parseIceCandidate(event)
    PeerConnection.addIceCandidate(iceCandidate)
}

4. 添加本地音视频轨道

在WebRTC建立连接后,此时远端的数据会通过回调传来,如果本机需要向远端推流,此时只需要设置音视频轨道即可

// 1. 创建一个空流,需要手动为期添加音轨和视频轨
stream = peerConnectionFactory.createLocalMediaStream(WebRtcConstant.LOCAL_MEDIA_STREAM_LABEL)

// 2. 创建视频源,默认创建的源是没有数据的,通常要与摄像头、或自定义数据源进行绑定
videoSource = peerConnectionFactory.createVideoSource(false)

// 3. 创建视频轨道,可以绑定到 UI 组件(如本地预览)或添加到 PeerConnection。
//    例如将视频轨道绑定到本地预览视图:localVideoTrack.addSink(localVideoView)
localVideoTrack = peerConnectionFactory.createVideoTrack(WebRtcConstant.VideoTrackID, videoSource)

// 4. 向流添加视频轨
stream.addTrack(localVideoTrack)
// 5. 将视频流交至WebRTC处理
localPeerClient?.addTrack(stream!!.videoTracks[0], listOf(stream!!.id))

ps:为什么要设计将数据源和数据轨道分开来

  • 解藕数据源和传输的逻辑,数据源负责数据的采集和生成,数据轨道负责数据的传输
  • 可实现多个数据轨道共享同一个数据源,避免重复采集

5. 开启数据通道

WebRTC不仅提供数据流的传输,还能提供数据报文传输,只需要打开数据通道

// 1. 创建数据通道
localDataChannel = localPeerClient?.createDataChannel("data-channel-of-${connectParameter?.clientId}", DataChannel.Init())
// 2. 注册消息监听
localDataChannel?.registerObserver(object :DataChannel.Observer{
    override fun onBufferedAmountChange(previousAmount: Long) {}
    override fun onStateChange() {}
    override fun onMessage(buffer: DataChannel.Buffer) {
        // 2.1 远端消息到来时回调
        val byteArray = ByteArray(buffer.data.remaining())
        buffer.data.get(byteArray)
        val messageStr = String(byteArray, Charsets.UTF_8)
    }
})
// 3. 向远端发送消息
localDataChannel?.send(
    DataChannel.Buffer(
        ByteBuffer.wrap(content.toByteArray(Charset.defaultCharset())),
        false
    )
)

http://www.kler.cn/a/429835.html

相关文章:

  • Kivy App开发之UX控件DropDown下拉列表
  • Agentless:OpenAI 采用的非代理框架
  • 【黑马程序员三国疫情折线图——json+pyechart=数据可视化】
  • Angular 最新版本和 Vue 对比完整指南
  • 如何使用靜態IP代理?【詳細教程】
  • 云原生周刊:在Docker上部署大语言模型
  • scala 身份证号码
  • hping3-网络工具
  • Brain.js(六):构建FNN神经网络实战教程 - 用户喜好预测
  • 鸿蒙实现后台任务管理
  • 「Mac畅玩鸿蒙与硬件44」UI互动应用篇21 - 随机励志语录生成器
  • Springboot3整合Redis
  • Fyne ( go跨平台GUI )中文文档-Fyne总览(二)
  • gitlab配置调试minio
  • Java将数组转换成字符串
  • 构建万能 MOCK-API
  • 如何在拉丁美洲推广游戏
  • docker逃逸总结
  • vue+elementUI+transition实现鼠标滑过div展开内容,鼠标划出收起内容,加防抖功能
  • docker搭建elasticsearch服务
  • python爬虫--小白篇【爬虫实践】
  • R 语言科研绘图第 4 期 --- 折线图-置信区间
  • 一种基于通义千问prompt辅助+Qwen2.5-coder-32b+Bolt.new+v0+Cursor的无代码对话网站构建方法
  • 使用 RabbitMQ 创建简单消费者的完整指南