Android NDK でビルドした FFmpeg(libav* 系 .so)または既製バイナリを、 JNI から実際に叩いて 動画をトリミング するための検証用アプリです。 ebutuoY / Loopit など本番アプリに FFmpeg を組み込む前に、 ビルド・リンク・権限・パフォーマンスを一通り確かめるためのプロジェクトとして作りました。
try_ffmpeg は、ユーザーが選んだ mp4 動画を、 「開始時刻」と「長さ(または終了時刻)」を指定して切り出すだけの シンプルなテストアプリです。 しかし裏側では、NDK でビルドした FFmpeg を 正しくロードし、JNI 経由でコマンドを実行し、 標準出力・標準エラーをログに集めるところまでを一気通貫で確認しています。
最終的には、-ss と -t(または -to)を使った
無再エンコード(-c copy)・再エンコードの両方を試し、
どこまでスマホ単体で高速に編集できるかを測ることを目的としています。
UI(Kotlin)のボタンからトリミング要求が飛び、
JNI ラッパーを経由して NDK 側の ffmpeg_main() を呼び出します。
コマンド引数は文字列配列で渡し、FFmpeg 側のログはコールバックで
Kotlin に引き上げて TextView や Logcat に表示しています。
ffmpeg_main() を呼び出す。
try_ffmpeg では、Android 用にクロスビルドした FFmpeg の .so を
jniLibs/ 配下に配置し、CMake からリンクする構成を試しました。
ABI 別(arm64-v8a, armeabi-v7a)の .so を分けて配置し、
実機に合わせて正しいバイナリがロードされるかを確認しています。
add_library( # native lib
native-lib SHARED native-lib.cpp )
add_library( avcodec SHARED IMPORTED )
set_target_properties(avcodec PROPERTIES
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libavcodec.so")
target_link_libraries(native-lib avcodec avformat avutil log)
C 側では FFmpeg の ffmpeg_main(int argc, char** argv) 風のエントリを
1 つの関数として定義し、その周りを JNI でラップします。
Kotlin 側では String 配列を渡し、C 側で char** に変換して実行します。
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_tryffmpeg_FFmpegRunner_run( JNIEnv* env, jobject thiz, jobjectArray args ) {
int argc = env->GetArrayLength(args);
char** argv = convert_to_argv(env, args);
int ret = ffmpeg_main(argc, argv);
free_argv(argv, argc);
return ret;
}
動画トリミングは、まずは FFmpeg の王道パターンである
-ss <start> -t <duration> -c copy を使用。
再エンコード無しでコンテナを書き換えるだけの高速カットと、
再エンコード有りの場合の画質・速度差も計測しました。
ffmpeg -ss 00:00:05 -t 00:00:10 -i input.mp4 \
-c copy output_trimmed.mp4
FFmpeg のログコールバックを差し替え、 文字列を JNI 経由で Kotlin 側に送ることで、 アプリ画面上の TextView にリアルタイムにログを表示できるようにしました。 将来的にはログから処理済みフレーム数・時間をパースして プログレスバーに反映する予定です。
60秒のフルHD mp4 を用意し、5秒〜15秒の区間だけを切り出すテストを行いました。
-c copy の場合は数秒以内に完了し、
再エンコードあり(ビットレート指定)の場合は
端末の性能に応じた処理時間になることを確認しました。
・FFmpeg の .so が大きく、APK サイズが膨らみがち ・ABI ごとにビルドした結果の管理が煩雑 ・一部端末では SAF 経由のパス処理にクセがある など、実運用に向けて解決したいポイントが見えてきました。
入力動画の選択 → 開始/終了時刻の指定 → トリミング実行 → ログが流れて出力動画がギャラリーに保存されるまでを 収めたデモ動画です。
try_ffmpeg はテストアプリですが、 ここで作った JNI ラッパ・ビルドスクリプト・ログの扱いは そのまま ebutuoY や Loopit の動画編集エンジンとして再利用できます。 将来的には、切り抜きアプリ用に カット / 結合 / 速度変更 / 字幕焼き込みなども実装していく予定です。
コアの NDK 部分を安定させつつ、徐々に UI と機能を広げて 「テストアプリから本番用ライブラリ」へ昇格させていきます。
try_ffmpeg を作る中で、「NDK と FFmpeg を自分で回せるようになる」と 動画編集アプリに対して一気に自由度が増すことを実感しました。 既製ライブラリに頼るのではなく、自分でビルド・リンク・JNI を理解しておくことで、 将来の拡張やトラブル対応にも強くなれると感じています。
一方で、ビルド時間やバイナリサイズ、ABI の数など、 実務寄りの制約とも向き合う必要がありました。 このプロジェクトは、単なるテスト以上に「Android × NDK × FFmpeg」の リハビリ兼入門として大きな意味があったと感じています。