Overview
The createReactNativeWebRtcTransport function creates a WebRTC transport that connects to the OpenAI Realtime API using the react-native-webrtc library. It handles peer connection, data channels, audio streaming, and real-time event communication.
Usage
import { createReactNativeWebRtcTransport } from '@navai/voice-mobile' ;
import { mediaDevices , RTCPeerConnection } from 'react-native-webrtc' ;
const transport = createReactNativeWebRtcTransport ({
globals: {
mediaDevices ,
RTCPeerConnection
},
model: 'gpt-4o-realtime-preview' ,
remoteAudioTrackVolume: 10
});
// Connect to realtime API
await transport . connect ({
clientSecret: 'secret_abc123' ,
onEvent : ( event ) => console . log ( 'Realtime event:' , event ),
onError : ( error ) => console . error ( 'Transport error:' , error )
});
// Send events
await transport . sendEvent ({
type: 'session.update' ,
session: { instructions: 'You are a helpful assistant.' }
});
// Disconnect
await transport . disconnect ();
Options
globals
NavaiReactNativeWebRtcGlobals
required
React Native WebRTC globals required for WebRTC functionality. import { mediaDevices , RTCPeerConnection } from 'react-native-webrtc' ;
globals : {
mediaDevices ,
RTCPeerConnection
}
type NavaiReactNativeWebRtcGlobals = {
RTCPeerConnection : new ( ... args : any []) => NavaiPeerConnectionLike ;
mediaDevices : {
getUserMedia : ( ... args : any []) => Promise < NavaiMediaStreamLike >;
};
};
Default model to use for realtime connections. Defaults to gpt-realtime. Can be overridden per connection in connect() options. model : 'gpt-4o-realtime-preview'
OpenAI Realtime API endpoint URL. Defaults to https://api.openai.com/v1/realtime/calls. realtimeUrl : 'https://api.openai.com/v1/realtime/calls'
Volume multiplier for remote audio tracks (range: 0-10). Defaults to no adjustment. Note: Uses react-native-webrtc’s _setVolume API if available. remoteAudioTrackVolume : 10 // Maximum volume
Custom fetch implementation. Defaults to global fetch.
RTCConfiguration object for RTCPeerConnection. Use for custom ICE servers, etc. rtcConfiguration : {
iceServers : [{ urls: 'stun:stun.l.google.com:19302' }]
}
MediaStreamConstraints for getUserMedia. Defaults to { audio: true, video: false }. audioConstraints : {
audio : {
echoCancellation : true ,
noiseSuppression : true ,
autoGainControl : true
},
video : false
}
Return Value
Returns NavaiRealtimeTransport object:
connect
(options: NavaiRealtimeTransportConnectOptions) => Promise<void>
Connect to the OpenAI Realtime API. Client secret from backend. Obtain via backendClient.createClientSecret().
Model override for this connection.
Callback for real-time events from the API.
Callback for transport errors.
Throws error if connection fails.
Disconnect and clean up resources. Safe to call multiple times.
sendEvent
(event: unknown) => Promise<void>
Send a real-time event to the API. await transport . sendEvent ({
type: 'session.update' ,
session: { instructions: 'New instructions' }
});
Throws error if data channel is not open.
getState
() => NavaiRealtimeTransportState
Get current transport state. Returns: 'idle' | 'connecting' | 'connected' | 'error' | 'closed'
Examples
Basic Connection
import { createReactNativeWebRtcTransport } from '@navai/voice-mobile' ;
import { mediaDevices , RTCPeerConnection } from 'react-native-webrtc' ;
const transport = createReactNativeWebRtcTransport ({
globals: { mediaDevices , RTCPeerConnection }
});
await transport . connect ({
clientSecret: 'secret_abc123' ,
model: 'gpt-4o-realtime-preview' ,
onEvent : ( event ) => {
console . log ( 'Event:' , event . type );
},
onError : ( error ) => {
console . error ( 'Error:' , error );
}
});
console . log ( 'State:' , transport . getState ()); // 'connected'
With Voice Session
import {
createNavaiMobileVoiceSession ,
createReactNativeWebRtcTransport ,
createNavaiMobileBackendClient
} from '@navai/voice-mobile' ;
import { mediaDevices , RTCPeerConnection } from 'react-native-webrtc' ;
const transport = createReactNativeWebRtcTransport ({
globals: { mediaDevices , RTCPeerConnection },
model: 'gpt-4o-realtime-preview' ,
remoteAudioTrackVolume: 10
});
const backendClient = createNavaiMobileBackendClient ({
apiBaseUrl: 'https://api.myapp.com'
});
const session = createNavaiMobileVoiceSession ({
transport ,
backendClient ,
onRealtimeEvent : ( event ) => {
console . log ( 'Realtime event:' , event );
},
onRealtimeError : ( error ) => {
console . error ( 'Realtime error:' , error );
}
});
await session . start ();
Custom Audio Constraints
const transport = createReactNativeWebRtcTransport ({
globals: { mediaDevices , RTCPeerConnection },
audioConstraints: {
audio: {
echoCancellation: true ,
noiseSuppression: true ,
autoGainControl: true ,
sampleRate: 48000
},
video: false
}
});
Custom RTC Configuration
const transport = createReactNativeWebRtcTransport ({
globals: { mediaDevices , RTCPeerConnection },
rtcConfiguration: {
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'stun:stun1.l.google.com:19302' }
],
iceCandidatePoolSize: 10
}
});
Sending Events
// Update session configuration
await transport . sendEvent ({
type: 'session.update' ,
session: {
type: 'realtime' ,
instructions: 'You are a helpful fitness coach.' ,
tools: [ ... ],
tool_choice: 'auto'
}
});
// Create conversation item
await transport . sendEvent ({
type: 'conversation.item.create' ,
item: {
type: 'message' ,
role: 'user' ,
content: [{ type: 'text' , text: 'Hello!' }]
}
});
// Trigger response
await transport . sendEvent ({
type: 'response.create'
});
State Management
const transport = createReactNativeWebRtcTransport ({ globals });
console . log ( transport . getState ()); // 'idle'
await transport . connect ({ clientSecret: 'secret' });
console . log ( transport . getState ()); // 'connected'
await transport . disconnect ();
console . log ( transport . getState ()); // 'closed'
Error Handling
const transport = createReactNativeWebRtcTransport ({ globals });
try {
await transport . connect ({
clientSecret: 'invalid_secret' ,
onEvent : ( event ) => console . log ( event ),
onError : ( error ) => {
console . error ( 'Transport error:' , error );
}
});
} catch ( error ) {
console . error ( 'Connection failed:' , error . message );
console . log ( 'State:' , transport . getState ()); // 'error'
}
Connection Lifecycle
Idle : Initial state, no connection
Connecting : WebRTC negotiation in progress
Create peer connection
Request microphone access
Create and configure data channel
Get local audio tracks
Create WebRTC offer
Send offer to OpenAI Realtime API
Receive answer and set remote description
Wait for data channel to open
Connected : Ready to send/receive events
Error : Connection failed or error occurred
Closed : Disconnected and cleaned up
Remote Audio Volume
The remoteAudioTrackVolume option uses react-native-webrtc’s _setVolume API to adjust the volume of remote audio tracks:
const transport = createReactNativeWebRtcTransport ({
globals: { mediaDevices , RTCPeerConnection },
remoteAudioTrackVolume: 10 // Maximum volume (range: 0-10)
});
Volume is applied:
When remote tracks are received (via ontrack event)
After remote description is set (via getReceivers)
Note: This feature requires react-native-webrtc’s private _setVolume API. If unavailable, volume adjustment is silently skipped.
Timeouts
Connection timeout : 12 seconds (CONNECT_DATA_CHANNEL_TIMEOUT_MS)
Send event timeout : 6 seconds (SEND_EVENT_DATA_CHANNEL_TIMEOUT_MS)
If the data channel doesn’t open within the timeout, an error is thrown.