react-native-webrtc2

1.84.5 • Public • Published

react-native-webrtc2(Support transceiver APIs - unified-plan mode)

React Native Version npm version npm downloads

用于 React Native 的 WebRTC 模块

  • 支持 iOS / Android(plan-b 模式:W3C 建议弃用).
  • 支持 Video / Audio / Data Channels.
  • 仅 Android 版支持: Transceiver API(unified-plan 模式:W3C 建议使用).

NOTE 对于 Expo 用户:除非您退出,否则此插件将不起作用。 wanWYd waKax1 wanRFH wauoC9 wau54J

感谢开源项目

社区

欢迎大家光临我们的 Discourse community 讨论任何与 React Native 和 WebRTC 相关的主题。

WebRTC 修订版

  • 当前使用版本: M84
  • 支持的架构
    • Android: armeabi-v7a, arm64-v8a, x86, x86_64
    • iOS: arm64, x86_64

WebRTC 修订版(旧)

react-native-webrtc WebRTC Version arch(ios) arch(android) npm published notes
1.75.2 M75 x86_64
i386
armv7
arm64
armeabi-v7a
arm64-v8a
x86
x86_64
✔️
1.75.1 M75 x86_64
i386
armv7
arm64
armeabi-v7a
arm64-v8a
x86
x86_64
✔️
1.75.0 M75 x86_64
i386
armv7
arm64
armeabi-v7a
arm64-v8a
x86
x86_64
✔️
1.69.2 M69 x86_64
i386
armv7
arm64
armeabi-v7a
arm64-v8a
x86
x86_64
✔️
1.69.1 M69
commit
(24012)
(+16-24348)
x86_64
i386
armv7
arm64
armeabi-v7a
arm64-v8a
x86
x86_64
✔️
1.69.0 M69
commit
(24012)
(+16-24348)
x86_64
i386
armv7
arm64
armeabi-v7a
x86
✔️
master M75 x86_64
i386
armv7
arm64
armeabi-v7a
arm64-v8a
x86
x86_64
⚠️ Please test!

请参见 wiki page 关于修订历史。

安装

使用

现在,请先看下图,WebRTC 认证、协议握手流程图(其中需要 信令服务器,媒体服务器[ STUN、TURN ]) certification

这儿有个 信令服务器 可用于 开发、测试,使用 socket.io 加房间方式。(仅开发、测试,正式运营,需要自己写信令服务器 和 压力测试)

现在,您可以像在浏览器中一样使用WebRTC。在你的 index.ios.js/index.android.js, 您可以在 WebRTC 项目中 导入 RTCPeerConnection,RTCSessionDescription 等。

import {
  RTCPeerConnection,
  RTCIceCandidate,
  RTCSessionDescription,
  RTCRtpTransceiver,
  RTCRtpReceiver,
  RTCRtpSender,
  RTCView,
  MediaStream,
  MediaStreamTrack,
  mediaDevices,
  registerGlobals
} from 'react-native-webrtc2';

关于使用 RTCPeerConnection,RTCSessionDescription 和 RTCIceCandidate 的任何内容都类似于浏览器。 支持大多数 WebRTC API,请参阅 Mozilla Document.

var sdpSemantics = "plan-b"; //unified-plan: 收发器,plan-b: 常规
const configuration = {"iceServers": [{"url": "stun:stun.l.google.com:19302"}], sdpSemantics: sdpSemantics};
const pc = new RTCPeerConnection(configuration);
 
let isFront = true;
mediaDevices.enumerateDevices().then(sourceInfos => {
  console.log(sourceInfos);
  let videoSourceId;
  for (let i = 0; i < sourceInfos.length; i++) {
    const sourceInfo = sourceInfos[i];
    if(sourceInfo.kind == "videoinput" && sourceInfo.facing == (isFront ? "front" : "environment")) {
      videoSourceId = sourceInfo.deviceId;
    }
  }
  mediaDevices.getUserMedia({
    audio: true,
    video: {
      mandatory: {
        minWidth: 500, // Provide your own width, height and frame rate here
        minHeight: 300,
        minFrameRate: 30
      },
      facingMode: (isFront ? "user" : "environment"),
      optional: (videoSourceId ? [{sourceId: videoSourceId}] : [])
    }
  })
  .then(stream => {
    // Got stream!
  })
  .catch(error => {
    // Log error
  });
});
 
pc.createOffer().then(desc => {
  pc.setLocalDescription(desc).then(() => {
    // Send pc.localDescription to peer
  });
});
 
pc.onicecandidate = function (event) {
  // send event.candidate to peer
};
 
// 支持的事件
// onnegotiationneeded, oniceconnectionstatechange, onsignalingstatechange, onicecandidate
// onaddstream, onremovestream, ontrack, ondatachannel
 
