Flutter中如何实现ChatGPT流式音频回答?
Flutter实现ChatGPT流式音频回答方案
OpenAI API支持情况
目前OpenAI没有提供直接将ChatGPT流式回答实时转为音频的原生API。官方的Text to Speech(TTS)API仅支持传入完整文本生成音频,无法对接ChatGPT的流式文本输出。
实现流式音频回答的具体方案
要实现类似官方ChatGPT的流式音频效果,需要结合ChatGPT流式文本接口和本地TTS工具,分三步处理:
1. 调用ChatGPT流式接口获取逐段文本
使用OpenAI的Chat Completions API时,设置stream: true参数,接口会以SSE(Server-Sent Events)的形式逐块返回回答内容。每一块数据包含部分生成的文本,无需等待完整回答生成。
在Flutter中,可以通过http包处理流式响应,实时解析每一块返回的文本片段。
2. 优化文本分块,避免音频断句混乱
直接将每个小文本块单独转音频会导致播放时频繁断句,影响体验。需要做以下处理:
- 维护一个文本缓存,将流式返回的片段逐步拼接
- 按语义分割点(句号、感叹号、换行符等)分割缓存文本,积累到完整的短语或句子后,再送入TTS工具
3. 音频播放的无缝衔接
使用flutter_tts包的播放状态监听功能,当前一段音频播放完成后,自动处理队列中的下一段文本。也可以提前预加载下一段音频,减少播放间隙。
简化代码示例
import 'dart:convert'; import 'dart:async'; import 'package:http/http.dart' as http; import 'package:flutter_tts/flutter_tts.dart'; import 'dart:collection'; Future<void> streamChatAndSpeak(String userPrompt) async { final apiKey = 'YOUR_OPENAI_API_KEY'; final flutterTts = FlutterTts(); final audioQueue = Queue<String>(); String textBuffer = ''; bool isPlaying = false; // 发起流式ChatGPT请求 final request = http.Request('POST', Uri.parse('https://api.openai.com/v1/chat/completions')) ..headers['Authorization'] = 'Bearer $apiKey' ..headers['Content-Type'] = 'application/json' ..body = jsonEncode({ 'model': 'gpt-3.5-turbo', 'messages': [{'role': 'user', 'content': userPrompt}], 'stream': true, }); final response = await request.send(); final stream = response.stream.transform(utf8.decoder); // 监听流式返回的文本块 await for (final chunk in stream) { final lines = chunk.split('\n').where((line) => line.startsWith('data: ') && line != 'data: [DONE]'); for (final line in lines) { final data = jsonDecode(line.substring(6)); final content = data['choices'][0]['delta']['content'] ?? ''; textBuffer += content; // 按句号/换行分割,积累完整语义单元 if (textBuffer.contains('.') || textBuffer.contains('\n')) { final parts = textBuffer.split(RegExp(r'(?<=\.)|(?<=\n)')); for (final part in parts) { if (part.trim().isNotEmpty) { audioQueue.add(part.trim()); } } textBuffer = parts.last.trim(); } // 启动播放队列 if (!isPlaying && audioQueue.isNotEmpty) { isPlaying = true; _playQueue(flutterTts, audioQueue, () => isPlaying = false); } } } // 处理剩余的文本缓存 if (textBuffer.trim().isNotEmpty) { audioQueue.add(textBuffer.trim()); if (!isPlaying) { _playQueue(flutterTts, audioQueue, () => isPlaying = false); } } } Future<void> _playQueue(FlutterTts tts, Queue<String> queue, VoidCallback onQueueEmpty) async { if (queue.isEmpty) { onQueueEmpty(); return; } final text = queue.removeFirst(); await tts.speak(text); tts.setCompletionHandler(() => _playQueue(tts, queue, onQueueEmpty)); }
内容的提问来源于stack exchange,提问作者Hyejung
相关产品推荐
相关产品推荐

