💭

【Flutter】ffmpeg_kit_flutter_audioを使って、m4aをmp3に変換する方法

2024/08/13に公開

はじめに

様々な方言を話すおしゃべり猫型ロボット「ミーア」を開発中。

https://mia-cat.com/

前回、「flutter_soundを用いた音声録音再生、アップロード機能の実装」の記事を記載したのだが、ESP32のミーア本体に音声ファイルがダウンロードされるものの、なぜか再生できない現象が生じた。

https://kazulog.fun/others/flutter_sound_upload/

エラーも出ないので、なかなか原因特定が難しかったのだが、flutter_soundでm4a形式で録音していたものを拡張子だけmp3に変更しており、中身はm4aのままだったのでESP32で再生するときに再生できなくなっていたことが原因だった。

そのままm4aを再生できるようにESP32側のコードを修正しても良いのだが、機械音声合成でmp3をすでに出力しているので、今回はmp3に統一したいと思う。

flutter_soundではmp3をサポートしていない!?

flutter_sound_platform_interfaceパッケージでは、一応mp3形式でのエンコードもサポートしてそうな雰囲気が出ているが(shame on you!と記載されているがw)、実際にmp3を使ったところエラーになりエンコードできなかった。

https://pub.dev/documentation/flutter_sound_platform_interface/latest/flutter_sound_platform_interface/Codec.html

同じ問題に遭遇している人を発見https://github.com/Canardoux/flutter_sound/issues/175

回答者のこちらのテーブルに記載されているようにflutter_soundではMP3のエンコードはiOSもAndroidもサポートされていない。

スクリーンショット 2024-08-13 9.31.26.png

record + audioplayersパッケージの場合は?

代替案として、flutter_sound以外のパッケージを使うことを考え、リサーチしたところ音声録音としてrecordパッケージ、音声再生としてaudioplayersパッケージを使うことを検討。

しかし、recordパッケージも録音ファイルの形式はm4aやwavなどが中心で、mp3形式には対応していないことが判明したので、結局今のflutter_soundパッケージの場合と同じ課題が残る。

そこで、ffmpeg_kit_flutter_audio パッケージを使用して、m4aをmp3に変換する方針に変更。このパッケージは、外部ライブラリを使用して幅広い形式に対応しており、mp3形式への変換に必要な lame ライブラリが含まれている。

ffmpeg_kit_flutter_audioを使った変換

ffmpeg_kit_flutterパッケージはこちら。

https://pub.dev/packages/ffmpeg_kit_flutter

ffmpeg_kit_flutter パッケージ自体はmp3変換ライブラリを含んでいないが、さらに8つの外部ライブラリを提供しており、audioライブラリはmp3変換ライブラリを含んでいる。

https://github.com/arthenica/ffmpeg-kit?tab=readme-ov-file

スクリーンショット 2024-08-13 9.37.32.png

というわけで、ffmpeg_kit_flutter_audioパッケージをインストール。

dependencies:
  ffmpeg_kit_flutter_audio: 6.0.3-LTS

ffmpeg_kit_flutter_audioパッケージを使って、m4aをmp3に変換するコードを下記のように記載。

Future<void> _convertToMp3() async {
    if (_recordedFilePath == null) return;

    final directory = await getTemporaryDirectory();
    final outputPath =
        '${directory.path}/recording_${DateTime.now().millisecondsSinceEpoch}.mp3';

    final ffmpegCommand =
        '-i $_recordedFilePath -codec:a libmp3lame -qscale:a 2 $outputPath';

    await FFmpegKit.execute(ffmpegCommand).then((session) async {
      final returnCode = await session.getReturnCode();
      if (ReturnCode.isSuccess(returnCode)) {
        setState(() {
          _convertedFilePath = outputPath;
        });
        print('MP3への変換が成功しました: $outputPath');
      } else {
        setState(() {
          _errorText = "MP3への変換に失敗しました";
        });
        print('MP3への変換に失敗しました。エラーメッセージを確認してください。');
      }
    });
  }

そして、変換したMP3の音声ファイルパスを使用して、、、

続きはこちらで記載しています。
https://kazulog.fun/dev/flutter-m4a-to-mp3/

Discussion