// 支持的方法
//setRemoteDescription, createAnswer,addIceCandidate, addTransceiver, setDirection, getRtpSenders
//addStream, removeStream, addTrack, removeTrack, replaceTrack, stop
 
//并且支持 Data Channel

收发器介绍( Transceiver API )

收发器方向,一共有四种:sendrecv、sendonly、recvonly、inactive( 提示:会导致 C++ 销毁收发器,销毁后不能使用 setDirection(方向) )

pc.addTransceiver('audio' | 'video' | MediaStreamTrack, {direction: 'sendrecv'})
.then((res)=>{
  that.state.videoTransceiver = res;
})
 
//控制收发器,工作模式(音频流 只接收、只发送 、视频流 只接收、只发送)
//从而控制:麦克风静音,关闭远程摄像头 等
this.state.videoTransceiver.setDirection("recvonly")

direction

RTCView

但是,渲染视频流应以 React 方式使用(e.g)。

//使用 sdpSemantics: plan-b -> addStream(MediaStream) 下的 toURL 方法(是一个 UUID)
<RTCView streamURL={this.state.stream.toURL()}/>
 
//使用 sdpSemantics: unified-plan -> addTrack(MediaStreamTrack) outStream 是一个 UUID)
//推荐使用(实验室功能,可控制 收发器 方向)
<RTCView streamURL={this.state.videoTrack.toURL()}/>
 
//媒体流 和 媒体轨道,都集成 toURL 方法,无需刻意区分(e.g)。
pc.ontrack = function(event){
  //如果是视频,才渲染给 RTCView
  if(event.track.kind === "video"){
    that.setState({videoTrack: event.track});
  }
}
属性名称 类型 默认值 描述
mirror boolean false 指在渲染过程中 “streamURL” 指定的视频是否是镜像。通常,应用程序选择镜像启用手机相机。
objectFit string 'contain' 可选择 (contain) 或者 (cover)
streamURL string '' 必须的(本地视频轨道 UUID 或者远程视频轨道 UUID)
zOrder number 0 类似于 zIndex

自定义 APIs

registerGlobals()

通过调用此方法,JavaScript 可注册全局对象,并增加以下内容:

  • navigator.mediaDevices.getUserMedia()
  • navigator.mediaDevices.enumerateDevices()
  • window.RTCPeerConnection
  • window.RTCIceCandidate
  • window.RTCSessionDescription
  • window.MediaStream
  • window.MediaStreamTrack
  • -------以下对象(新增)--------
  • window.RTCRtpTransceiver
  • window.RTCRtpReceiver
  • window.RTCRtpSender

这儿提供了一些全局变量,以帮助你像 Web 浏览器一样使用 WebRTC,同时 WebRTC JavaScript libraries 将更好的和 react-native-webrtc2 (native code) 通讯。

MediaStreamTrack.prototype.switchCamera()

此功能允许在视频轨道中即时切换 前置、后置 摄像机,而无需 添加、删除 轨道或重新商定协议。

VideoTrack.enabled

此项不适用于 unified-plan 模式

从版本 1.67 开始,将本地视频轨道的启用状态设置为 false 时,摄像机将关闭,但该轨道将保持活动状态。 将其重新设置为 true 将重新启用相机。

RTCPeerConnection.addTransceiver('audio' | 'video' | MediaStreamTrack, init)

添加收发器,会自动添加轨道(addTrack),不需手动添加,一个收发器,对应一个轨道,同时拥有(RTCRtpSender 和 RTCRtpReceiver)两个对象,可以使用 setDirection 方法设置收发方向。

  • (Promise)返回:收发器对象(RTCRtpTransceiver)
for (var i = 0; i < stream.getTracks().length; i++) {
    var track = stream.getTracks()[i]
    var info = {
      constraints: track.getConstraints(),
      enabled: track.enabled,
      id: track.id,
      kind: track.kind,
      label: track.label,
      muted: track.muted,
      remote: track.remote,
      readyState: track.readyState,
    }
    var mediaStreamTrack = new MediaStreamTrack(info);
 
    //direction:sendrecv 发送接收,sendonly 只发送,recvonly 只接收,inactive 不发送不接收,未激活
    //建议用 mediaStreamTrack 方式,添加收发器。
    pc.addTransceiver(mediaStreamTrack, {direction: 'sendrecv'}).then((rtpTransceiver)=>{
      this.state.rtpTransceiver = rtpTransceiver;
      //this.state.rtpTransceiver.setDirection("sendrecv")
      console.log("收发器(RTCRtpTransceiver):", rtpTransceiver);
    })
    'or' //audio, video
    pc.addTransceiver('audio', {direction: 'sendrecv'})
 
    //用 audio, video 这种方式,反复关闭连接,在进入可能会有连接不上,可在添加收发器后
    //加入这句代码(addTrack)保证每次能连接上去,如未出现,可忽略。
    for (const track of stream.getTracks()) {
      pc.addTrack(track);
    }
}

