AI動画解析サービスを試してみる 2

[前回](https://qiita.com/TechSavvy_24/items/62da90a5f126b4775fcc)の[Amazon Rekognition Video](https://aws.amazon.com/jp/rekognition)に引き続き、AI動画解析サービスを試してみるの2回目です。

今回は Googleの[Video AI(Video Intelligence API)](https://cloud.google.com/video-intelligence?hl=ja)を使うまでの設定とPythonスクリプトを使用した解析を実行して結果を取得し、JSONで保存してみます。

## Video AI(Video Intelligence API)とは？

詳しくは公式Webサイトを見ていただくのが一番ですが、簡単に言えばローカルにあるファイルやGoogle Cloud Storageに保存してある画像や動画に対して顔検出、テキスト検出、ラベル検出などの解析が行えるサービスです。

検出について細かいカスタマイズはできませんが、手元に解析するハード・ソフト含めた環境や知識がない場合でも手軽にAI動画解析を試すことができます。

https://cloud.google.com/video-intelligence


## アカウント設定の手順について

基本的には下記のURLの手順に沿って進めれば準備が完了します。特に難しいところはありませんでしたが、無料クレジットを使用するのにもクレジットカードの登録が必須のようでした。
Pythonのスクリプトで解析の実行と結果の取得をしたいのでPython用のSDKが動くところまでの設定をします。

アカウント設定の参考ページ：  
https://cloud.google.com/video-intelligence/docs/common/auth?hl=ja

上記手順の途中に追加で[Cloud Storage](https://cloud.google.com/storage?hl=ja)に保存したファイルを読み取る権限の設定を行います。

### 1. プロジェクトの作成

* [プロジェクト セレクタ][link-proj-sele]ページ から使用できるプロジェクトがある場合は既存のプロジェクトを選択し、なければ「プロジェクトの選択」をクリックし新しいプロジェクトを作成します
  ![ユーザー作成画面の画像1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/9687b8bf-0988-a3db-ba8d-451662953533.png "ユーザー作成1")
* 次に 「新しいプロジェクト」をクリック
  ![ユーザー作成画面の画像2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/1f3bfe7f-e5f4-4a1b-268a-4219c02df9b2.png "ユーザー作成2")
* プロジェクト名を入力します  
  今回は「ai-test」というユーザー名で進めます  
  名前を入力したら「作成」をクリックしてプロジェクトを作成します。
  ![ユーザー作成画面の画像3](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/7383e112-575e-9d3c-2a29-2cda589fbc8f.png "ユーザー作成3")

### 2. Google Cloundプロジェクトの課金設定の確認

これは次のステップにまとめて確認できます。

### 3. Cloud Video Intelligence APIの有効化

* APIの有効化ページの表示  
  [APIの有効化][link-ena-api]ページで、ステップ1で選択または作成したプロジェクトに対する変更であることを確認して「次へ」をクリック
  ![API有効化の画像1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/9c11121d-d0d8-e3b7-7596-b167124e1fe9.png "API有効化1")  
  もしプロジェクトが異なる場合は、
  ![API有効化の画像2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/9687b8bf-0988-a3db-ba8d-451662953533.png "API有効化2")  
   上記画像の「プロジェクトの選択」の部分が異なるプロジェクトになっているので正しいプロジェクトを選択した上で、 [APIの有効化][link-ena-api]ページを表示してください
* 請求先アカウント  
  「課金を有効化」をクリックして課金されるアカウントの設定を行ってください
  ![API有効化の画像3](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/a86e3dfa-9ba4-e74b-b0de-988f337cdc96.png "API有効化3")
* APIを有効化  
  「有効にする」をクリックしてAPIの有効化の完了です
  ![API有効化の画像4](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/b9446850-3ee7-5e59-0e2f-6c8bd8383c59.png "API有効化4")

### 4. サービスアカウントの作成

* サービスアカウントを作成するプロジェクトの選択  
  [サービスアカウントの作成][link-srv-act]ページで、ステップ1で選択または作成したプロジェクトをクリック
  ![サービスアカウントの作成画像1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/03591fb2-b43c-ef07-064f-18c2612ca51f.png "サービスアカウントの作成1")  
* サービスアカウントを作成  
  「サービス アカウント名」にアカウント名を入力します。  
   サービスアカウント名も「ai-test」として進めます  
  「サービス アカウントID」は自動で入力されますので、それをそのまま使用します  
  「作成して続行」をクリックして次のステップに進みます
  ![サービスアカウントの作成画像2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/b14ef978-a847-b0b9-deb3-cffe96298bbb.png "サービスアカウントの作成2")  
* サービスアカウントにCloud Storageの権限を追加  
  * 「ロールを選択」をクリックします
    ![サービスアカウントの作成画像3](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/5e21bbb3-3452-278d-ee02-7927906d631f.png "サービスアカウントの作成3")  
  * 「フィルタ」に Storage を入力し 「Storageオブジェクト閲覧者」を選択します
    ![サービスアカウントの作成画像4](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/d26ce4e3-be2b-0785-53ca-d9c18c3245f5.png "サービスアカウントの作成4")  
  * 「Storage オブジェクト閲覧者」が選択されていることを確認し  
     「続行」をクリックします
    ![サービスアカウントの作成画像5](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/aab390d9-ff84-5786-e33f-63b2fc13954a.png "サービスアカウントの作成5")
  * 「完了」をクリックしてサービスアカウントの作成を完了します
    ![サービスアカウントの作成画像6](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/02a4d79e-de96-6688-54fd-2c6bb133af41.png "サービスアカウントの作成6")

### 5. サービスアカウントのキーを作成します

* サービスアカウントの一覧からサービスアカウントの「操作」カラムの縦点線のメニューをクリックし「鍵を管理」をクリック
  ![サービスアカウントの作成画像7](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/638334e5-643d-8b83-2fb6-36b5911b4c75.png "サービスアカウントの作成7")  
* 「鍵を追加」をクリック
  ![サービスアカウントの作成画像8](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/09b71dd0-91aa-5e76-fad4-7dfa57f141d4.png "サービスアカウントの作成8")  
* 「キーのタイプ」で「JSON」を選択し「作成」をクリック
  ![サービスアカウントの作成画像9](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/3849ba1b-262e-c1c8-be4e-9e11b07d1904.png "サービスアカウントの作成9")  
* 次の画面でキーがダウンロードされます
  ![サービスアカウントの作成画像10](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791092/af1ae21b-ce4d-43cf-0c8e-0593f176e230.png "サービスアカウントの作成10")  

### 6. 環境変数の設定
* 各プラットフォームで「GOOGLE_APPLICATION_CREDENTIALS」という環境変数にステップ5で作成したJSONのパスを指定してください
  * Linux の場合  
    `export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-file.json"` 
  * Windows コマンドプロンプトの場合  
    `set GOOGLE_APPLICATION_CREDENTIALS=C:\path\to\service-account-file.json` 
  * Windows PowerShellの場合  
    `$env:GOOGLE_APPLICATION_CREDENTIALS="C:\path\to\service-account-file.json"` 

### 7. Google Cloud CLIのインストール

* [Google Cloud CLI][link-cli-dl]のページで各プラットフォーム用のバイナリをインストールしてください
### 8. Google Cloud CLIの初期化

下記のコマンドを実行し初期化を行います

```shell
gcloud init
```

## ラベル解析の実行

Cloud Storageにアップロードした動画ファイルに対して、ラベル解析を行うPythonスクリプトについて解説します。

[前回](https://qiita.com/TechSavvy_24/items/62da90a5f126b4775fcc)行った[Amazon Rekognition Video](http://qiita.comhttps://aws.amazon.com/jp/rekognition)のラベル解析内で行っていたオブジェクトの認識と同等の解析は、Video Inteligence APIではオブジェクト追跡(オブジェクトトラッキング)となります。

### Cloud Storageに動画ファイルのアップロード

事前にCloud Storageにバケットを作成し、解析に使用する動画をアップロードしておきます。

参考: https://cloud.google.com/storage/docs/discover-object-storage-console?hl=ja

### Python スクリプト

ここでは複数ある解析の種類からラベルの検出をして、その結果をJSONとしてファイルに保存します。

Video Intelligence APIで動画の解析の結果は、Protbuf形式となるためPythonの辞書形式を経由してJSONに変換しています。
すべての結果は、1つのファイルにすべて保存されます。

JSONで保存しているのは、今後のスクリプトでJSONであった方が都合が良いためなので本来はどんな形式でも構いません。


#### 設定項目

スクリプトファイルの下部にあるmain関数にユーザーと解析対象となる動画ファイルに関する設定項目があります。

* `<uri>`  
   Cloud Storageに保存した動画の `gs://～` から始まるgsutil URIを指定します

#### 出力結果 (例)

```
$ ./run-detection.py
$ ./video-ai.py
Start object detection.
.........................
ai-test.mp4-object-all.json
Finished processing.
```

#### スクリプト全体

```python
import sys
import asyncio
import json
from google.cloud import videointelligence_v1 as videointelligence

class VideoAI:
    def __init__(self, uri):
        self.uri = uri
        self.video = self.SimpleBasename(self.uri)
        self.jobtype = 'object'
        self.model = 'builtin/latest'

    def ReturnNoneObj(x):
        return None

    def SimpleBasename(self, path):
        i = path.rfind('/') + 1
        return path[i:]

    def WriteJsonFile(self, name, data):
        print(name)
        with open(name, mode='wt', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)

    async def StartDetection(self):
        dotLine = 0
        task = asyncio.create_task(self.RunDetection())
        while task.done() == False:
            await asyncio.sleep(3)
            if dotLine < 40:
                print('.', end='')
                dotLine = dotLine + 1
            else:
                print()
                dotLine = 0
            sys.stdout.flush()
            continue
        print()

        result = await task
        json_name = '{}-{}-all.json'.format(self.video, self.jobtype)
        self.WriteJsonFile(json_name, result)

        print('Finished processing.\n')

    async def RunDetection(self):
        client = videointelligence.VideoIntelligenceServiceAsyncClient()

        context = videointelligence.types.VideoContext(
                object_tracking_config = videointelligence.types.ObjectTrackingConfig(model=self.model),
                )

        operation = await client.annotate_video(
            request={
                'features': [videointelligence.Feature.OBJECT_TRACKING],
                'input_uri': self.uri,
                'video_context': context,
            }
        )

        print('Start {} detection.'.format(self.jobtype))
        result = await operation.result()

        dictdata = type(result).to_dict(result)

        return dictdata

def main():
    uri = '<cloud-storage-uri>'
    uri = 'gs://db-test-videofiles/ar-sample.mp4'

    analyzer = VideoAI(uri)
    asyncio.run(analyzer.StartDetection())

if __name__ == '__main__':
    main()
```

[link-proj-sele]: https://console.cloud.google.com/projectselector2/home/dashboard?hl=ja
[link-ena-api]: https://console.cloud.google.com/flows/enableapi?apiid=videointelligence.googleapis.com&hl=ja
[link-srv-act]: https://console.cloud.google.com/projectselector/iam-admin/serviceaccounts/create?supportedpurview=project&hl=ja
[link-cli-dl]: https://cloud.google.com/sdk/docs/install?hl=ja