Google Cloudバッチ(Batch)を使ってみる

## Batchとは
2022年7月14日、Google Cloudにバッチ処理のための新サービス、名前はそのまんま「バッチ(Batch)」がリリースされました。記事の投稿時点ではプレビュー版の扱いとなっています。

https://cloud.google.com/blog/ja/products/compute/new-batch-service-processes-batch-jobs-on-google-cloud

## どういう場合に使えそうか
動画のエンコーディングなど…
* １ファイルにつきそこそこ重くて時間がかかる処理 
* 大量のファイルを処理する

場合に威力を発揮しそうです。Compute EngineのVMインスタンスで1台で処理すると、36時間かかって終了するバッチ処理があったとします。Batchなら1から最大1000! までのタスクが並走(parallel)します。

![スクリーンショット 2022-08-11 14.13.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661777/69e81639-cf4a-e6d1-caa3-113801752af9.png)

> Pricing
> There is no charge for the Batch service. You will only pay for the Google  Cloud resources used to execute your batch jobs.
> https://cloud.google.com/batch/docs/get-started

バッチのサービス自体に課金はなく、バッチ処理にあたったリソースの稼働時間で決定されます。他のGCSのサービスと同様にマシーンのスペックによって時間あたりの金額が変わってきます。


## MP4のエンコーディング
それでは、オフィシャルのチュートリアルに従って、mp4からwebmへのエンコーディングを試してみましょう。

https://github.com/GoogleCloudPlatform/batch-samples/tree/main/transcoding

まずはgithubからレポジトリをcloneします。
```
git clone https://github.com/GoogleCloudPlatform/batch-samples.git
cd batch-samples/transcoding/
```

以下のディレクトリ構成になっています。
```
transcoding/
├── transcode.sh
├── job.json
└── input/
    ├── video-0.mp4
    ├── video-1.mp4
    └── video-2.mp4
```

`job.json`の`script`に記述された内容がタスクとして`taskCount`の数だけ実行されます。その他job.jsonには、使用するマシーンタイプ、GCSバケットをマウントするディレクトリなど各種設定を書くことができます。詳細は、記事の下部でまとめます。

```json:job.json
"script": {
    "text": "bash /mnt/share/transcode.sh"
}
```
```json:job.json
"taskCount": 3,
```



さて、`job.json`が実行している`transcode.sh`は以下の通り。

```sh:transcode.sh
infile=$dir/input/video-$BATCH_TASK_INDEX.mp4
outfile=$dir/output/video-$BATCH_TASK_INDEX.webm
...........
ffmpeg -i $infile $vopts -an $outfile
```
`BATCH_TASK_INDEX`は、0から始まり、タスクが実行されるたびに`taskCount`(=タスクの総数)までカウントアップしていきます。その結果、video-0.mp4、video-1.mp4、video-2.mp4と次々にエンコード処理が走ります。

### 実行

それでは、処理内容がわかったところで実際に試してみます。
必要であれば実験用に新しいprojectを作成しましょう。
```
gcloud projects create [PROJECT_ID]
gcloud config set project [PROJECT_ID]
```

バッチAPIを有効化します。
```
gcloud services enable batch.googleapis.com
```

CloudStorageにバケットを作成して、`transcode.sh`と`input`ディレクトリをバケットにコピーします。

```
gsutil mb -p [PROJECT_ID] -b on -l US gs://[BUCKET_NAME]
gsutil cp -R transcode.sh input gs://[BUCKET_NAME]
```

job.jsonの`remotePath`を作成したバケット名に変更します。
```json:job.json
        "volumes": [
          {
            "gcs": {
              "remotePath": "[BUCKET_NAME]"
            },
            "mountPath": "/mnt/share"
          }
        ],
```

準備ができたらsubmitしましょう。現時点でバッチが対応しているリージョンは、us-central1,us-east1, us-west1, europe-north1の4つです。

```
gcloud beta batch jobs submit transcode --location=us-central1 --config=job.json
```

コンソールから確認すると以下のようにバッチ処理がスケジュールされたたことが確認できます。しばらくすると処理が始まり、変換後のwebmは、`gs://[BUCKET_NAME]/output`に出力されます。

![スクリーンショット 2022-08-15 18.10.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661777/2211e96f-2345-648e-b46b-fa034fc04330.png)

なおサンプルスクリプトは複数回実行すると、ffmepegがoutputを上書きできず失敗します。job.jsonを変えながら試したい場合は、出力されたwebmを削除してから再度実行するようにしましょう。`gsutil rm gs://[BUCKET_NAME]/output/*`

### job.jsonまとめ

__remotePath__
マウントするバケット名
"[BUCKET_NAME]"を 環境に合わせて書き換える

__machineType__
マシーンのスペック
例:n2d-standard-4

__provisioningModel__
SPOT or STANDARD

__text__
Batchによって実行されるコマンド
例："bash /mnt/share/transcode.sh"

__taskCount__
一回のjobで実行されるタスクの総数

__parallelism__
並列処理の最大数



## このままでは…
* 変換対象のファイル名に`$BATCH_TASK_INDEX`に相当する連番が必要
* タスクの総数は、job.jsonの`task_count`を書き換える

都度書き換えるのは面倒なので、次回「バッチでPDFを圧縮してみる」編で、サンプルのスクリプトをアップデートして使いやすくしてみます。

(以下に続きを書きました。)

https://qiita.com/kuromiya123/items/aa10d7eed1deeee6b9ef