[Android Tips] mp4parser を使って動画ファイルを編集する
Android で動画編集
Android の動画編集は Android 4.1 (APIレベル16) からできるようになりましたが、4.1 以下で対応するためには標準 API ではできません。そこで、Google が公開している mp4parser という mp4 形式の動画ファイルを編集するライブラリがあるので、ちょっと使ってみました。なお、サンプルコードは以下で公開していますので、お急ぎの場合はこちらを Clone して実行してみてください。
https://github.com/suwa-yuki/Mp4ParserSample
ちなみに assets ディレクトリに mp4 ファイルのサンプルを用意しました。こちらを端末の外部SDカードの直下に置くと読み込めるようになります。
ライブラリの導入
mp4parser ライブラリは Maven を使うか jar ファイルを取り込むかいずれかの方法で導入できます。今回は手軽に jar ファイルをダウンロードしてくることにしました。以下の URL からダウンロードできます(今回は 1.0.1 を使います)。
http://repo1.maven.org/maven2/com/googlecode/mp4parser/isoparser/
なお、aspectjrt に依存しているので、こちらも一緒に入れてください。
http://repo1.maven.org/maven2/org/aspectj/aspectjrt/1.7.3/
試してみる
オリジナル動画
以下の動画を編集します。動画は動画素材.comさんからお借りしました。美味しそう!
複数の動画ファイルを1つにする
それでは試してみます。以下は2つの mp4 ファイルを1つにまとめる処理です。
private boolean append() { try { // 複数の動画を読み込み String f1 = Environment.getExternalStorageDirectory() + "/sample1.mp4"; String f2 = Environment.getExternalStorageDirectory() + "/sample2.mp4"; Movie[] inMovies = new Movie[]{ MovieCreator.build(f1), MovieCreator.build(f2)}; // 1つのファイルに結合 List<Track> videoTracks = new LinkedList<Track>(); List<Track> audioTracks = new LinkedList<Track>(); for (Movie m : inMovies) { for (Track t : m.getTracks()) { if (t.getHandler().equals("soun")) { audioTracks.add(t); } if (t.getHandler().equals("vide")) { videoTracks.add(t); } } } Movie result = new Movie(); if (audioTracks.size() > 0) { result.addTrack(new AppendTrack(audioTracks.toArray(new Track[audioTracks.size()]))); } if (videoTracks.size() > 0) { result.addTrack(new AppendTrack(videoTracks.toArray(new Track[videoTracks.size()]))); } // 出力 Container out = new DefaultMp4Builder().build(result); String outputFilePath = Environment.getExternalStorageDirectory() + "/output_append.mp4"; FileOutputStream fos = new FileOutputStream(new File(outputFilePath)); out.writeContainer(fos.getChannel()); fos.close(); } catch (Exception e) { return false; } return true; }
実行結果
処理には少し時間がかかるので、AsyncTaskLoader などを使って非同期で処理を行いましょう。ファイルサイズが大きくなる場合は Service を使ってしまったほうが良いかも知れません。
動画ファイルを分割する
次に1つの動画ファイルを分割する処理です。
private boolean crop() { try { // オリジナル動画を読み込み String filePath = Environment.getExternalStorageDirectory() + "/sample1.mp4"; Movie originalMovie = MovieCreator.build(filePath); // 分割 Track track = originalMovie.getTracks().get(0); Movie movie = new Movie(); movie.addTrack(new AppendTrack(new CroppedTrack(track, 200, 400))); // 出力 Container out = new DefaultMp4Builder().build(movie); String outputFilePath = Environment.getExternalStorageDirectory() + "/output_crop.mp4"; FileOutputStream fos = new FileOutputStream(new File(outputFilePath)); out.writeContainer(fos.getChannel()); fos.close(); } catch (Exception e) { e.printStackTrace(); return false; } return true; }
実行結果
ちょっとバグってますね・・・(´・ω・`)
動画ファイルに字幕を入れる
次に動画ファイルに字幕を入れる処理です。映画の字幕みたいな感じですね。
private boolean subTitle() { try { // オリジナル動画を読み込み String filePath = Environment.getExternalStorageDirectory() + "/sample1.mp4"; Movie countVideo = MovieCreator.build(filePath); // SubTitleを追加 TextTrackImpl subTitleEng = new TextTrackImpl(); subTitleEng.getTrackMetaData().setLanguage("eng"); subTitleEng.getSubs().add(new TextTrackImpl.Line(0, 1000, "Five")); subTitleEng.getSubs().add(new TextTrackImpl.Line(1000, 2000, "Four")); subTitleEng.getSubs().add(new TextTrackImpl.Line(2000, 3000, "Three")); subTitleEng.getSubs().add(new TextTrackImpl.Line(3000, 4000, "Two")); subTitleEng.getSubs().add(new TextTrackImpl.Line(4000, 5000, "one")); countVideo.addTrack(subTitleEng); // 出力 Container container = new DefaultMp4Builder().build(countVideo); String outputFilePath = Environment.getExternalStorageDirectory() + "/output_subtitle.mp4"; FileOutputStream fos = new FileOutputStream(outputFilePath); FileChannel channel = fos.getChannel(); container.writeContainer(channel); fos.close(); } catch (Exception e) { e.printStackTrace(); return false; } return true; }
実行結果
↑ Galaxy S3 で再生したときのキャプチャです。下のほうに字幕が表示されます。
まとめ
今回の例以外にも、いくつかできることはあるのでこちらのサンプルコードを参考に実装してください。
動画を用いたアプリはあまり多くないと思うので、このライブラリを使って面白い動画アプリを作りたいですね!ぜひ使ってみてください。