-
Notifications
You must be signed in to change notification settings - Fork 0
Ai Conversation Translation
Build a two-person, turn-based translation experience by starting a short simultaneous-interpretation session for the active speaker and swapping source and target languages for the other participant.
This is a product workflow demonstrated by ConversationTranslationDemoController; it does not introduce a separate ConversationTranslationAPI.
One conversation turn
Each speaker turn owns one interpretation session. Reverse the language direction for the partner's turn and never run both turns concurrently.
- Choose Active Speaker — Resolve source and target languages from the selected side.
- Configure Turn — Create a simultaneous-interpretation configuration for this direction.
- Start Session — Start interpretation and retain the returned session.
- Provide Speech — Use AIBuds AI SDK internal recording, or feed external PCM from the host app or connected device.
- Render Translation — Order definite source and target segments from streaming callbacks.
- Finish Turn — Stop external recording first, then stop the interpretation service.
- Meet all prerequisites from Simultaneous Interpretation.
- Use different hyphenated source and target language identifiers.
- Track the active speaker, current session, start/stop state, and rendered turn messages in the host app.
- Prevent both speakers from starting sessions simultaneously.
Conversation Translation uses startSimultaneousInterpretation, stopSimultaneousInterpretation, and SimultaneousInterpretationConfig.
See Simultaneous Interpretation for the complete public declarations and callback contract.
The Demo maps “Me” to myLanguage → partnerLanguage and “Partner” to the reverse direction. The following helpers accept the resolved direction, making that product state explicit.
func startConversationTurn(source: String, target: String) {
guard currentSession == nil, source != target else { return }
let config = SimultaneousInterpretationConfig.default
config.sourceLanguage = source
config.targetLanguage = target
config.usesInternalAudioRecording = true
config.preferSpeakerOutput = true
config.enableVoicePlayback = true
AIBudsAISDK.startSimultaneousInterpretation(
config,
onStartSuccess: { session in
currentSession = session
setTurnActive(true)
},
onStartFailure: { error in
currentSession = nil
setTurnActive(false)
show(error)
},
onStopByInterruption: { error in
currentSession = nil
setTurnActive(false)
if let error { show(error) }
},
onException: { error in
showRecoverable(error)
},
streamResultHandler: { _, response, error in
if let error {
show(error)
return
}
guard let response else { return }
if response.isSourceTextDefinite { renderSource(response) }
if response.isTargetTextDefinite { renderTarget(response) }
},
onEvent: { event in
handle(event)
},
onFinish: { report in
currentSession = nil
setTurnActive(false)
save(report)
}
)
}- (void)startConversationTurnFrom:(NSString *)source to:(NSString *)target {
if (self.currentSession != nil || [source isEqualToString:target])
return;
AIBudsSimultaneousInterpretationConfig *config =
[AIBudsSimultaneousInterpretationConfig defaultConfig];
config.sourceLanguage = source;
config.targetLanguage = target;
config.usesInternalAudioRecording = YES;
config.preferSpeakerOutput = YES;
config.enableVoicePlayback = YES;
[AIBudsAISDK startSimultaneousInterpretationWithConfig:config
onStartSuccess:^(id<AIBudsSimultaneousInterpretationSessionConvertible> session) {
self.currentSession = session;
[self setTurnActive:YES];
}
onStartFailure:^(NSError *error) {
self.currentSession = nil;
[self setTurnActive:NO];
[self showError:error];
}
onStopByInterruption:^(NSError *error) {
self.currentSession = nil;
[self setTurnActive:NO];
if (error != nil)
[self showError:error];
}
onException:^(NSError *error) {
[self showRecoverableError:error];
}
streamResultHandler:^(
BOOL isFinal, AIBudsSimultaneousInterpretationDataModel *response, NSError *error) {
if (error != nil) {
[self showError:error];
return;
}
if (response.isSourceTextDefinite)
[self renderSource:response];
if (response.isTargetTextDefinite)
[self renderTarget:response];
}
onEvent:^(AIBudsSimultaneousInterpretationEventModel *event) {
[self handleEvent:event];
}
onFinish:^(AIBudsSimultaneousInterpretationReportModel *report) {
self.currentSession = nil;
[self setTurnActive:NO];
[self saveReport:report];
}];
}When currentSession.isRecordingInternally is false, stop device-side AI recording before stopping the service so the final audio is delivered in order.
func stopConversationTurn() {
guard let session = currentSession else { return }
if !session.isRecordingInternally,
let recordingDevice = device as? DeviceAudioRecordingAPI
{
recordingDevice.stopAIAudioRecording(.onSite) { _, _ in
AIBudsAISDK.stopSimultaneousInterpretation()
}
} else {
AIBudsAISDK.stopSimultaneousInterpretation()
}
}- (void)stopConversationTurn {
if (self.currentSession == nil)
return;
if (!self.currentSession.isRecordingInternally) {
id<AIBudsDeviceAudioRecordingAPI> recordingDevice =
(id<AIBudsDeviceAudioRecordingAPI>)self.device;
if ([recordingDevice conformsToProtocol:@protocol(AIBudsDeviceAudioRecordingAPI)]) {
[recordingDevice
stopAIAudioRecordingWithScene:AIBudsRecordingSceneOnSite
completion:^(__unused BOOL success, __unused NSError *error) {
[AIBudsAISDK stopSimultaneousInterpretation];
}];
return;
}
}
[AIBudsAISDK stopSimultaneousInterpretation];
}Handle startup failure, interruption, recoverable exception, stream error, device-recording failure, and final completion separately. If a stop is requested while device recording is still starting, defer the service stop until the device start callback has completed; the Demo tracks this race explicitly.
- A conversation can contain many turns, but only one interpretation session should be active at a time.
- Swap languages only while no turn is active.
- Use source and target sequence fields to order definite segments instead of blindly appending every callback.
- When external device recording is used, register the retained interpretation session with the application's PCM forwarding path before starting device audio so the first packet is not lost.
AIBuds SDK documentation · Full documentation · API Reference
- Introduction
- Getting Started
- Core Concepts
-
Core Features
- Basic Features
- Device Info
- Find Device
- Physical Operations
- Work Mode
- Work Status
- Wear Detection
- Volume Control
- Music Control
- TWS
- Equalizer
- ANC
- Audio
- Camera
- Remote Camera
- File Import
- Teleprompter
- Segment Navigation
- Live Streaming
- Device Applications
- OTA
- Camera OTA
- Service Auth
- AI Services
- Voice Assistant
- Logging
- Advanced Topics
- Releases
- Troubleshooting