【AWS】ElasticTranscoderで動画変換する仕組みを構築する

## はじめに
今回、弊社運動通信社で開発しているスポーツブルアプリの中のスーパープレイ動画機能の裏側について少しご紹介させていただきます。
スーパープレイ動画機能とは様々な競技のスーパープレイの部分を切り取った縦型の動画集をスワイプしながらザッピング感覚で閲覧できるものです。

↓動画は以下のように縦型フルスクリーンで閲覧できます。
![tatefuluのコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/a8d702b9-f20b-328a-ce02-4bf45c08d7bd.png)

ザッピング感覚で閲覧できるようにする上で通信環境の考慮が必要となってきます。
通信環境によって読み込み時間が長いと体験が損なわれてしまうため、通信環境に応じた複数ビットレートの動画を用意し、その点を解決しました。
具体的にはAWSのElasticTranscoderを使ってその仕組みを構築してみましたので、事例としてご紹介したいと思います。


## 構成イメージ
ざっくりした構成と処理の流れはこんな感じになります。
![tatehuru.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/9e7bd4cd-e5e9-d63a-828e-a2449e6dd2d5.png)


## 手順

### ElasticTranscoderの設定
1. Pipeline
ジョブを管理するキューです。作成したキューをLambda側から指定するため必要な項目を入力し作成します。
主な設定内容は以下となります。
  - 変換元ファイル入力先S3バケット
  - 変換後ファイル出力先S3バケット
  - サムネイル出力先S3バケット
  - SNSのtopic作成

2. Preset
変換処理に適用される設定を定義したテンプレートです。こちらも事前に作成しておいて、Lambdaからジョブを作成する際に使用するものを指定します。
設定の詳細については[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/elastictranscoder/latest/developerguide/preset-settings.html)で参照できます。


### Lambdaの作成
まず構成イメージの①②のところにあたる変換を実行するコードを書いていきます。

##### 変換実行のサンプルコード

```javascript
const aws = require('aws-sdk');
const transcoder = new aws.ElasticTranscoder({apiVersion: '2012-09-25', region: 'ap-northeast-1'});

exports.handler = async (event, context, callback) => {
  const key = event['Records'][0].s3.object.key;
  const file = key.split('/').reverse()[0];
  const filename = file.split('.')[0];

  new Promise((resolve, reject) => {
    try {
      const params = {
        // ElasticTranscoderのコンソールから作成したPipelineのID
        PipelineId: 'xxxxxxxxxxxxx-xxxxxx',
        OutputKeyPrefix: 'sample/',
        Input: {
          Key: key,
          FrameRate: 'auto',
          Resolution: 'auto',
          AspectRatio: 'auto',
          Interlaced: 'auto',
          Container: 'auto'
        },
        // 複数ビットレートの動画を出力する場合はここで対応する複数のpresetを指定する
        Outputs: [
          {
            Key: `preset1/${filename}.mp4`,
            ThumbnailPattern: `thumbnail/${filename}-{count}`,
            // ElasticTranscoderのコンソールから作成したPresetのID
            PresetId: 'xxxxxxxxxxxxx-xxxxxx',
            Rotate: 'auto'
          }
        ]
      };

      // ElasticTranscoderのJob作成
      transcoder.createJob(
        params,
        function(error, data) {
          if (error) {
            console.log(error);
            throw new Error(error);
          } else {
            console.log('Job submitted.');
          }
        }
      );

    } catch(e) {
      reject(e);
      return;
    }
    resolve();
    return;
  }).catch((e) => {
    callback(e);
  });

  callback(null, 'Success.');
}

```

変換完了後は構成イメージの④⑤のようにSNSから通知を受け取り、完了後の処理を実装できます。

##### 変換完了後のサンプルコード

```javascript
const aws = require('aws-sdk');

exports.handler = async (event, context, callback) => {
  const snsMessage = JSON.parse(event.Records[0].Sns.Message);
  // メッセージの中身を見て必要な処理を行う
};

```

## 終わりに
今回は、ElasticTranscoderを使った構成についてご紹介させていただきました。実際にシステムに組み込む場合は動画をサーバーからアップロードしたり、完了後にも必要な処理を組み込むなどあるかと思いますが、動画変換については基本的には今回ご紹介したような形になるかと思いますので少しでもご参考になる方がいらっしゃれば幸いです。
それでは。

## 参考サイト
https://docs.aws.amazon.com/ja_jp/elastictranscoder/latest/developerguide/preset-settings.html


運動通信社は
「日本を世界が憧れるスポーツ大国にする」というビジョンを達成するべく、
一緒に働く仲間を募集しています！
https://sportsbull.jp/about/#recruit