recognizeSpeech static method

Future<String> recognizeSpeech(
  1. String audioFilePath
)

将语音文件转换为文字

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;
  }
}