これからは動画だ！と考えているけどどうすればいいかわからないAndroiderへ

動画を取り扱うアプリが増えてきて、ライブラリや開発情報が増えてきました。自分のために動画機能開発の導入部分を備忘録として残しつつ、Androidの動画機能開発者に貢献に役立つといいなぁ。逆に動画なんていらないだろという人にも、動画コンテンツを配信する興味を持ってもらうことも期待しています。

現状Qiitaでは、[ExoPlayerというキーワードを使った記事が4つしかヒットしない](http://qiita.com/search?utf8=%E2%9C%93&q=exoplayer&sort=rel)ので、もっと増えていけば心理的導入負担が少し減るかもしれないです。

## 動画というコンテンツの良さを自身の開発環境で考えてみる

人間はより短い時間で大量かつ良質の情報を消費、収集、ストックできることに利益を感じます。バイラルメディアが叩かれる昨今だけど、人はより冗長な情報を削いだ情報や適度にまとめられた密度の高い二次情報を欲しがっています。バイラルメディアのいいねが伸びることやGithubのAwesomeレポジトリのスター数を見れば一目瞭然です。

動画は相手に短時間に伝える情報が多く、漫画がアニメになると途端に面白くなるのは伝わらなかったニュアンスが急に伝わるからなのではないでしょうか。ユーザーの面白い体験、伝えたいメッセージなど今まではテキストや写真で伝わらなかったものが伝わる。そんな良さが動画にはあるはずです。サービスにとって「本当に伝えたい何か」を動画にするともしかしたらよくなるかもしれないですね。

- 登録画面は動画にするとイメージがわくかも
- チュートリアルは動画のほうがわかるかも
- 料理の手順は動画のほうが一瞬でわかるかも
- オークション出品物の使用感は動画のほうがわかるかも
- 宿泊地の雰囲気は動画のほうがわかるかも

こんな風に一度考えてみてユーザーが本当に嬉しいものを作れたらいいです。

## 自分の環境に適した動画機能は何か見極める

動画の導入が進むことを願う記事だが、とりあえず動画にする！というのはちょっと待って、冷静に本当に動画であるべきかどうか考えましょう。それだけ動画はプロダクトの印象を変えるし、そこにかかるコストは割と大きいです。

- コンテンツの作成者と消費者に明確な線引きがある動画の提供（テレビ、huluなど）
   - ストリーミング、HLSなどによる再生が必要
- 誰でも気軽に動画を投稿、閲覧できるサービスの提供（Youtube、ニコ動、Amebaなど）
   - 投稿、再生が必要
- ユーザーが映像作品としての動画を残していく良さを提供（Instagram、Mixchannelなど）
   - 投稿、編集、保存、再生が必要

## 動画機能を持つ参考アプリ

### [Instagram](https://play.google.com/store/apps/details?id=com.instagram.android)

![insta_1.png](https://qiita-image-store.s3.amazonaws.com/0/26883/bd96181f-3a4a-0090-fdc6-900ec67dc567.png)　![insta_2.png](https://qiita-image-store.s3.amazonaws.com/0/26883/9938bedb-8f52-773a-f58d-c861cabc2244.png)


インスタグラムでは、撮影からエフェクトをかけて切り取りなどの編集も可能です。サムネイルを選択できるようになっているのは動画を作品として残すアプリにはマストかもしれないです。

### [Boomerang](https://play.google.com/store/apps/details?id=com.instagram.boomerang)

![boomerang.png](https://qiita-image-store.s3.amazonaws.com/0/26883/d948505a-b0b3-408d-84a8-35800b1bb8dd.png)

インスタグラムが出した1秒のループ動画を撮影可能なアプリ。Facebookへの投稿もバッチリです。現状、動画の編集はできませんが、できることの制約が逆にアプリの良さになっています。ユーザーの操作も非常に簡単です。

### [Ameba](https://play.google.com/store/apps/details?id=jp.ameba&hl=ja)

![ameba.png](https://qiita-image-store.s3.amazonaws.com/0/26883/be6b1f0d-8171-7822-4656-82ff7c39ffbe.png)

Amebaブログの投稿が可能なプラットフォームアプリ。ブログ投稿時に1分以内へ切り取り可能になっています。

### [MixChannel](https://play.google.com/store/apps/details?id=tv.mixch.android&referrer=utm_source%3Dtwitter%26utm_medium%3Dmap)

![mix_1.png](https://qiita-image-store.s3.amazonaws.com/0/26883/9fc81003-b2e8-6f73-3b28-57ceb553b43f.png)　![mix_3.png](https://qiita-image-store.s3.amazonaws.com/0/26883/da86b857-3210-42b0-d48a-9b25b7e5dbad.png)

主に中高生のカップルを対象とした動画共有SNSです。画面をタッチしている間に撮影し、それを繰り返して繋げていき一つの動画を完成させるようなデザインになっています。またサムネイル選択も0.01秒くらいのコマで調節可能です。

### [vine](https://play.google.com/store/apps/details?id=co.vine.android&hl=ja)

![vine.png](https://qiita-image-store.s3.amazonaws.com/0/26883/02e297da-9392-e994-42fc-ba35057bf671.png)

こちらも6秒以内の短い動画を撮影し投稿できるSNSサービス。動画の編集は切り取りに対応しています。
 
### TwitterやFacebook

![twitter.png](https://qiita-image-store.s3.amazonaws.com/0/26883/b27725d6-a2a2-3c15-dbda-ecd98a00510f.png)　![facebook.png](https://qiita-image-store.s3.amazonaws.com/0/26883/99067c0e-01fd-ad26-6909-0426aac8a4de.png)

この二つに関しては基本的な、撮影、投稿のみの機能になっています。

### InstagramがAndroidのライブラリとか公開してくれたら楽しそうな気がする

[Instagramの公開レポジトリ](https://github.com/Instagram?page=1)の中にAndroidなものはない…これは結構悲しい。
素晴らしいノウハウがあるはずなので、是非ともAndroidコミュニティの活性化を手伝ってもらいたい。
ちなみに、僕はInstagramのAndroid betaテスターになっていて、誰でも[ここ](https://groups.google.com/forum/#!forum/instagram-for-android-beta-testers)から参加できるのでおすすめです。時には起動した瞬間に落ちるバグなどもあったりしましたが、活発に更新されていて面白いのです。

# 実装やライブラリについて

導入記事なので実装に関しては詳しく書きません。詳しいことは公式のドキュメントを読むかデモアプリのコードを読むのが一番です。

## 再生の実装の注意点

### [動画の再生にはExoPlayer](https://github.com/google/ExoPlayer)

ExoPlayerはGoogleI/Oの2014で紹介されていて、スタンダードになっているライブラリです。豊富なサンプルがついて実装の参考になると思います。メンテナンスを行っているのがなんと一人なので、みんなでバグを見つけてPRを出していくのが良さそうです。また、仕様変更がversionによって大きいので、イシューや[リリースノート](https://github.com/google/ExoPlayer/blob/dev/RELEASENOTES.md)はこまめに確認したほうが良さそうです。

ローカルやURL先の動画を再生するには[ここ](https://github.com/google/ExoPlayer/blob/master/demo/src/main/java/com/google/android/exoplayer/demo/player/ExtractorRendererBuilder.java)の以下の部分でプレイヤーを作成し、プレイヤーをコントロールするだけで可能です。

```java
@Override
public void buildRenderers(DemoPlayer player) {
    Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE);

    // Build the video and audio renderers.
    DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(player.getMainHandler(),null);
    DataSource dataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
    ExtractorSampleSource sampleSource = new ExtractorSampleSource(uri, dataSource, allocator,BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE);
    MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(context,sampleSource, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 5000, player.getMainHandler(),player, 50);
    MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource,null, true, player.getMainHandler(), player, AudioCapabilities.getCapabilities(context));
    TrackRenderer textRenderer = new TextTrackRenderer(sampleSource, player,player.getMainHandler().getLooper());

    // Invoke the callback.
    TrackRenderer[] renderers = new TrackRenderer[DemoPlayer.RENDERER_COUNT];
    renderers[DemoPlayer.TYPE_VIDEO] = videoRenderer;
    renderers[DemoPlayer.TYPE_AUDIO] = audioRenderer;
    renderers[DemoPlayer.TYPE_TEXT] = textRenderer;
    player.onRenderers(renderers, bandwidthMeter);
}
```

ExoPlayer最大の注意は

> ExoPlayer’s standard audio and video components rely on Android’s MediaCodec API, which was released in Android 4.1 (API level 16). Hence they do not work on earlier versions of Android.

なので、 **API level 16以上でないと使えないこと** です。古い端末のユーザーがいるサービスでは判定処理が必須になります。基本的な再生に関して日本語で書かれているドキュメントは[こちら](http://shunirr.hatenablog.jp/entry/2015/09/16/231512)です。

### [アプリとSurfaceViewの相性が悪ければexoplayer-textureview](https://github.com/satorufujiwara/exoplayer-textureview)

特に、SurfaceViewは回転などで再生がうまくいかなかったりするので、横画面での使用や編集時の回転などを考慮する場合に役立つと思います。内部の実装もとても参考になります。ですが、

> *This library is experimental. API and all codes will be changed without notice*

と書いてあるように、APIに大きな変更が加わる可能性があるのでご注意ください。

### 対応形式

Androidは最近の端末ではmp4形式で保存されているのがほとんどだと思いますが、それ以外にも対応されています。詳しくは[ExoPlayer#SampleSource - Developer guide](https://google.github.io/ExoPlayer/guide.html#samplesource)を参照してください。

## 編集機能の実装時の問題

動画の切り取りには[mp4parser](https://github.com/sannies/mp4parser)を使うと良いでしょう。一年以上前の記事ですが、日本語であれば[[Android Tips] mp4parser を使って動画ファイルを編集する | Developers.IO](http://dev.classmethod.jp/smartphone/android/mp4parser/)という記事があります。

基本的にここでは切り取りにmp4parserを使うことを考えているので、その他の形式については別途調べる必要があります。

### ファイルサイズ

動画のサイズはピクセル数によりますが、Google Photoなどでいろんな端末から共有されたデータは1時間以上のものがある可能性もあります。動画のファイルサイズでの指定や、以下のように動画の時間を取得して、適切な長さの動画のみを編集対象にするのも一つの手です。

```java
int duration = MediaPlayer.create(context, uri).getDuration();
```

### 一時ファイルをどうするか

動画のアップロードは時間がかかります。もしネットワーク環境が悪く失敗した場合などを考慮して、ファイルの一時保存、アップロード成功時の一時データ削除などを考えるべきだと思います。特に編集を行うアプリの場合、 **「時間をかけて作った動画が一度失敗したら消えた… :scream_cat:」** みたいなのはユーザーが萎えます。

### 編集画面のレイアウト

ここは独自実装になります。サンプルライブラリも見当たらないので作成中です。近日公開。動画にエフェクトをかけるなら[GPUImageのAndroid版](https://github.com/CyberAgent/android-gpuimage)が良いでしょう。

動画に関連するライブラリですが、あまり種類は知りません。他にもあれば是非教えてもらいたいです！

## 最後に

実装に入る前にまず公式のドキュメントは読んでおくべきです。

- [Recording Videos Simply](http://developer.android.com/intl/ja/training/camera/videobasics.html)
- [ExoPlayer Develoer guide](https://google.github.io/ExoPlayer/guide.html)

### サンプル作成中

ここまで書いてきた内容で頑張ってプロダクト導入はしたものの、他のAndroidエンジニアからの意見をもらったり、実装の参考として使ってもらえるようなサンプルを作成中です。ベースはInstagramのデザインですが、中身はExoPlayerで表示、mp4parserで切り取りを行うものです。依存ライブラリが二つあるのはあまり良くないですが、対応できるフォーマットを増やしつつ依存も解消していけるようにします。近日公開。

もしストックされた場合、公開後通知を飛ばします。
今後、需要があればHLSなどについても書いていきます。