AWSを利用した動画変換から動画配信まで

動画関連の知識がなく苦労したのでメモ。

ffmpegでの動画変換も試したのですが、変換の時間とサーバのリソースを食うため、
小規模サービスでは向かないと判断し、ElasticTranscoderを利用することとしました。

今回の構成としては、COOKPADに近いものとなっています。
http://techlife.cookpad.com/entry/2014/06/17/160905


## 動画配信方法
PC,スマートフォン(iOS, Android)向けに配信する方法を調査し、最終的にmp4とHLSで配信する事としました。
大半のデバイスはこの2種類を用意すればカバーできます。
mp4 : PC, Android2系への配信(flash)
HLS : iOS, Android4系への配信

HTML5での動画再生用のライブラリがいくつかあるので、
そちらを使えば両形式の配信に対応できます。
今回のサンプルではVideoJSを使います。
http://www.videojs.com/

## 事前準備
まず、AWSで __【CloudFront】__ __【S3】__ __【ElasticTranscoder】__ を利用します。
__【S3】__
bucket、サンプル動画、アウトプット用フォルダを用意します。
bucket：video_sample
動画ファイル：sample.mov
フォルダ：test

__【CloudFront】__
Distributionは「Web」「RTMP」を用意します。
WebはHLS、RTMPはflashで使用します。

__【ElasticTranscoder】__
テスト用のPipeline「test-Pipeline」を作成します。
Pipelineとは、InputやOutput用のS3のバケット等を指定するものです。
動画変換は、このPipelineに対してJobを作成すると動画変換されるようになっています。
また、動画変換時に指定するPresetは変換するコンテナ等の定義となっています。
※サムネイルも生成する場合、デフォルトで用意されているPresetでは画像が荒いため、個別に作成することをお勧めします。

## SDKを利用した動画変換サンプル
今回利用するPHPとSDKのバージョンは下記の通りです。
・PHP5.5系
・AWD SDK for PHP2.4.5

API reference
http://docs.aws.amazon.com/aws-sdk-php/latest/class-Aws.ElasticTranscoder.ElasticTranscoderClient.html

```ElasticTranscoder.php

<?php
use Aws\Common\Aws;
use Aws\Common\Enum\Region;
use Aws\ElasticTranscoder\Exception\ElasticTranscoderException;
use Aws\ElasticTranscoder\ElasticTranscoderClient;

class ElasticTranscoder {

	private $obj = null;

	/**
	 * AWS SDK for PHP
	 */
	private function getInstance() {
		if (is_null($this->obj)) {
			$this->obj = Aws::factory([
				'key'    => 'xxxxxxxxxx',
				'secret' => 'yyyyyyyyyy',
				'region' => Region::TOKYO
			])->get('ElasticTranscoder');
		}
		return $this->obj;
	}

	/**
	 * createJob
	 */
	public function createJob($args) {
		try {
			$res = $this->getInstance()->createJob($args);
		} catch (Exception $e) {
			#echo $e->getMessage();
			return false;
		}
		return $res;
	}
}

$ElasticTranscoder = new ElasticTranscoder();
$ElasticTranscoder->createJob([
	'PipelineId' => 'test-Pipeline',
	'Input' => [
		'Key' => 'sample.mov',
	],
	'Outputs' => [
		// mp4 & Thumbnail
		[
			'Key'              => 'test/output.mp4',
			'PresetId'         => '1351620000001-100070', // System preset: HLS 2M
			'ThumbnailPattern' => "output-{count}"
		],
		// HLS
		[
			'Key'             => 'test/output',
			'PresetId'        => '1351620000001-200010', // System preset: HLS 2M
			'SegmentDuration' => 5 // 動画を何秒ごとに分割するか
		]
	],
]);

```

上記の処理を実行してJobが完了すると、アウトプット用フォルダ「test」内に下記のファイルが生成されます。
サムネイルとHLSのファイルに関しては、Presetや動画の再生時間によってファイル数が変わります。
・サムネイル
output-00001.png
output-00002.png
・mp4
output.mp4
・HLS
output.m3u8
output000000.ts
output000001.ts



## 動画再生用HTMLサンプル
headタグ

``` 
<link rel="stylesheet" type="text/css" href="video-js.css" />	
<script type="text/javascript" src="video.js">
```

bodyタグ

```
<video id="sample_video" class="video-js vjs-default-skin" width="100%" height="100%" poster="http://{S3のドメイン}/test/output-00001.png" preload="none" controls>
     <source src="http://{CloudFront(Web)のドメイン}/test/output.m3u8" type="application/x-mpegURL" />
	<source src="rtmp://{CloudFront(RTMP)のドメイン}/cfx/st/&mp4:test/output.mp4" type="rtmp/mp4" />
</video>
<script>
videojs.options.flash.swf = "video-js.swf";
var homePlayer=_V_("sample_video");
</script>
```

### 最後に
動画ファイルの管理から変換、配信までAWSのサービスだけで完結できるので、AWS凄いなという印象です。
ただ、動画について知識が無い状態でスタートすると、用意する動画の形式や配信方法、ElasticTranscoderの使い方等、
情報が少なく苦戦したので、今後動画関連の機能を実装する方の参考になれば幸いです。