[update] use aliyun andriod sdk

This commit is contained in:
2025-08-15 09:37:53 +08:00
parent 24a3a6bd62
commit 1302cd34a9
4 changed files with 93 additions and 66 deletions

View File

@@ -3,6 +3,7 @@ import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:ai_chat_assistant/utils/tts_util.dart';
import 'package:flutter/services.dart';
import '../utils/common_util.dart';
@@ -16,15 +17,20 @@ class ChatSseService {
HttpClient? _currentClient;
HttpClientResponse? _currentResponse;
bool _isAborted = true;
bool isTtsStarted = false;
bool _isFirstData = true;
bool _isTtsStarted = false;
String? get conversationId => _cachedConversationId;
Future<void>? _startTtsFuture;
void request({
required String messageId,
required String text,
required Function(String, String, String, bool) onStreamResponse,
required bool isChinese,
required Function(String, String, bool) onStreamResponse,
}) async {
print("----------------------SSE Start");
_isAborted = false;
if (_cachedUserId == null) {
_cachedUserId = _generateRandomUserId(6);
@@ -48,25 +54,17 @@ class ChatSseService {
request.add(utf8.encode(json.encode(body)));
_currentResponse = await request.close();
if (_currentResponse!.statusCode == 200) {
bool isFirst = true;
_startTtsFuture = startTts(isChinese);
await for (final line in _currentResponse!
.transform(utf8.decoder)
.transform(const LineSplitter())) {
if (_isAborted) {
break;
}
if (isFirst) {
if (!isTtsStarted) {
if (await _channel.invokeMethod<bool>("startTts") == true) {
isTtsStarted = true;
}
}
isFirst = false;
}
if (line.startsWith('data:')) {
final jsonStr = line.substring(5).trim();
if (jsonStr == '[DONE]' || jsonStr.contains('message_end')) {
onStreamResponse(messageId, responseText, tempText, true);
onStreamResponse(messageId, responseText, true);
break;
}
try {
@@ -81,13 +79,21 @@ class ChatSseService {
if (_isAborted) {
break;
}
_channel.invokeMethod("sendTts", {"text": CommonUtil.cleanText(textChunk, true)});
tempText += textChunk;
int endIndex = _getCompleteTextEndIndex(tempText);
String completeText = CommonUtil.cleanText(tempText.substring(0, endIndex).trim(), true);
if (completeText.isNotEmpty) {
if (_isFirstData && _startTtsFuture != null) {
await _startTtsFuture;
_isFirstData = false;
}
print("----------------------Send text: " + completeText);
completeText += isChinese ? '' : ',';
TtsUtil.send(completeText);
}
tempText = tempText.substring(endIndex).trim();
responseText += textChunk;
// tempText += textChunk;
// int endIndex = _getCompleteTextEndIndex(tempText);
// final completeText = tempText.substring(0, endIndex).trim();
// tempText = tempText.substring(endIndex).trim();
onStreamResponse(messageId, responseText, "completeText", false);
onStreamResponse(messageId, responseText, false);
}
} catch (e) {
print('解析 SSE 数据出错: $e, 原始数据: $jsonStr');
@@ -100,15 +106,22 @@ class ChatSseService {
} catch (e) {
// todo
} finally {
isTtsStarted = false;
resetRequest();
}
}
Future<void> startTts(bool isChinese) async {
print("----------------------TTS Start");
if (!_isTtsStarted) {
if (await TtsUtil.start(isChinese) == true) {
_isTtsStarted = true;
}
}
}
Future<void> abort() async {
_isAborted = true;
_channel.invokeMethod("stopTts");
isTtsStarted = false;
TtsUtil.stopTts();
resetRequest();
}
@@ -119,11 +132,13 @@ class ChatSseService {
_currentClient?.close(force: true);
_currentClient = null;
_currentResponse = null;
_isFirstData = true;
_isTtsStarted = false;
}
int _getCompleteTextEndIndex(String buffer) {
// 支持句号、问号、感叹号和换行符作为分割依据
final sentenceEnders = RegExp(r'[。!?\n]');
final sentenceEnders = RegExp(r'[,!?:。!?\n]');
final matches = sentenceEnders.allMatches(buffer);
return matches.isEmpty ? 0 : matches.last.end;
}