2025年7月14日月曜日

react-nativeでjanusのstream動画を受信する


背景

react-nativeとはjavascriptでAndroidやiOS向けのアプリを作れる環境です。
janusとはWebRTC通信の仲介をしてくれるサーバープログラムです。

前回把握したjanusのapiとjavascriptのWebRTCPeerConnectionを利用してstream動画の受信方法を流用しつつ、WebRTCPeerConnectionの部分をreact-native-webrtcの関数に置き換えればreact-native環境でもjanusのstram動画を受信できました。

詰まりどころがあったので、備忘録を兼ねて記述方法を記事に残します。

使ったもの

react-native 0.79.4
今回はexpoを使わないreact-native環境で動作確認しました。

react-native-webrtc 124.0.5
今回はexpoを使わなかったのでこのライブラリのみで済みましたが、expo環境の場合はこれに加えてconfig-plugins/react-native-webrtcの利用が必要そうです。

Android 14のスマートフォン
Zenfone9で動作確認しました。

react-native-webrtcのAndroid用の設定

Android用の説明を参考にしつつ下記の設定を有効にしました。
iOSの場合はそれ用の説明を参考に設定を施してください。

stream動画の受信だけならNETWORK系とINTERNETの権限付与で済みます。
android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

tsx(js)のコード

WebSocketを利用したjanus apiからの情報取得は前回の記事と同じものが動くので、前回の下記の記事を参考にしてください。
janusのstream動画をapiとRTCPeerConnectionで受信 

ここでは主にreact-native-webrtcを利用する箇所の注意点を説明します。

RTCPeerConnectionはreact-native-webrtcからimportしたものを使います。
インスタンス作成時はブラウザ環境のRTCPeerConnectionと異なりsdpSemanticsの指定が不要です。
react-native-webrtcのreadmeによると標準でunified-planが使われているようです。
import { RTCPeerConnection, MediaStream, RTCView } from 'react-native-webrtc';
  const peerConnection = new RTCPeerConnection({
iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
// sdpSemantics: "unified-plan",
})

stream情報の受け渡しはreactのstateを利用し、表示はreact-native-webrtcのRTCViewを使います。
RTCViewはjsのvideoで必要だったplay呼び出し無しで使えます。
MediaStreamは利用してもしなくても自分が試した範囲では挙動が同じでした。
import { RTCPeerConnection, MediaStream, RTCView } from 'react-native-webrtc';
  const [stream, setStream] = useState<any>(null)
        onTrack: (event: any) => {
if (event.track.kind == 'video') {
// setStream(event.streams[0]) // MediaStreamに変換せずこれでも良い
const stream = new MediaStream([event.track]);
console.log('stream', stream)
console.log(stream.toURL())
console.log(stream.getTracks())
console.log('put stream to videoTag')
setStream(stream)
}
},
      {!stream ? <Text>Stream is not avairable</Text>
: <RTCView
objectFit={'cover'}
streamURL={stream.toURL()}
zOrder={20}
style={{
width: "100%",
flex: 1,
}} />
}

RTCViewの幅の指定が無いとstream動画が再生されていても閲覧できないので、幅を指定します。
自分はこれが分からず時間を取られました。
        <RTCView
style={{
width: "100%",
flex: 1,
}} />

上記のコードを動かすと、janusで配信するstream動画をアプリで閲覧できました。

課題: WebRTCのresourceが勝手に開放されてしまう

stream動画を閲覧可能になったのは良いのですが、1分ほど経過するとjanus側でWebRTC resources freedのログが出て動画が止まってしまいます。
[5697525146018126] WebRTC resources freed; 0x7a68d4024750 0x7a68d40152a0
[5697525146018126] Handle and related resources freed; 0x7a68d4024750 0x7a68d40152a0

閲覧継続のために何かが足りてないのだと思いますが、今の所原因箇所は不明です。

おわり

janusのapiで取得した情報をreact-native-webrtcを利用して接続しstream動画を閲覧できました。
前回のブラウザ環境と同様に時間が経つと接続が解除されてしまう不具合は残っていますが、閲覧はできたので一旦良しです。

参考

react-native-webrtcのgithubのページです。
react-native-webrtc

react-native-webrtc利用例を解説したブログ記事です。
全体像の把握に役立ちました。
How to Build a WebRTC React Native App?

RTCViewに幅の指定が必要と気づいたissueの投稿です。
RTCView is blank #606

0 件のコメント :