Androidアプリ開発

動画や音楽のファイル形式を変換する

この記事は約30分で読めます。
記事内に広告が含まれています。
スポンサーリンク

この記事は Android スマホ用のアプリ開発の中で、
今後の開発で再使用性が高いと思われるコーディングをまとめたものです。
Java での開発経験、XML 構文規則、Android のアプリ開発経験がある方を対象としています。
Android のアプリ開発でお役にたててれば、嬉しいです。
(これから Android のアプリ開発や Java での開発を始めたい方への案内は、
記事の最後で紹介します)

この記事のテーマ


 FFmpegを使用して、動画ファイルや音楽ファイルの形式を変換する

Androidのスマホは、MP4形式しか動画ファイルは再生できません。
ビデオカメラで撮影した動画ファイルは、MTS形式が多い。
MTS形式の動画ファイルをAndroidで再生するには、MP4形式に変換する必要があります。

Android13から、AIFF形式(Apple標準のオーディオ形式)の音楽ファイルが再生できなくなっています。
CDの曲をiTunesに取り込んだ音楽ファイルをAndroid13以降で再生するには、MP3形式に変換する必要があります。

FFmpegは、動画ファイルや音声ファイルを記録・変換・再生するためのフリーソフトウェアです。
Androidで対応していない形式のファイルは
FFmpegを使用して、MP4形式やMP3形式に変換すれば、Androidでも再生できるようになります。

FFmpegKitは、Androidで使用できるオープンソフトウェアライブラリです。

ffmpegkitを使用するための準備

ffmpegkitを使用するには、
プロジェクトおよび、モジュールの
build.gradleファイルに定義の追加が必要です。

◎build.gradle(プロジェクト)

:
allprojects {
    repositories {
        mavenCentral()
        :
    }
}
:

◎build.gradle(モジュール)
2024年2月現在の最新バージョンは 6.0.2 です。

dependencies {
    :
    implementation 'com.arthenica:ffmpeg-kit-full:6.0-2'
}

◎ライセンス表記
ffmpegkitは、LGPL v3.0 Licenseです。
アプリで使用する場合、ライセンス表記が必要です。

ライセンス条文の記載がある公式サイトのリンクをアプリに実装しています

動画ファイルの形式を変換する

ffmpegkitは、コマンドライン引数で動画ファイルの変換動作をパラメータで指定します。
フォーマット、コーデック、開始位置や長さ、品質指定などが指定できます。
これらパラメータ指定の組み合わせで、MP4形式変換、サムネイルの作成、動画のトリミングが可能です。

動画再生アプリ(Duel)は、MP4形式以外の動画ファイルも再生できます

メディアストア(動画フォルダ)の動画ファイルにアクセスするには、きめ細かいメディア権限を設定する必要があります。
詳細は、
Android13対応(ファイルのメディア権限)で紹介しています。

MP4形式変換

FFmpegKitは、動画ファイルの形式は拡張子で判断しています。
入力ファイルがMP4形式以外の拡張子で、出力ファイルの拡張子がMP4形式であれば、MP4形式に変換できます。

import com.arthenica.ffmpegkit.FFmpegKit;
import com.arthenica.ffmpegkit.FFmpegKitConfig;
import com.arthenica.ffmpegkit.FFmpegSession;
import com.arthenica.ffmpegkit.ReturnCode;
:
    String[] mimeList = new String[]{"video/mp4", "video/webm", "video/quicktime", "video/mp2ts"};
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    executorService.execute(() -> {
        try {
            ContentResolver resolver = context.getContentResolver();
            Cursor cursor = resolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null, null, "_ID DESC");
            while (cursor.moveToNext()) {
                if (Arrays.asList(mimeList).contains(cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.MIME_TYPE)))) {
                	Uri contentUri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, Long.parseLong(cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID))));
                    String path = cursor.getString(cursor.getColumnIndex(MediaStore.Video.VideoColumns.DATA));
                    String source = cursor.getString(cursor.getColumnIndex(MediaStore.Video.VideoColumns.DISPLAY_NAME));
                    String ext = source.substring(source.lastIndexOf(".")).toLowerCase();
                    long width = Long.parseLong(cursor.getString(cursor.getColumnIndex(MediaStore.Video.VideoColumns.WIDTH)));
                    long height = Long.parseLong(cursor.getString(cursor.getColumnIndex(MediaStore.Video.VideoColumns.HEIGHT)));
                    // 拡張子がMP4以外はコーディック
                    if (!ext.equals(".mp4") && ext.length() > 0) {
                        // ファイル名からスペース削除と拡張子変更
                    	String file = source.toLowerCase().replace(" ", "").replace(" ", "").replace(ext, ".mp4");
                        path = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) + File.separator + file;
                        // mp4ファイル変換
                        String mts = FFmpegKitConfig.getSafParameterForRead(context, contentUri);
                        String mp4 = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) + File.separator + file;
                        FFmpegSession session = FFmpegKit.execute(String.format("-i '%s' -qmin %d -qmax %d -acodec libmp3lame -ab 192000 -ar 48000 -s %dx%d '%s'", mts, 16, 20, width ,height , mp4));
                        if (ReturnCode.isSuccess(session.getReturnCode())) {
                        	// 変換成功
                            :
                        } else {
                        	// 変換失敗
                            :
                        }
                    }
                }
            }
            cursor.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    });

コンテンツリゾルバを使用して、メディアストア(動画フォルダ)の動画ファイルのリストを取得しています。
また、MIMEタイプがmp4、webm、quicktime(MOV)、mp2ts(MTS)の動画ファイルか判定しています。
コンテンツリゾルバのクエリ結果より、Uri、パス、ファイル名、拡張子、サイズを取得します。
MP4形式以外の場合、MP4形式に変換します。
FFmpegKitの引数として、入力ファイルパス(-i)、品質指定(-qmin, -qmax)、音声コーディック(-acodec)、音声サンプリングレートレート(-ar)、音声ビットレート(-ab)、サイズ(-s 横*縦)、出力ファイルパスを指定しています。
動画コーディックは、デフォルト(指定なし)を使用します。
変換結果は、
FFmpegSessionで判定します。

エンコード時の出力ファイルの動画品質(q値範囲の最小と最大)を指定できます。
小さい方が高品質ですが、ファイルサイズは大きくなる傾向があります。
引数に
-c:v copyを追加することで動画コーディックをしない指定が可能です。
音声コーディックはMP3エンコーダー、サンプリングレートとビットレートは業界標準値です。

サムネイル画像の作成

動画ファイルの開始位置とフレーム数に1を指定することで、サムネイル画像ファイルを出力できます

import com.arthenica.ffmpegkit.FFmpegKit;
:
    String[] mimeList = new Strin