RTCRtpTransceiver.stop()

停止收发器:此项是单向不可逆的,停止后将永不能使用。

RTCRtpTransceiver.isStopped: boolean

获取此收发器,是否停止(true, false)

RTCRtpSender.replaceTrack

将一个新的 MediaStreamTrack 对象,作为参数,交给 RTCRtpSender 发送者,可替换当前轨道(Audio、Video)。入参:MediaStreamTrack
提示:替换后,程序智能将收发器重置为 direction = sendrecv,确保 RTC 通讯正常。

* 新增 RTCPeerConnection.addTrack: RtpSender

为 RTCPeerConnection 增加 addTrack 方式,将满足 Transceiver API 规范。 入参:MediaStreamTrack
提示:智能判断是否存在收发器,存在,轨道将添加到收发器 RtpSender 里(同时设置:direction = sendrecv),否则 直接添加轨道到 RTCPeerConnection 中,支持通讯中,动态 removeTrack 和 addTrack 满足产品需求。( e.g )

  • (Promise)返回:RtpSender 对象
var that = this;
that.getLocalStream(false, (stream) => {
    that.state.isOffer = true;
    pc = new RTCPeerConnection(configuration);
 
    if(sdpSemantics === "unified-plan"){
        //添加收发器,会自动添加轨道
        pc.addTransceiver("audio", {direction: 'sendrecv'})
        .then((res)=>{
          that.state.audioTransceiver = res;
          console.log("添加收发器(音频轨):", res);
        })
        pc.addTransceiver("video", {direction: 'sendrecv'})
        .then((res)=>{
          that.state.videoTransceiver = res;
          console.log("添加收发器(视频轨):", res);
        })
 
        //加入这句代码(addTrack)保证每次能连接上去,如未出现,可忽略。
        for (const track of stream.getTracks()) {
          pc.addTrack(track).then((result) => {
            console.log("RtpSender:", result);
          });
        }
    }
})

* 新增 RTCPeerConnection.removeTrack

为 RTCPeerConnection 增加 removeTrack 方式,将满足 Transceiver API 规范。 入参:RtpSender(可以从 RTCPeerConnection -> getRtpSenders 获取 Array 列表,指定移除某个轨道,RtpSender -> track() 可以查看 MediaStreamTrack 对象)

  • (Promise)返回:boolean 成功、失败

* 新增 RTCPeerConnection.getRtpSenders: Array< RtpSender >

获取 RTCPeerConnection 托管的,所有 RtpSenders 对象集,这些对象是使用 RTCPeerConnection.addTrack 添加的(会调用 android 本地代码取值),所以是异步的。

  • (Promise)返回:Array< RtpSender >,建议使用 async 和 await 关键字。

* 为 setDirection 设置进度对话框(Progress Dialog)

为解决快速 setDirection 设置方向舵, C++ 报错导致 APP 崩溃,新增弹出进度对话框,延迟 2 秒关闭。

  • 传入参数
    • direction (String:sendrecv,sendonly,recvonly ,inactive)
    • isShow (boolean:可选,默认 - true)是否显示,进度对话框(Progress Dialog)

* 重要提示:

客户端 A createOffer,setLocalDescription 后,连接信令服务器,客户端 B 在连接信令服务器,此时客户端 A 需要重新 和 客户端 B 商定 SDP(再次 createOffer,setLocalDescription)通过信令,告诉客户端 B,其中 SDP 包含,transceiver(收发器)相关重要信息 direction:(sendrecv sendonly recvonly inactive。如果不重新商定,告诉客户端 B,收发器将失效。

如果打开混淆 WebRTC,请配置

在文件 proguard-rules.pro 中配置
-keep class org.webrtc.** { *; }

相关项目

react-native-incall-manager

使用 react-native-incall-manager 使屏幕保持打开状态,使麦克风静音等。

react-native-callkeep

使用 react-native-callkeep 在 iOS 上使用 Callkit 或在 Android 上使用连接服务,以使 webrtc 应用程序具有本机拨号程序。

赞助商

该存储库没有获得赞助的计划。(以后可以由合作者讨论)。 如果您想为解决某些错误或获得某些功能而赏金,可以随意打开一个添加 [BOUNTY] 标题中的类别。 添加其他赏金网站链接,例如 this 会更好。

创作者

该代码库最初是由创建的 Wan Huang Yang,后经过 Openland 组织 加入收发器,再由作者本人,修复 bug 添加一些 API,单元测试。

协议(License)

MIT

Package Sidebar

Install

npm i react-native-webrtc2

Weekly Downloads

0

Version

1.84.5

License

MIT

Unpacked Size

47.5 MB

Total Files

171

Last publish

Collaborators

  • juncocoa