Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RN (等)でRealtime Voice AIプロダクトを作る @React Native ...

RN (等)でRealtime Voice AIプロダクトを作る @React Native Meetup #21

Avatar for DAIKI ARAI

DAIKI ARAI

April 16, 2025
Tweet

More Decks by DAIKI ARAI

Other Decks in Programming

Transcript

  1. RN ( 等) でRealtime RN ( 等) でRealtime Voice AI

    プロダクトを作る Voice AI プロダクトを作る darai: Kotoba Technologies darai: Kotoba Technologies @React Native Meetup #21 @React Native Meetup #21 1
  2. 2

  3. 要件 要件 プロダクト化はマルチプラットフォームで! 1,2 人開発(infra ~ UI まで開発) なのでJS 統一で言語のコンテキ

    ストスイッチを下げたい Audio Streaming はnative をいじりたくてbare 選択 Web でのDemo でSafari やWebView に課題( 後述) => native を触るつもりで開発開始 1. Next.js でWeb のDemo 2. (bare) ReactNative (v76) でiOS & Web Product Web はReactNative Web + vite 3. tauri でMac & Windows Product ReactNative Windows & Mac は? 4
  4. Tauri (v2) も使い始めた Tauri (v2) も使い始めた 要件: システムオーディオ取りたい 要件: システムオーディオ取りたい

    BlackHole/VB-Cable 無しで音声キャプチャしたい MacBook: Web Audio API/MediaDevices API のデバイスとは別 Electron では cf, iOS AUE/Android AudioPlaybackCapture は要コラボ JS& エコシステム強さで比較 fork star latest commit 2.8k 91.4k 5h 1.2k 16.7k 2days 146 3.8k 3days Audio Tap API サポート外Windows に限りMediaDevices API で取得可能 Tauri RN win RN mac 5 . 1
  5. Appendix. Expo いいなぁ Appendix. Expo いいなぁ OTA アップデート : サービス終了、OSS

    化 個人: / : いずれも 40 fork/500 star, New architecture 対応 いけてるサービスのSDK がExpo しか対応してない ex, bare RN から使うには独自Provider + @clerk/clerk-react RN はiOS/Web 間でも意外とコード共通化できない... ex, Alert 拡張子でimport module が変わるのは素晴らしいけれど MicroSoft Code push react-native-ota-hot-update hot-updater @clerk/clerk-expo 6
  6. Web/ 電話回線の Realtime 通信比較 Web/ 電話回線の Realtime 通信比較 API 遅延

    Protocol 説明 WebRTC ~0.1s RTP 他 準備大変,Client 最有 力, がくる! WebSocket ~0.1s HTTP1 簡単、Client/Server/ 電 話、mqtt も話せる gRPC ? HTTP2 Web の実装待ち? RTMP 5s TCP HLS 10s HTTP1/2 HTTP chunked encoding ? HTTP1 OpenAI Streaming API などで使われる opus1.5 8
  7. Voice AI 界隈のRealtime API Voice AI 界隈のRealtime API OpenAI Realtime

    API WebSocket or WebRTC input format pcm16, g711_ulaw or g711_alaw 24kHz ( ※) baidu WebSocket input format pcm16 16kHz Kotoba Tech 近日WebSocket 版をリリース予定 ※ 16-bit PCM at a 24kHz sample rate, 1 channel, and little- ※ 16-bit PCM at a 24kHz sample rate, 1 channel, and little- endian byte order endian byte order 9
  8. PCM? SamplingRate? PCM? SamplingRate? PCM (パルス符号変調): 連続値である音を、秒間X 回振幅値 を記録してプロット 横軸時間,

    縦軸音の振幅= 強さ 振幅: 16bit = 2byte = -32768~32768 で音の強度を表す SamplingRate: 秒間X 回のX [Hz] Rate が高い= 標本点が多い= 再現度 pcm16 は1 数値2byte の生音Format pcm16 は1 数値2byte の生音Format audio/wav: pcm にヘッダをつけただけ 1chunk 目のみヘッダが含まれる= ロスト制御辛い 圧縮例, audio/ogg;codec=opus ogg 形式かつopus で圧縮 10 . 1
  9. Chunk サイズ計算式 Chunk サイズ計算式 cf, Safari/iOS WebView だと2ch48kHz 固定 =>

    6 倍多くなる cf, Safari/iOS WebView だと2ch48kHz 固定 => 6 倍多くなる cf, cf, だとユーザーの 25% は 250kbps 未満, 50% は だとユーザーの 25% は 250kbps 未満, 50% は 400kbps 未満, 95% は 450kbps 未満 400kbps 未満, 95% は 450kbps 未満 import {...} from "@dr.pogodin/react-native-audio"; const stream = new InputAudioStream( AUDIO_SOURCES.MIC, 16000, // Sample rate in Hz. CHANNEL_CONFIGS.MONO, // 1 channel cf, chromeは2ch AUDIO_FORMATS.PCM_16BIT, // pcm16 3200, // Sampling size. false // stopInBackground ) stream.addChunkListener((chunk, chunkId) => { webSocketRef.current.send(new Int16Array(chunk.buffer)); }) // => 3200/16000=0.2s おきに 3200*2byte*1=6.4kb => 32kbps stream.start() Meta 調べ Meta 調べ 11
  10. スケールする実装のために スケールする実装のために chunk size とネットワーク帯域 GPU 確保が難しくBE Region が日本とは限らない ex,

    Tokyo or Canada. レイテンシに影響= 流量にも 流量制御 のback-pressure, HighWaterMark HTTP ならleaky bucket アルゴリズムなど WebRTC 流量制御の話 by NTT Comm @sublimer さん Node.js Core API: Stream 12
  11. 14

  12. 15