Add fallback audio configurations for iOS

If primary audio config fails (OSStatus -50), automatically try:
1. videoChat mode (speaker default)
2. voiceChat mode (earpiece default)
3. minimal config (most compatible)

Also make speaker output setting non-critical - call will work
even if output can't be changed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Sergei 2026-01-22 09:43:05 -08:00
parent d9fff44fc9
commit e36b9bbf4a

View File

@ -50,32 +50,76 @@ export async function configureAudioForVoiceCall(): Promise<void> {
} }
if (Platform.OS === 'ios') { if (Platform.OS === 'ios') {
// iOS-specific configuration // iOS-specific configuration with fallback strategies
// IMPORTANT: Use 'videoChat' mode instead of 'voiceChat' to enable speaker by default // Try multiple configurations in order of preference
// voiceChat + defaultToSpeaker causes OSStatus error -50 on some iOS versions
console.log('[AudioSession] Step 1: Setting Apple audio config...');
await AudioSession.setAppleAudioConfiguration({
audioCategory: 'playAndRecord',
// Only use options that are safe with playAndRecord category
// Removed 'defaultToSpeaker' - it conflicts with some iOS versions
// Instead, using 'videoChat' mode which defaults to speaker
audioCategoryOptions: [
'allowBluetooth',
'mixWithOthers',
],
// Use 'videoChat' instead of 'voiceChat' - it enables speaker by default
audioMode: 'videoChat',
});
console.log('[AudioSession] Step 2: Starting audio session...'); const configs = [
// Strategy 1: videoChat mode (speaker by default, no problematic options)
{
name: 'videoChat',
config: {
audioCategory: 'playAndRecord',
audioCategoryOptions: ['allowBluetooth', 'mixWithOthers'],
audioMode: 'videoChat',
},
},
// Strategy 2: voiceChat mode (more compatible, but earpiece by default)
{
name: 'voiceChat',
config: {
audioCategory: 'playAndRecord',
audioCategoryOptions: ['allowBluetooth', 'mixWithOthers'],
audioMode: 'voiceChat',
},
},
// Strategy 3: Minimal config (most compatible)
{
name: 'minimal',
config: {
audioCategory: 'playAndRecord',
audioCategoryOptions: [],
audioMode: 'default',
},
},
];
let configSuccess = false;
let lastError: any = null;
for (const { name, config } of configs) {
try {
console.log(`[AudioSession] Trying ${name} configuration...`);
await AudioSession.setAppleAudioConfiguration(config);
console.log(`[AudioSession] ${name} configuration succeeded!`);
configSuccess = true;
break;
} catch (err) {
console.warn(`[AudioSession] ${name} config failed:`, err);
lastError = err;
// Continue to next strategy
}
}
if (!configSuccess) {
console.error('[AudioSession] All iOS configurations failed!');
throw lastError || new Error('All audio configurations failed');
}
console.log('[AudioSession] Starting audio session...');
await AudioSession.startAudioSession(); await AudioSession.startAudioSession();
console.log('[AudioSession] Step 3: Setting default output to speaker...'); // Try to set speaker output (non-critical, don't throw on failure)
await AudioSession.configureAudio({ try {
ios: { console.log('[AudioSession] Setting default output to speaker...');
defaultOutput: 'speaker', await AudioSession.configureAudio({
}, ios: {
}); defaultOutput: 'speaker',
},
});
} catch (outputErr) {
console.warn('[AudioSession] Could not set speaker output:', outputErr);
// Continue anyway - audio will work, just maybe on earpiece
}
} else if (Platform.OS === 'android') { } else if (Platform.OS === 'android') {
// Android-specific configuration // Android-specific configuration
// IMPORTANT: Using 'music' stream type to force output to speaker // IMPORTANT: Using 'music' stream type to force output to speaker