recognizeSpeech static method
将语音文件转换为文字
Implementation
static Future<String> recognizeSpeech(String audioFilePath) async {
try {
print('🎤 开始语音识别: $audioFilePath');
final file = File(audioFilePath);
if (!await file.exists()) {
throw Exception('音频文件不存在');
}
// 检查文件大小(最大25MB)
final fileSize = await file.length();
if (fileSize > 25 * 1024 * 1024) {
throw Exception('音频文件过大,最大支持25MB');
}
print('📦 文件大小: ${(fileSize / 1024).toStringAsFixed(2)} KB');
// 创建multipart请求
final request = http.MultipartRequest(
'POST',
Uri.parse('$baseUrl$asrPath'),
);
// 添加音频文件
request.files.add(await http.MultipartFile.fromPath(
'file',
audioFilePath,
filename: 'audio.m4a',
));
// 添加智谱AI ASR参数
request.fields['model'] = 'glm-asr';
request.fields['temperature'] = '0.95';
print('📤 发送语音识别请求到: $baseUrl$asrPath');
print('📋 请求参数: model=glm-asr, temperature=0.95');
final streamedResponse = await request.send().timeout(
const Duration(seconds: 30),
onTimeout: () {
throw Exception('语音识别超时');
},
);
final response = await http.Response.fromStream(streamedResponse);
print('✅ 响应状态码: ${response.statusCode}');
if (response.statusCode == 200) {
print('📥 响应内容: ${response.body}');
final result = json.decode(utf8.decode(response.bodyBytes));
// 按照智谱AI ASR的响应格式解析:result.data.text
String? text;
if (result is Map<String, dynamic>) {
// 优先尝试 data.text 格式
if (result['data'] != null && result['data'] is Map<String, dynamic>) {
text = result['data']['text'] as String?;
}
// 兼容其他可能的格式
text ??= result['text'] as String?;
text ??= result['result'] as String?;
}
if (text == null || text.isEmpty) {
throw Exception('语音识别结果为空,响应: ${response.body}');
}
print('✅ 识别结果: $text');
return text;
} else {
print('❌ 响应状态码: ${response.statusCode}');
print('❌ 响应内容: ${response.body}');
try {
final errorData = json.decode(utf8.decode(response.bodyBytes));
final errorMsg = errorData['message'] ??
errorData['error'] ??
errorData['msg'] ??
'语音识别失败';
throw Exception(errorMsg);
} catch (e) {
if (e.toString().contains('语音识别失败')) {
rethrow;
}
// JSON解析失败,返回原始错误信息
final bodyPreview = response.body.length > 200
? '${response.body.substring(0, 200)}...'
: response.body;
throw Exception('语音识别失败 (${response.statusCode}): $bodyPreview');
}
}
} catch (e) {
print('❌ 语音识别失败: $e');
rethrow;
}
}