You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中获取指定格式语音输入并通过API传输的方法求助

Flutter语音录制转Base64并传递API的可行方案

核心思路

目标是录制语音后转成Base64编码字符串(即你示例中的格式),再通过API传递。推荐使用record包处理录音(稳定性优于你之前尝试的部分包),配合http发送请求,path_provider管理临时文件。

步骤实现

1. 添加依赖

在pubspec.yaml中加入以下依赖:

dependencies:
  flutter:
    sdk: flutter
  record: ^4.4.4  # 专业录音包,支持多平台
  http: ^1.1.0    # 处理API请求
  path_provider: ^2.1.1  # 获取临时文件路径

2. 配置权限

  • Android:在android/app/src/main/AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  • iOS:在ios/Runner/Info.plist中添加麦克风权限说明:
<key>NSMicrophoneUsageDescription</key>
<string>需要使用麦克风录制语音</string>

3. 完整代码示例

import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:record/record.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';

class VoiceToApiPage extends StatefulWidget {
  const VoiceToApiPage({super.key});

  @override
  State<VoiceToApiPage> createState() => _VoiceToApiPageState();
}

class _VoiceToApiPageState extends State<VoiceToApiPage> {
  final AudioRecorder _recorder = AudioRecorder();
  bool _isRecording = false;
  String? _audioFile;

  // 启动录音
  Future<void> startRecording() async {
    final hasPerm = await _recorder.hasPermission();
    if (!hasPerm) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('请开启麦克风权限')),
      );
      return;
    }
    await _recorder.start(
      const RecordConfig(encoder: AudioEncoder.wav), // 按需选编码(mp3/wav等)
      path: await _getTempPath(),
    );
    setState(() => _isRecording = true);
  }

  // 停止录音并处理数据
  Future<void> stopRecording() async {
    final path = await _recorder.stop();
    setState(() {
      _isRecording = false;
      _audioFile = path;
    });
    if (_audioFile != null) await sendToApi(_audioFile!);
  }

  // 获取临时音频文件路径
  Future<String> _getTempPath() async {
    final tempDir = await getTemporaryDirectory();
    return '${tempDir.path}/voice_recording.wav';
  }

  // 转Base64并发送API
  Future<void> sendToApi(String filePath) async {
    final bytes = await File(filePath).readAsBytes();
    final base64Str = base64Encode(bytes);
    
    try {
      final response = await http.post(
        Uri.parse('https://your-api-url.com/voice'),
        body: {'voice_data': base64Str}, // 按API要求传参
      );
      if (response.statusCode == 200) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('语音数据发送成功')),
        );
        // 可选:删除临时文件
        await File(filePath).delete();
      } else {
        throw Exception('请求失败,状态码:${response.statusCode}');
      }
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('发送失败:${e.toString()}')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('语音转API')),
      body: Center(
        child: ElevatedButton(
          onPressed: _isRecording ? stopRecording : startRecording,
          child: Text(_isRecording ? '停止录制' : '开始录制'),
        ),
      ),
    );
  }
}

关键注意事项

  • 确认API支持的音频编码格式,比如如果API要求mp3,就把AudioEncoder.wav改成AudioEncoder.aacLc(对应mp3)
  • 录制完成后可以删除临时文件,避免占用设备存储空间
  • 权限判断必须放在录音前,否则会直接录制失败
  • 如果API需要其他参数,直接在http.post的body中添加即可

内容的提问来源于stack exchange,提问作者Udit Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:55:03