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

在Flutter应用(Dart)中无需调用Swift/Java实现MP3/Wav文件拼接

解决方案:纯Flutter实现音频拼接/暂停续录

当然可以!完全不用碰Swift/Java代码,也不用折腾FFmpeg,咱们用纯Flutter的Dart包就能完美解决你的需求——不管是录音时暂停后继续生成单个文件,还是事后拼接多个音频片段,都能搞定。

一、最省心:录音时直接支持暂停&续录(无需事后拼接)

如果你要的是暂停录音后继续,最终生成单个文件,其实不用先录多个片段再拼接——直接用支持暂停续录的Flutter录音包就行,一步到位。推荐用flutter_sound,它是个成熟的音频处理库,支持WAV和MP3格式,纯Dart调用,完全不用碰原生代码。

步骤1:添加依赖

在pubspec.yaml里加上:

dependencies:
  flutter_sound: ^9.2.13

步骤2:实现暂停续录功能

这里给你一个简化的服务类示例,直接用就行:

import 'package:flutter_sound/flutter_sound.dart';
import 'package:path_provider/path_provider.dart';

class AudioRecorder {
  FlutterSoundRecorder? _recorder;
  String? _finalFilePath;

  // 初始化录音器
  Future<void> init() async {
    _recorder = FlutterSoundRecorder();
    await _recorder!.openRecorder();
    // 库会自动处理录音权限请求
  }

  // 开始录音
  Future<void> start() async {
    final docDir = await getApplicationDocumentsDirectory();
    _finalFilePath = '${docDir.path}/my_recording.wav'; // 换成.mp3就是MP3格式
    await _recorder!.startRecorder(
      toFile: _finalFilePath,
      codec: Codec.pcm16WAV, // WAV用这个,MP3用Codec.mp3
    );
  }

  // 暂停录音
  Future<void> pause() async {
    if (_recorder!.isRecording) {
      await _recorder!.pauseRecorder();
    }
  }

  // 恢复录音
  Future<void> resume() async {
    if (_recorder!.isPaused) {
      await _recorder!.resumeRecorder();
    }
  }

  // 停止录音,得到最终单个文件
  Future<String?> stop() async {
    await _recorder!.stopRecorder();
    print('录音完成,文件路径:$_finalFilePath');
    return _finalFilePath;
  }

  // 释放资源
  Future<void> dispose() async {
    await _recorder!.closeRecorder();
    _recorder = null;
  }
}

二、如果需要拼接已有音频文件

如果你已经有多个独立的WAV/MP3文件要合并,也有纯Flutter的方案:

1. WAV文件拼接(简单高效)

WAV是无压缩的音频格式,结构简单,只要确保所有文件的采样率、位深、声道数一致,就能直接合并音频数据。推荐用dart_wav包来处理:

依赖:

dependencies:
  dart_wav: ^1.0.0

拼接代码:

import 'package:dart_wav/dart_wav.dart';
import 'dart:io';

Future<void> mergeWavFiles(List<String> inputFilePaths, String outputPath) async {
  // 读取所有WAV文件
  List<Wav> wavList = [];
  for (var path in inputFilePaths) {
    final bytes = await File(path).readAsBytes();
    wavList.add(Wav.fromBytes(bytes));
  }

  // 校验所有文件参数一致(必须,否则拼接后音频会异常)
  final template = wavList.first;
  for (var wav in wavList) {
    if (wav.sampleRate != template.sampleRate ||
        wav.bitDepth != template.bitDepth ||
        wav.channels != template.channels) {
      throw Exception('所有WAV文件的采样率、位深、声道数必须完全一致');
    }
  }

  // 合并音频数据
  List<int> mergedData = [];
  for (var wav in wavList) {
    mergedData.addAll(wav.data);
  }

  // 生成新的WAV文件
  final mergedWav = Wav(
    sampleRate: template.sampleRate,
    bitDepth: template.bitDepth,
    channels: template.channels,
    data: mergedData,
  );

  // 写入输出文件
  await File(outputPath).writeAsBytes(mergedWav.toBytes());
  print('WAV文件拼接完成:$outputPath');
}

2. MP3文件拼接(压缩格式专用)

MP3是压缩格式,不能直接拼接字节,需要专门处理MP3帧。可以用mp3_joiner这个纯Flutter包:

依赖:

dependencies:
  mp3_joiner: ^0.0.1

拼接代码:

import 'package:mp3_joiner/mp3_joiner.dart';
import 'dart:io';

Future<void> mergeMp3Files(List<String> inputFilePaths, String outputPath) async {
  final joiner = Mp3Joiner();
  await joiner.join(
    inputPaths: inputFilePaths,
    outputPath: outputPath,
  );
  print('MP3文件拼接完成:$outputPath');
}

总结

  • 优先用暂停续录直接生成单个文件的方案,最省事,不用额外处理拼接逻辑;
  • WAV文件拼接逻辑简单,适合自己控制细节;
  • MP3拼接用专用包,避免手动处理复杂的压缩帧结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:59:40