Вот поведение, которое я наблюдаю:
Когда я ухожу на странице я вызываю метод Dispose() в своем классе ConversationHandler.
После возвращения на страницу и начала первого диалога я получаю следующую ошибку:
Код: Выделить всё
🆘 Error playing audio: Connection aborted
I/flutter (17214): 🎙️ Switching to listening mode
I/flutter (17214): 🆘 Error playing audio: Connection aborted
I/flutter (17214): 🎙️ Switching to listening mode
I/flutter (17214): 🆘 Error playing audio: Connection aborted
I/flutter (17214): 🎙️ Switching to listening mode
Однако при последующих попытках приложение зависает в состоянии «Прослушивание» и не работает.< /p>
При последующих попытках приложение зависает в состоянии «Прослушивание». Я наблюдаю следующие журналы:
Код: Выделить всё
🎵 Sending audio chunk of size: 2560
I/flutter (17214): 🎵 Sending audio chunk of size: 2560
I/flutter (17214): 🎵 Sending audio chunk of size: 2560
I/flutter (17214): 🔄 Raw message from Deepgram: {"type":"Results","channel_index":[0,1],"duration":3.02,"start":0.0,"is_final":true,"speech_final":false,"channel":{"alternatives":[{"transcript":"","confidence":0.0,"words":[]}]},"metadata":{"request_id":"03448721-acf0-4eac-a1c7-d1fcc67f97ba","model_info":{"name":"general","version":"2024-01-26.8851","arch":"base"},"model_uuid":"1ed36bac-f71c-4f3f-a31f-02fd6525c489"},"from_finalize":false}
I/flutter (17214): 🔄 Decoded response: {type: Results, channel_index: [0, 1], duration: 3.02, start: 0.0, is_final: true, speech_final: false, channel: {alternatives: [{transcript: , confidence: 0.0, words: []}]}, metadata: {request_id: 03448721-acf0-4eac-a1c7-d1fcc67f97ba, model_info: {name: general, version: 2024-01-26.8851, arch: base}, model_uuid: 1ed36bac-f71c-4f3f-a31f-02fd6525c489}, from_finalize: false}
Код: Выделить всё
🎵 Sending audio chunk of size: 2560
I/flutter (17214): 🎵 Sending audio chunk of size: 2560
I/flutter (17214): 🏁 Deepgram WebSocket connection closed
I/flutter (17214): 🎵 Sending audio chunk of size: 2560
Я использую пакет just_audio для аудио воспроизведение. Вот соответствующие части моего класса ConversationHandler:
Код: Выделить всё
class ConversationHandler {
// ... (other properties)
late AudioRecorder _recorder;
late IOWebSocketChannel _deepgramChannel;
late IO.Socket _conversationSocket;
late IO.Socket _audioSocket;
late AudioPlayer _audioPlayer;
ConversationState _state = ConversationState.idle;
String _currentTranscript = '';
late Stream _audioStream;
StreamSubscription? _audioStreamSubscription;
bool _isInitialized = false;
// ... (constructor and other methods)
Future startConversation() async {
if (!_isInitialized) {
print('❗ ConversationHandler not initialized');
_updateStatus("Oops! Something went wrong. Please try again.");
return;
}
if (_state != ConversationState.idle) {
print('❗ Cannot start conversation: not in idle state');
return;
}
_updateStatus("Listening...");
await _switchToListeningMode();
}
Future _switchToListeningMode() async {
print('🎙️ Switching to listening mode');
_state = ConversationState.listening;
try {
bool hasPermission = await _recorder.hasPermission();
if (!hasPermission) {
print('❌ Microphone permission not granted');
_updateStatus("Microphone access needed. Please grant permission.");
return;
}
_audioStream = await _recorder.startStream(const RecordConfig(
encoder: AudioEncoder.pcm16bits,
numChannels: 1,
sampleRate: 16000,
));
print('🎙️ Audio stream started');
_initializeDeepgram();
_audioStreamSubscription = _audioStream.listen(
(Uint8List audioChunk) {
if (_state == ConversationState.listening) {
if (audioChunk.isNotEmpty) {
print('🎵 Sending audio chunk of size: ${audioChunk.length}');
_deepgramChannel.sink.add(audioChunk);
_lastAudioDetected = DateTime.now();
} else {
print('❗ Audio chunk is empty');
}
}
},
onError: (error) {
print('🆘 Error in audio stream: $error');
_updateStatus("Oops! Something went wrong. Please try again.");
},
);
} catch (e) {
print('🆘 Error starting audio stream: $e');
_updateStatus("Oops! Something went wrong. Please try again.");
}
}
void _initializeDeepgram() {
final deepgramUrl = 'wss://api.deepgram.com/v1/listen?encoding=linear16&sample_rate=16000&channels=1&endpointing=500';
try {
_deepgramChannel = IOWebSocketChannel.connect(
Uri.parse(deepgramUrl),
headers: {
'Authorization': 'Token $deepgramApiKey',
},
);
print('🌐 Deepgram WebSocket connected');
} catch (e) {
print('🆘 Error connecting to Deepgram WebSocket: $e');
_updateStatus("Oops! Something went wrong. Please try again.");
return;
}
_deepgramChannel.stream.listen(
(message) {
try {
final response = jsonDecode(message);
print('🔄 Raw message from Deepgram: $message');
print('🔄 Decoded response: $response');
if (response['type'] == 'Results' &&
response['channel'] != null &&
response['channel']['alternatives'] != null &&
response['channel']['alternatives'].isNotEmpty) {
final isFinal = response['is_final'] ?? false;
final transcript = response['channel']['alternatives'][0]['transcript'] as String? ?? '';
if (isFinal && transcript.isNotEmpty) {
_currentTranscript += ' ' + transcript;
print('📝 Current transcript: $_currentTranscript');
if (response['speech_final'] == true) {
_handlePause();
}
}
}
} catch (e) {
print('🆘 Error processing Deepgram response: $e');
_updateStatus("Oops! Something went wrong. Please try again.");
}
},
onError: (error) {
print('🆘 Deepgram WebSocket error: $error');
_updateStatus("Oops! Something went wrong. Please try again.");
},
onDone: () {
print('🏁 Deepgram WebSocket connection closed');
},
);
}
Future _playAudio(Uint8List audioBuffer) async {
print('Playing audiooo');
try {
final tempDir = await getTemporaryDirectory();
print('tempr gotten');
final tempFile = File('${tempDir.path}/temp_audio.mp3');
await tempFile.writeAsBytes(audioBuffer);
print('gotten temp fileeee');
await _audioPlayer.setFilePath(tempFile.path);
await _audioPlayer.play();
await _audioPlayer.playerStateStream.firstWhere(
(state) => state.processingState == ProcessingState.completed
);
print('🔊 Audio playback completed');
} catch (e) {
print('🆘 Error playing audio: $e');
_updateStatus("Oops! Something went wrong. Please try again.");
}
}
Future stopConversation() async {
print('🛑 Stopping conversation');
_state = ConversationState.idle;
_audioStreamSubscription?.cancel();
await _recorder.stop();
_deepgramChannel.sink.close();
await _audioPlayer.stop();
_updateStatus("Conversation ended.");
}
Future dispose() async {
print('♻️ Disposing ConversationHandler');
await stopConversation();
await _conversationSocket.disconnect();
await _audioSocket.disconnect();
await _audioPlayer.dispose();
}
}
Что может быть причиной ошибки «Соединение прервано» при попытке воспроизвести аудио после навигации по странице?
Почему? кажется, что приложение зависает в состоянии «Прослушивание» при последующих попытках разговора, при этом от Deepgram приходят пустые расшифровки?
Как правильно повторно инициализировать или сбросить аудиоплеер, устройство записи и обработчик разговора при возвращении в страницу, чтобы обеспечить согласованное поведение?
Почему соединение Deepgram WebSocket неожиданно закрывается и как я могу гарантировать, что оно останется открытым или правильно инициализировать его после закрытия?
Любые идеи или предложения был бы очень признателен. Заранее благодарю за помощь!
Подробнее здесь: https://stackoverflow.com/questions/790 ... igation-su
Мобильная версия