How to merge two audio files with just_audio for playing both at the same time?

1,219

The only way I have found to concatenate multiple audio files is to use ffmpeg. Add this to your pub.dev flutter_ffmpeg and add this class to your lib folder:

class FFmpeg {

  static Future<File> concatenate(List<String> assetPaths, {String output = "new.mp3"})async{

    final directory = await getTemporaryDirectory();
    final file = File("${directory.path}/$output");

    final ffm = FlutterFFmpeg();
    final cmd = ["-y"];
    for(var path in assetPaths){
      final tmp = await copyToTemp(path);
      cmd.add("-i");
      cmd.add(tmp.path);
    }

    cmd.addAll([
      "-filter_complex",
      "[0:a] [1:a] concat=n=${assetPaths.length}:v=0:a=1 [a]",
      "-map", "[a]", "-c:a", "mp3", file.path
    ]);

    await ffm.executeWithArguments(cmd);
    return file;
  }

  static Future<File>copyToTemp(String path)async{
    Directory tempDir = await getTemporaryDirectory();
    final tempFile = File('${tempDir.path}/${path.split("/").last}');
    if(await tempFile.exists()){
      return tempFile;
    }
    final bd = await rootBundle.load(path);
    await tempFile.writeAsBytes(bd.buffer.asUint8List(), flush: true);
    return tempFile;
  }
}

Example:

final track = await FFmpeg.concatenate(
      [
        "assets/audios/test1.mp3",
        "assets/audios/test2.mp3",
        "assets/audios/test3.mp3",
      ],
      output: "output.mp3"
    );
Share:
1,219
JavaRunner
Author by

JavaRunner

Updated on November 28, 2022

Comments

  • JavaRunner
    JavaRunner over 1 year

    How to merge (not concat) two audio files with just_audio for playing both at the same time?

    I want to merge it to avoid a hardware limit of just_audio instances playing at the same time. To play with just one instance of just_audio.

    • Ryan Heise
      Ryan Heise about 3 years
    • JavaRunner
      JavaRunner about 3 years
      @RyanHeise, no, I want to merge it to avoid a limit of just_audio instances playing at the same time. To play with just one instance of just_audio.
    • Ryan Heise
      Ryan Heise about 3 years
      Did the question change? If the question is now about avoiding a limit, the answer is that there is no way to avoid the limit. If you are merging N audio sources simultaneously, you need N decoders. The fact that each decoder represents an AudioPlayer instance in just_audio doesn't add anything extra to the minimum resources required to solve the problem, so feel free to just create as many instances you need until you hit a limit for the number of simultaneous decoders that the device can cope with.
    • JavaRunner
      JavaRunner about 3 years
      @RyanHeise, I mean I wanna get a waveform of a first file plus waveform of a second file to play the output waveform using just one instance of just_audio.
    • Ryan Heise
      Ryan Heise about 3 years
      I can theoretically redesign just_audio for you to do this in a single instance. But the catch is that mixing two audio sources in a single just_audio instance will still use double the resources because as I already said above, there is no way to avoid the hardware limit. If you push the air bubble down somewhere, it will pop up elsewhere. When it comes to the hardware resources required to decode audio, it doesn't come for free. Decoding two waveforms is twice the work as decoding one waveform, so there is obviously a limit to how much simultaneous work can be done at once.