Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
【DroidKaigi版】ReactNativeとKotlinで叶える夢のリアルタイム音声配信
yu mitsuhori
October 20, 2021
Technology
1
2.8k
【DroidKaigi版】ReactNativeとKotlinで叶える夢のリアルタイム音声配信
DroidKaigi2021での発表資料です
yu mitsuhori
October 20, 2021
Tweet
Share
More Decks by yu mitsuhori
See All by yu mitsuhori
ReactNativeとKotlinで叶える夢のリアルタイム音声配信
youmitsu
1
540
stand.fm(Android)におけるreact-native-track-playerの改善
youmitsu
1
1.4k
TargetSdkVersion29で BottomNavigationが点滅する件
youmitsu
1
1.1k
リリース前のリグレッションテストをUIテストで自動化、1年間運用した話
youmitsu
2
280
New features in RemoteConfig, Analytics at Google I/O 2019
youmitsu
1
380
FirebaseNotification,RemoteConfigでユーザセグメントごとにプッシュ通知を実装する
youmitsu
9
1.2k
Report from Google I/O 2019
youmitsu
1
49
OSSにコントリビュートした話
youmitsu
1
53
初めて自作ViewのAARライブラリを公開した話
youmitsu
1
310
Other Decks in Technology
See All in Technology
エアドロップ for オープンソースプロジェクト
epicsdao
0
390
立ち止まっても、寄り道しても / even if I stop, even if I take a detour
katoaz
0
440
230125 モニターマウントLT ITガジェット翁(Ryu.Cyber)さん
comucal
PRO
0
4.6k
私見「UNIXの考え方」/20230124-kameda-unix-phylosophy
opelab
0
160
ECテックカンファレンス2023 EC事業部のモバイル開発2023
tatsumi0000
0
290
OpenShiftでスポットVMを使おう.pdf
jpishikawa
1
280
NGINXENG JP#2 - 1-NGINX-エンジニアリング勉強会-きょうの見どころ
hiropo20
0
100
Deep Neural Networkの共同学習
hf149
0
160
OpenShiftのリリースノートを整理してみた
loftkun
2
320
Deep dive in Reserved Instance ~脳死推奨量購入からの脱却~
kzkmaeda
0
510
PCL (Point Cloud Library)の基本となぜ点群処理か_2023年_第2版.pdf
cvmlexpertguide
0
160
Multi-Cloud Gatewayでデータを統治せよ!/ Data Federation with MCG
tutsunom
1
220
Featured
See All Featured
JazzCon 2018 Closing Keynote - Leadership for the Reluctant Leader
reverentgeek
175
9.1k
Build your cross-platform service in a week with App Engine
jlugia
221
17k
Fashionably flexible responsive web design (full day workshop)
malarkey
396
63k
Code Reviewing Like a Champion
maltzj
508
38k
A Tale of Four Properties
chriscoyier
149
21k
How STYLIGHT went responsive
nonsquared
89
4.2k
Building Adaptive Systems
keathley
27
1.3k
A better future with KSS
kneath
230
16k
Building a Scalable Design System with Sketch
lauravandoore
451
31k
Intergalactic Javascript Robots from Outer Space
tanoku
261
26k
The Art of Programming - Codeland 2020
erikaheidi
35
11k
No one is an island. Learnings from fostering a developers community.
thoeni
12
1.5k
Transcript
ReactNativeとKotlinで叶える 夢のリアルタイム音声配信 株式会社stand.fm エンジニア 三堀 裕 2021/10/20 DroidKaigi 2021
三堀 裕 stand.fmのソフトウェアエンジニア モバイル開発がメイン。現在はReactNativeをやって います。前職ではAndroid、Flutterもやっていました 1013Youmeee 2
発表のテーマ、ゴール感 ゴール感 - ReactNativeAndroidにおけるNativeModuleの実装方法がわかる - ReactNativeAndroidのNativeModuleでのKotlinの導入方法がわかる - stand.fmのような音声収録・配信アプリの配信クライアントの実装の仕組みが わかる 3
「ReactNative with Kotlin」 〜ReactNativeでも音声収録・配信アプリは作れる〜
4 この発表における想定ターゲット - ReactNativeエンジニア - NativeModuleについて興味がある - NativeModuleを書いたことがあるが、Android側は今までJavaで書いていた
- Androidエンジニア - 音声配信のクライアント実装について興味がある方
本発表で話さないこと - iOS、サーバーサイドの実装方法について - 音声配信アプリの受信クライアントの実装方法(配信音声を聞く側) - 使用ライブラリの優劣については議論しません
- サンプルで使用する例が必ずしもベストプラクティスではないです。あくまで一例という前提でご覧 いただければと思います - 実装例はstand.fmと全く同じものではありません - あくまで簡易的なサンプルになります 5
アジェンダ - ReactNative、NativeModuleとは - ReactNativeでのKotlinの導入方法 - ReactNativeとKotlinを用いた音声収録・配信機能の実装 - 収録 -
配信(RTMP) - コラボ機能の紹介(WebRTC)※実装は割愛 - ReactNativeの音声ライブラリ紹介 - まとめ 6
ReactNative、 NativeModuleとは 7
ReactNativeについて - Facebookが実装したモバイルアプリケーションフレームワーク - クロスプラットフォーム開発の一つとして上げられる - Reactのエコシステムを生かした開発ができ、近年流行りの宣言的UIパターンやライブラリなど の恩恵を受けれる
- JavaScriptCoreやHermesなどのJavaScriptエンジンをベースとして動作し、JavaScript、 TypeScriptが利用可能 - レンダリングにはネイティブのコンポーネントが使われる - TextViewやFrameLayoutなど 8
ReactNativeのNativeModuleとは - ReactNativeでネイティブのコードを実行する仕組み - Android: Java, Kotlin
- iOS: Swift, Objective-C - https://reactnative.dev/docs/native-modules-intro 引用: https://medium.com/hackernoon/first-experiences-with-react-native-bridging-an-andr oid-native-module-for-app-authentication-501fec247b2b 9
NativeModuleの実装を知っておくと良いこと - Expoでの開発をしていたがネイティブのモジュールを使わざるを得なくなったとき - プラットフォームごとのSDKやAPIを用いないと実現できない場合がある (今回取り上げる音声の録音、配信などもこれに該当する) -
react-native関連のOSSライブラリがあるが、自分たちが望んでいる挙動でない場合や、クラッ シュなどの問題がある場合に対応できるようにしておく必要がある 10
AndroidのNativeModuleを実装する準備 1. AndroidStudioをインストール a. https://developer.android.com/studio 2. react-native init
コマンドで ReactNativeプロジェクトを作成 3. AndroidStudioでReactNativeプロジェクトの androidディレクトリを開く(→のようになる) 11 ↑ReactNativeプロジェクトをAndroidStudioで開く
12 NativeModule導入サンプル〜Androidのトースト表示〜 - トースト:Androidにおける簡易的なメッセージ表示をする コンポーネント - トーストを表示するサンプルを作ってみます
トースト
13 NativeModuleの主な実装ステップ 1. Java側 a. Moduleクラスを作る(JS側に公開するインターフェース) b. Packageクラスを作る
c. MainApplication.javaでbのpackageをわたす 2. JS側 a. Javaで定義したNativeModuleのインターフェースを実装する
14 NativeModuleによるJSとNative間のやり取りの種類 1. JS→Nativeを呼ぶ場合 2. Native→JSにイベントを通知する場合
NativeModuleの例(Java側)〜Androidのトースト表示〜 a. ToastModuleクラスを作る 15 public class ToastModule extends
ReactContextBaseJavaModule { public ToastModule(ReactApplicationContext context) { super(context); } @NonNull @Override public String getName() { return "ToastModule"; } @ReactMethod public void showToast(String text) { final Toast toast = Toast.makeText(getReactApplicationContext(), text, Toast.LENGTH_LONG); toast.show(); } } @ReactMethodアノテーションをつけたメソッドがJS側から実行できる JSに公開するNativeModuleの名前を定義 ReactContextBaseJavaModule を継承
NativeModuleの例(Java側)〜Androidのトースト表示〜 b. Packageクラスを作る 16 public class ToastPackage implements
ReactPackage { @NonNull @Override public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new ToastModule(reactContext)); return modules; } @NonNull @Override public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) { return Collections.emptyList(); } } ReactPackageインターフェースを実装 ToastModuleインスタンスを初期化し、追加
NativeModuleの例(Java側)〜Androidのトースト表示〜 c. MainApplication.javaにToastPackageのインスタンスを追加する 17 public class MainApplication extends
Application implements ReactApplication { private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override protected List<ReactPackage> getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List<ReactPackage> packages = new PackageList(this).getPackages(); packages.add(new ToastPackage()); return packages; } }; } Packageインスタンスを初期化し、追加
NativeModuleの例(JS側)〜Androidのトースト表示〜 a. NativeModuleのインターフェースを定義(toast.js) 18 // @flow import {
NativeModules } from 'react-native' const { ToastModule } = NativeModules const showToast = React.useCallback(() => { ToastModule.showToast('Tapped!') }, [showToast]) b. タップ時showToastメソッドをコールする→ return ( <SafeAreaView> <Pressable onPress={show}> <Text>SHOW TOAST!</Text> </Pressable> </SafeAreaView> ); 先程定義したToastModuleをimport ToastModuleのメソッドを呼び出す
19 NativeModule(Native→JSにイベントを通知する場合) - ネイティブ側からのEventをjs側に伝えるための手段 - NativeEventEmitterというものを使う WritableMap
params = Arguments.createMap(); params.putString("message", "Something is occured."); context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) .emit("SomethingEvent", params); import { NativeModules, NativeEventEmitter } from 'react-native' const eventEmitter = new NativeEventEmitter(NativeModules.SomethingModule) eventEmitter.addListener('SomethingEvent', (event) => { console.log(event.message) // output: Something is occured }) イベントパラメータの作成 イベント名とパラメータを指定してemit()を呼ぶ ネイティブで指定したイベント名でイベントをListenする 指定したModuleのNativeEventEmitterを定義
ReactNativeでの Kotlinの導入 20
- JetBrains製のJVM言語の一つ - Androidネイティブ開発におけるファースト言語とされている - 完全Java互換 - JavaからKotlinをコードを呼べるし、KotlinからJavaのコードを呼べる -
NullSafety, SealedClass, Coroutinesなど様々な言語機能を備えており生産性が高い Kotlinとは 21
ReactNativeライブラリはAndroid側はJavaで書かれている事が多い 22 「Kotlinで書きたい!!!」 Androidエンジニアとしては... と思うわけです。。 - 以下のようなライブラリをforkして修正することがあるが、これらはJavaで書かれている -
例1: react-native-share - https://github.com/react-native-share/react-native-share - 例2: react-native-track-player - https://github.com/DoubleSymmetry/react-native-track-player
ReactNativeでKotlinを使う方法 1. AndroidStudioでKotlinのプラグインをインストール a. Preferences > Plugins > 「Kotlin」を検索し、Installをする
2. build.gradleでKotlinの依存を含める a. build.gradleとapp/build.gradleの2つにKotlinを利用するための宣言を書く 23
buildscript { ext { kotlin_version = '1.4.10' // add }
dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // add } } 24 build.gradleでKotlinの依存を含める build.gradle apply plugin: "com.android.application" apply plugin: "kotlin-android" // add apply plugin: "kotlin-android-extensions" // add … dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" // add } SyncNowを押下し、依存モジュールをインストール app/build.gradle
25 既存コードをKotlinに変換する - AndroidStudioでは「Convert Java File to Kotlin File」
というコマンドがある - これを実行すると自動的にJavaをKotlinに変換してくれる - 変換されたコードはKotlinらしい書き方になっていない場合 があるので気になる方は直すと良い
変換前:ToastModule.java(例) 26 public class ToastModule extends ReactContextBaseJavaModule { public ToastModule(ReactApplicationContext
context) { super(context); } @NonNull @Override public String getName() { return "ToastModule"; } @ReactMethod public void showToast(String text) { final Toast toast = Toast.makeText(getReactApplicationContext(), text, Toast.LENGTH_LONG); toast.show(); } }
変換後:ToastModule.kt(例) 27 class ToastModule(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) { override fun
getName(): String = "ToastModule" @ReactMethod fun showToast(text: String?) { val toast = Toast.makeText(reactApplicationContext, text, Toast.LENGTH_LONG) toast.show() } } 1. 大幅にコード量を削減 2. 冗長性のあるコードを削減 3. 安全性のあるコードが書ける
ReactNativeとKotlinを用いた 音声収録・配信機能の実装 28
stand.fmは誰でもかんたんに アプリで収録・LIVE配信ができる音声 プラットフォーム 29
30 stand.fmを支える技術
31 stand.fmのコア機能はNativeModuleに支えられている 収録 (ソロ・コラボ) LIVE (ソロ・コラボ) ※AndroidのコラボLIVEは開発中
ReactNativeとKotlinを用いた 音声収録・配信機能の実装 〜音声の収録〜 32
音声の収録機能の全体イメージ 33 App 配信者 録音 PCM AAC エンコード 音声ファイル
(.m4a) ファイル出力
音声の録音機能の実装イメージ 34 システムの録音権限の要求 音声ファイルの準備 録音停止 録音開始 録音ファイルの出力
35 音声の録音機能の実装〜システムの録音権限の要求〜 1. android/app/src/AndroidManifest.xmlにRECORD_AUDIO権限を追加 <manifest ... package="com.rnmatsurisampleapp"> <uses-permission
android:name="android.permission.RECORD_AUDIO" /> </manifest> 2. ユーザーにパーミッションを明示的に要求 export const requestPermission = async (): Promise<boolean> => { const granted = await PermissionsAndroid.request( PermissionsAndroid.RECORD_AUDIO, { title: "録音の開始にはシステム権限の許可が必要です ", message: "音声の録音に使用します。許可しますか " } ) return granted === PermissionsAndroid.RESULTS.GRANTED } RECORD_AUDIO権限の追加 PermissionsAndroidモジュールでユーザーにマイク権限をリクエスト このような権限要求ダイアログが表示される
音声の録音機能の実装〜音声ファイルの準備〜 36 - RecorderModuleを定義 - startRecordingのReactMethodを定義する - 録音した音声の出力先ファイルを作成しておく
class RecorderModule(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) { private var recordingFilePath: String? = null @ReactMethod fun startRecording(promise: Promise) { val fileName = System.currentTimeMillis().toString() recordingFilePath = "${this.reactApplicationContext.filesDir.absolutePath}/${fileName}.m4a" } } アプリ内領域のストレージの絶対パスを取得
音声の録音機能の実装〜録音開始〜 37 - 音声の録音にはMediaRecorderというAndroidのAPIを使う - https://developer.android.com/guide/topics/media/mediarecorder?hl=ja - 録音に使用されるサンプリングレートや出力フォーマットなどの設定をする
- prepare()を呼んだあとstart()を呼ぶことで録音が開始される private var recorder: MediaRecorder? = null @ReactMethod fun startRecording(promise: Promise) { recorder = MediaRecorder().apply { setAudioSource(MediaRecorder.AudioSource.MIC) setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setOutputFile(recordingFilePath) setAudioEncoder(MediaRecorder.AudioEncoder.AAC) setAudioSamplingRate(44100) try { prepare() start() } catch (e: IOException) { promise.reject(e) } } promise.resolve(null) } ・入力ソース:マイク ・出力ファイルフォーマット:MP4(.m4a) ・エンコーダーの指定:AAC ・サンプリングレート:44.1kHz 録音の開始 以下の項目を設定
音声の録音機能の実装〜録音停止〜 38 - MediaRecorderのstop()とrelease()を実行し、録音を停止する - 録音したファイルパスをjs側に返す @ReactMethod fun stopRecording(promise:
Promise) { recorder?.apply { stop() release() } recorder = null recordingFilePath = null promise.resolve(recordingFilePath) } 録音された音声ファイルのパスを返す 録音を停止する
PromiseとAndroidのNativeModule 39 - Promiseの結果としてNativeModuleでの結果を返したい場合は、Promiseオブジェクトを ReactMethodの引数に渡す - resolveする場合はpromise.resolveを呼び、返り値を引数に渡す -
rejectする場合はpromise.rejectを呼ぶ - 引数にはErrorCode, Message, Throwableを渡すことができ、js側のreject時のオブジェクトにまとめ て渡される @ReactMethod fun startRecording(promise: Promise) { … try { promise.resolve(null) } catch (e: Exception) { promise.reject(e) } } try { const result = await RecorderModule.startRecording() } catch (err) { console.error(err) } Promiseの結果を渡す
音声の録音機能の実装〜js側の呼び出し〜 40 - 録音開始時と終了時にNativeModuleを呼び出すuseCallbackを定義 const onStartRecordingPressed = useCallback(async
() => { try { await RecorderModule.startRecording() } catch (err) { // エラー処理 } }, []) const onStopRecordingPressed = useCallback(async () => { try { const filePath = await RecorderModule.stopRecording() } catch (err) { // エラー処理 } }, []) 録音の開始 録音の停止
ReactNativeとKotlinを用いた 音声収録・配信機能の実装 〜音声の配信〜 41
音声の配信機能の全体イメージ 42 App (配信クライアント ) MediaServer RTMP 配信者 録音
PCM AAC エンコード App (受信クライアント ) CDN HLS
音声の配信機能の全体イメージ(今日話す部分) 43 App (配信クライアント ) MediaServer RTMP 配信者 録音
PCM AAC エンコード App (受信クライアント ) CDN HLS
44 RTMP(Real-Time Messaging Protocol)とは - Adobe社が開発したビデオや音声をリアルタイムに転送するためのストリーミングプロトコル - TCPベースのプロトコルで低遅延接続を維持できるように設計されている
- 対応音声コーデック: - AAC、AAC-LC、MP3、Speexなど - 関連フォーマット: - RTMPS (SSL経由で暗号化) - RTMFP (TCPの代わりにUDP経由でレイヤー化) - 2020年末のFlashサポート終了とともにサポートが終了しているが、メディアサーバーへの転送 プロトコルとしてはいまだ利用されているところが多い
音声の配信機能の実装イメージ 45 RTMPコネクションの開始 音声キャプチャとエンコーダの開始 キャプチャ音声のAACエンコーディング AAC音声をRTMPで逐次アップロード RTMPコネクションの停止 音声キャプチャとエンコーダの停止 ストリーミングの開始
ストリーミングの停止 ストリーミング中
RTMPストリーミング用クライアントライブラリの導入 - RTMPストリーミングにはrtmp-rtsp-stream-client-javaというネイティブ用ライブラリを使います - https://github.com/pedroSG94/rtmp-rtsp-stream-client-java - 音声のキャプチャ(録音)、エンコードも一括でやってくれる
- 導入にはapp/build.gradleにdependenciesを定義して、Sync Nowを押下 46 dependencies { ... implementation "com.github.pedroSG94.rtmp-rtsp-stream-client-java:rtplibrary:2.1.1" }
RTMPコネクションと録音の開始〜コネクション開始〜 47 class StreamingModule(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) { override
fun getName(): String = "StreamingModule" private var rtmpClient: RtmpOnlyAudio? = null @ReactMethod fun startStreaming(promise: Promise) { val rtmpUrl = "rtmp://exmaple.com:1935/rnmatsurisampleapp/abcdefg" rtmpClient = RtmpOnlyAudio(connectCheckerRtmp).apply { setAuthorization("username", "password") prepareAudio(64 * 1024, 44100, false) startStream(rtmpUrl) } } } - StreamingModuleというNativeModuleを定義 - startStreamingメソッドを実装 RTMPクライアントのインスタンス RTMPの認証パラメータのセット 音声関連の設定(bitrate, sampleRate, isStereo) マイク、エンコーダーの初期化をする RTMPコネクションの開始要求
RTMPコネクションと録音の開始〜RTMPイベントのコールバック設定〜 - RtmpOnlyAudioの初期化にはConnectCheckerRtmpというコールバック受け取り用のオブジェクトを 渡す必要がある 48 private val connectCheckerRtmp =
object: ConnectCheckerRtmp { override fun onConnectionFailedRtmp(reason: String) { // RTMPコネクションの接続が失敗した場合 } override fun onConnectionStartedRtmp(rtmpUrl: String) { // RTMPコネクションの接続が開始されたとき } override fun onConnectionSuccessRtmp() { // RTMPコネクションの接続が成功したとき } override fun onDisconnectRtmp() { // RTMPコネクションのSocketが切れたとき } ... }
RTMPコネクションと録音の停止 - stopStreamというメソッドを呼びストリーミング停止要求を行う - RTMPコネクション、録音、エンコーダの停止処理を同時にやってくれる 49 class
StreamingModule(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) { ... @ReactMethod fun stopStreaming() { rtmpClient?.stopStream() } }
50 ストリーミング開始の成功と失敗のハンドリング - startStreamとstopStreamは非同期で実行される - それらの結果を利用したい場合は、ConnectCheckerRtmpのコールバック結果を元にしてハンド リングをする fun
sendEvent(context: ReactApplicationContext, event: StreamingEvent) { val body = event.toBodyMap() context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit(event.name, body) } private val connectCheckerRtmp = object: ConnectCheckerRtmp { override fun onConnectionFailedRtmp(reason: String) { sendEvent(context, StreamingEvent.OnError(StreamingErrorCode.RTMP_CONNECTION_FAILED_OR_CLOSED)) } override fun onConnectionSuccessRtmp() { sendEvent(context, StreamingEvent.OnSuccessStream) } } KotlinのNativeEventEmitterの実装 RTMPコネクションの失敗イベントをemit RTMPコネクションの成功イベントをemit
51 SealedClassを用いたNativeEventEmiterへの応用 sealed class StreamingEvent(val name: String) { object
OnSuccessStream: StreamingEvent("onSuccessStream") class OnError(val code: StreamingErrorCode): StreamingEvent("onError") } SealedClassで 2つのイベント型を定義 fun sendEvent(context: ReactApplicationContext, event: StreamingEvent) { val body = event.toBodyMap() context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit(event.name, body) } sendEvent(context, StreamingEvent.OnError(StreamingErrorCode.RTMP_CONNECTION_FAILED_OR_CLOSED)) sendEvent(context, StreamingEvent.OnSuccessStream) イベントタイプごとにReadableMapを生成 する拡張関数 onErrorイベントの場合: { code: 1, message: “Failed to RTMP connection” } onSuccessStreamの場合: {}
52 音声の配信〜js側の呼び出し〜 import { NativeModules, NativeEventEmitter } from 'react-native'
const { StreamingModule } = NativeModules const eventEmitter = new NativeEventEmitter(StreamingModule) StreamingModule.startStreaming() StreamingModule.stopStreaming() const onSuccessListener = eventEmitter.addListener( 'onSuccessStream', (event) => { showToast('ストリーミングの開始に成功しました ') }) onSuccessListener.remove() const onErrorListener = eventEmitter.addListener( 'onError', (event) => { showToast('ストリーミングに失敗しました ') }) onErrorListener.remove() イベントハンドラの実装 (useEffectなどで定義) ストリーミングの開始と停止 (useCallbackなどで定義)
ReactNativeとKotlinを用いた 音声収録・配信機能の実装 〜コラボ機能(WebRTC)〜 53
54 WebRTCとは - 複数クライアント間でリアルタイムでの通信を提供する - Webブラウザ、モバイルアプリでの音声、ビデオ通話などに利用される - P2P通信を使ってリアルタイム通信を実現する
- 実際には通信に必要な相手のIPアドレスなどをやりとりするシグナリングサーバーが必要 - STUN, TURNなどの、NATやファイアウォールを超える仕組みも必要 - WebRTCの実装には専用のSDKやソフトウェアを提供しているサービスを利用することが多い - agora.io - Twillio - etc...
コラボ機能の全体イメージ(例: コラボ収録) 55 配信者 通話相手 PCM AAC エンコード 音声ファイル
(.m4a) ファイル出力 合成音声の取得
ReactNativeの 便利な音声ライブラリ 56
57 ここまでの正直な感想として - とは言ってもネイティブ書くの面倒じゃない?jsだけでなんとかならないの? - iOSも書かなきゃいけないじゃない? - さくっとプロトタイプで爆速で実装したい
そんなあなたには 便利なライブラリあります
58 ReactNativeの音声関連ライブラリ紹介 - 録音 - react-native-audio-toolkit https://github.com/react-native-audio-toolkit/react-native-audio-toolkit -
(archived) react-native-audio https://github.com/jsierles/react-native-audio - 配信(RTMP) - 見つかりませんでした(ありましたら教えて下さい) - 音声再生 - react-native-track-player https://github.com/DoubleSymmetry/react-native-track-player - react-native-sound https://github.com/zmxv/react-native-sound
まとめ 59
まとめ - ReactNativeでAndroidのNativeModuleを書くときはKotlinで 🐤 - ReactNativeでも音声録音・配信アプリは作れる - 音声を録音し、ファイルに保存するには MediaRecorder
を使う - 音声の配信には RTMP などのストリーミングプロトコルとライブラリを使う - ライブラリには、 rtmp-rtsp-stream-client-java が使える - コラボ機能には WebRTC を利用するが、agora.io などの開発プラットフォームを使うことが多い - 音声関連のReactNativeのライブラリはいくつかあるため、基本的な機能の実装にはこれらを使うと 良い - 実際の配信機能は、配信クライアントだけではなくサーバー側や受信クライアント側も適切に実 装する必要があるので広範な知識が必要 60
We are hiring! エンジニア積極的に募集中です https://corp.stand.fm/recruit 詳細はこちら • CTO候補 • VPoE候補
• クライアントエンジニア • バックエンドエンジニア • 機械学習エンジニア • 配信基盤エンジニア • QAエンジニア • エンジニアリングマネージャー • UI/UXデザイナー 積極募集しているプロダクト開発メンバー 61
62