クリスマスだし、みんなでバッチ作ろうぜ！(Sofdec)

Merry Christmas!
[株式会社グレンジ](https://www.grenge.co.jp/)でエンジニアマネージャー兼クライアントエンジニアのmesshiです。こんにちは。
(CyberAgentグループ、ゲーム事業部の子会社です)

この記事は[グレンジ Advent Calendar 2018](https://qiita.com/advent-calendar/2018/grenge)の最終日の記事となります。
今年のAdvent Calendarは「CRI Middleware」に関する記事が幾つかあったので、私もそれに便乗しようかなと思います。

・[@shirasaya0201](https://qiita.com/shirasaya0201)から、[UnityでCRIを使う覚悟はいいか？オレはできてる]
(https://qiita.com/shirasaya0201/items/53baa38c83eebaa2cfbf) 
・[@s_ebata](https://qiita.com/s_ebata)から、[CRIを使ったピッチ変更実装のハマりポイント](https://qiita.com/s_ebata/items/a0ddf5a0e25678704e3f)

こちらの記事はADXツールに関するTIPS、つまりサウンド周りです。
少し嗜好を変えて、Sofdecという動画関係のツールに関して、TIPSを取り上げてみようと思います。

# Sofdecといえば
CRI Middlewareが提供している、ゲームに特化した高画質・高音質の動画再生システムのことです。
開発者は、Sofdecのエンコードツールを利用してusmファイルという独自の動画ファイルを生成します。

この動画ファイルの生成には2通りあり、
【1】 Sofdec2EncWiz
　GUIがしっかりしていて、ポチポチしていくだけでusmファイルが生成できる
　基本的にはこちらを使って設定を行うのがメジャー
　ただし、 **複数の動画作成を一括で出来ません**
　つまり、プラットフォームの変更をしたいだけでも、都度設定しないといけない 

【2】exeファイルをコマンドプロンプトから叩く
　定義したコマンドを流し込み、動画を生成する
　ちなみにexeファイルは3種類あり、作成する動画コーデックによって使い分けましょう

|exeファイル|用途|
|---|---|
|sofdec2enc.exe|Sofdec.Prime用|
|sofdec2encVP9.exe|VP9用|
|sofdec2encH264.exe|H.264用|
　
弊社ではモバイル向けにアプリケーション開発を行っているので、少なくとも3つのファイルを作成する必要があります。(Android / iOS / PC)
この3ファイルをポチポチと設定しようものなら、人的ミスがいつ発生するか分かりません。
 これはもう、<font color="red">バッチ</font>で自動化するしかないですね。

# 要件定義
ゴール： 各プラットフォーム向けの動画ファイルが、一括生成できるバッチファイルを作成する

## エンコードファイル
・動画解像度、圧縮設定、音声圧縮コーデックは同じパラメータ
・動画圧縮コーデックは、「PC」はSofdec.Primeとし、「Android, iOS」はH.264とする

## 書き出し先
・バッチファイルのあるディレクトリにエンコード前の動画ファイルを格納する
・「Destination」ディレクトリを作成し、エンコード後の動画ファイルを格納する
　そのディレクトリ以下は「PC」, 「iOS」, 「Android」のフォルダを作成し、
　エンコード後のファイルをそれぞれのプラットフォーム毎に格納する
・ファイル名は、エンコード前のファイル名をそのまま踏襲する
・エンコード実行ファイルは1階層上にあるものとする

# バッチファイルの作成
さぁ、バッチファイルを作成しましょう。
といっても、フォルダの作成などについては、「バッチファイルの作り方」でググればいくらでも出てくるため、本稿では割愛します。

それでは、エンコードをするためのコマンドについて、解説していきます。

## エンコードのコマンド
sofdec2encに渡す引数は結構複雑です。
しかし、<font color="red"> **その引数を簡単に導き出す方法** </font>があります。

先ほど紹介した、GUIでポチポチするだけのSofdec2EncWizで書き出すと、「ファイル名.usm」と「ファイル名.txt」が生成されます。
この「ファイル名.txt」に「Console Args」という項目があり、これがそのまま使用できます。

Console Argsを参照した結果、次のようなコマンドになりました。

```
Android
"sofdec2encH264.exe" -video00="YOUR_SOURCE_PATH.avi" -out="YOUR_DEST_PATH.usm" -bitrate=1074000 -target=android -h264_profile=main -hca -hca_quality=3 -audio00="YOUR_SOURCE_PATH.avi" -scale=288,576

iOS
"sofdec2encH264.exe" -video00="YOUR_SOURCE_PATH.avi" -out="YOUR_DEST_PATH.usm" -bitrate=1074000 -target=ios -h264_profile=main -hca -hca_quality=3 -audio00="YOUR_SOURCE_PATH.avi" -scale=288,576

PC
"sofdec2enc.exe" -video00="YOUR_SOURCE_PATH.avi" -scale=288,576 -hca -hca_quality=3 -audio00="YOUR_SOURCE_PATH.avi" -bitrate=2999000 -output="YOUR_DEST_PATH.usm" -work_dir="YOUR_SOURCE_FOLDER_PATH" -preview=OFF -gop_closed=on -gop_i=1 -gop_p=4 -gop_b=2 -gui_mode
```

コマンドの理解を補助するために、一部コマンドを解説しておきます。
ここに記載していないコマンドは、CRIのドキュメントを見て下さい。

### コマンド

#### エンコード指定
・H.264
```-h264_profile=main```

・VP9
マルチパスで複雑なので割愛
実際にSofdec2EncWizで書き出して確認してくださいませ。

・Sofdec.Prime
特に指定なし

#### video
エンコードする動画ファイルの格納場所
使用例： ```-video00="【SourceFilePath】"```

#### out
エンコード後の動画ファイルの格納場所
使用例： ```-out="【TargetFilePath】"```

#### bitrate
動画圧縮率の設定
使用例： ```-bitrate=1074000```

Sofdec2EncWizでの各設定値はこちら

<hr>・H.264

|圧縮設定|動画圧縮率|
|---|---|
|高圧縮|1074000 (bps)|
|高圧縮と標準の間|1611000 (bps)|
|標準|2148000 (bps)|
|標準と高品質の間|5101000 (bps)|
|高品質|8054000 (bps)|
<hr>・Sofdec.Prime

|圧縮設定|動画圧縮率|
|---|---|
|高圧縮|2999000 (bps)|
|高圧縮と標準の間|4498000 (bps)|
|標準|5997000 (bps)|
|標準と高品質の間|7996000 (bps)|
|高品質|9995000 (bps)|
<hr>・VP9

|圧縮設定|動画圧縮率|
|---|---|
|高圧縮|477000 (bps)|
|高圧縮と標準の間|716000 (bps)|
|標準|955000 (bps)|
|標準と高品質の間|1432000 (bps)|
|高品質|1909000 (bps)|

#### target
ターゲットプラットフォーム
使用例： ```-target=ios```

|プラットフォーム|指定文字列|
|---|---|
|Android|android|
|IOS|ios|
|PC(standard)|指定なし|

#### scale
リサイズ後の解像度
指定がない場合、リサイズしません
使用例： ```-scale=288,576```

#### hca
音声コーデックをhcaとします
指定がない場合はadxコーデックになります
使用例： ```-hca```

#### hca_quality
音声コーデックがhcsの際の圧縮率の設定です
使用例： ```-hca_quality=3```

|圧縮設定|指定数値|
|---|---|
|高圧縮|1|
|高圧縮と標準の間|2|
|標準|3|
|標準と高品質の間|4|
|高品質|5|

# バッチファイル全容
最終形はこのようになりました

```movie_converter.bat
@echo off
echo [%date% %time%] --- Encoding Start --- >> encoding_log.txt

rem 書き出す動画リストを作成 (必要な拡張子を追加すること)
dir /b *.avi > movie_source_list.txt
dir /b *.mp4 >> movie_source_list.txt

rem 空ファイルなら終了
for %%a in (movie_source_list.txt) do (
  if %%~za==0 (
    echo [%date% %time%] --- Error: Movie File Is Empty --- >> encoding_log.txt
    del movie_source_list.txt
    exit 0
  )
)

rem 格納先フォルダの作成
rd /s /q destination
md destination\android destination\ios destination\pc

rem エンコード開始 (エンコードパラメータを変更する場合はココ)
setlocal enabledelayedexpansion

for /f %%a in (movie_source_list.txt) do (
  set fileName=%%~na
  set fileExtension=%%~xa

  echo [%date% %time%] --- %%a Encode Start --- >> encoding_log.txt
  echo [%date% %time%] --- android encode --- >> encoding_log.txt
  "../sofdec2encH264.exe" -video00="!fileName!!fileExtension!" -out="destination/android/!fileName!.usm" -bitrate=1074000 -target=android -h264_profile=main -hca -hca_quality=3 -audio00="!fileName!!fileExtension!" -scale=288,576

  echo [%date% %time%] --- ios encode --- >> encoding_log.txt
  "../sofdec2encH264.exe" -video00="!fileName!!fileExtension!" -out="destination/ios/!fileName!.usm" -bitrate=1074000 -target=ios -h264_profile=main -hca -hca_quality=3 -audio00="!fileName!!fileExtension!" -scale=288,576

  echo [%date% %time%] --- pc encode --- >> encoding_log.txt
  "../sofdec2enc.exe" -video00="!fileName!!fileExtension!" -scale=288,576 -hca -hca_quality=3 -audio00="!fileName!!fileExtension!" -bitrate=2999000 -output="destination/pc/!fileName!.usm" -work_dir="%CD%" -preview=OFF -gop_closed=on -gop_i=1 -gop_p=4 -gop_b=2 -gui_mode
)

endlocal

rem 後処理
del movie_source_list.txt
echo [%date% %time%] --- Success! --- >> encoding_log.txt

pause
```

# 最後に
今年も無事、25日間完走することが出来ました。
私たちの発信によって、読んでくださった方の一助になる事が出来れば幸いです。

また、少しでもグレンジという企業に興味を持っていただければ是非、[ご応募下さい](https://www.grenge.co.jp/#/recruit)
発明が生まれる組織を一緒に作っていきましょう。

それでは、最後まで読んで頂き、ありがとうございました。
皆さん、良い年をお迎えください。

# 追記
2019/11/30
hcaの表記が逆だという指摘を頂いたので修正致しました