Диалоговый перевод
Реализуйте поочерёдный перевод для двух собеседников: запускайте короткую сессию синхронного перевода для активного говорящего и меняйте местами исходный и целевой языки для второй стороны.
Это сценарий продукта, показанный в ConversationTranslationDemoController; отдельного ConversationTranslationAPI он не добавляет.
Одна реплика диалога
Каждой реплике соответствует одна сессия перевода. Для ответа собеседника поменяйте направление языков и не запускайте обе стороны одновременно.
Предварительные условия
- Выполните все условия из раздела «Синхронный перевод».
- Используйте разные идентификаторы исходного и целевого языков в формате с дефисом.
- Храните в приложении активного говорящего, текущую сессию, состояние запуска/остановки и показанные реплики.
- Не допускайте одновременного запуска сессий обеими сторонами.
Реализация с помощью AI
Реализуйте этот сценарий с AI
Используйте официальный навык «Реализация перевода диалогов AIBuds» и адаптируйте сценарий к приложению.
Прочитайте и выполните инструкции https://docs-aibuds.github.io/ru/skills/implement-aibuds-conversation-translation. Используйте этот навык, чтобы реализовать «Реализация перевода диалогов AIBuds» в данном iOS-проекте и проверить результат.API Reference
Диалоговый перевод использует startSimultaneousInterpretation, stopSimultaneousInterpretation и SimultaneousInterpretationConfig.
Полные публичные объявления и контракт callbacks приведены в разделе «Синхронный перевод».
Примеры использования
Начало реплики
Demo сопоставляет «Я» направлению myLanguage → partnerLanguage, а «Собеседник» — обратному. Следующие вспомогательные методы принимают уже определённое направление, явно отражая состояние продукта.
- Swift
- Objective-C
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];
}];
}Остановка активной реплики
Когда currentSession.isRecordingInternally равно false, сначала остановите AI-запись на устройстве, а затем сервис, чтобы последний фрагмент аудио был доставлен в правильном порядке.
- Swift
- Objective-C
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];
}Обработка ошибок
Отдельно обрабатывайте ошибку запуска, прерывание, восстанавливаемое исключение, ошибку потока, сбой записи устройства и окончательное завершение. Если остановка запрошена во время запуска записи, отложите остановку сервиса до callback запуска устройства; Demo явно учитывает эту гонку.
Примечания
- Диалог может содержать много реплик, но одновременно должна быть активна только одна сессия перевода.
- Меняйте языки местами только при отсутствии активной реплики.
- Упорядочивайте подтверждённые сегменты по полям последовательности исходного и целевого текста, а не добавляйте безусловно каждый callback.
- При внешней записи на устройстве зарегистрируйте сохранённую сессию перевода в канале передачи PCM приложения до запуска аудио устройства, чтобы не потерять первый пакет.