🖼️

VoTTでプロジェクト、アセットの保存パスを変更してもロードできるようにするコードを作った話

2021/12/19に公開

VoTT(Visual Object Tagging Tool)では、プロジェクトファイル(*.vott)、アセット管理ファイル(*-assets.json)、アセット(動画 or 画像)などのパスを変更するとロードできなくなります。

これは以下の2点が原因です。

  1. アセットに関する情報(アセットのIDなど)が絶対パスに依存している
  2. ローカルファイルシステム設定の場合、ソース接続、ターゲット接続が絶対パスで保存されている

この問題を直すため、プロジェクトファイルおよびアセット管理ファイルを修正するコードを作りました。ファイル構造について注釈しつつ、実装内容を共有いたします。


updates

※ 2021.12.31 ブラウザ動作版を用意しましたので、記事を更新しました。
2021.12.07頃、アノテーションツールのVoTTがarchiveになりました
😢引き続きVoTTお使いの方向けに、本記事を残しています。


vott-replace-paths-web: VoTTファイルパス修正ツール(Web版)

https://niccari.net/vott-replace-paths/ に公開しています。ツールを実行すると、変換後のプロジェクトファイル(*.vott)およびアセット管理ファイル(*-assets.json)をzipファイルでダウンロードできます。なお、入力されたデータおよび変換結果はブラウザ上でのみ処理され、他者に公開されません。

本ツールのソースコードについては、GitHubのNiccari/vott-replace-paths-webリポジトリ上にあります。

処理の流れ

大まかな処理の流れは以下の通りです。

  1. アセットに関する情報を書き換え
    1.1. 変更前のアセットIDと変更後のアセットIDのマッピング
    1.2. アセットのid, name, path書き換え
  2. ソース接続/ターゲット接続情報の書き換え
  3. ファイルのリネーム、zipファイルに圧縮して保存

プロジェクトファイルおよびアセット管理ファイルにおいて、複数箇所で同じアセットIDが使われることがあります。そのため、1.1.で変更前のアセットIDと変更後のアセットIDの対応関係をマッピングしています。

1.2.では、後述の内部構成に基づいてプロジェクトおよびアセット管理ファイルの書き換えを行います。

2.では、ソース接続/ターゲット接続情報を書き換えます。こちらも後述の内部構造に基づき、移動後の絶対パスもしくはAzure Blob Storageへの接続情報(アカウント名・アカウント名・SAS文字列)を暗号化して保存しています。

最後に、アセット管理ファイルを(アセットID)-asset.json、プロジェクトファイルを*.vottに書き込みます。それらファイルをzipファイルに圧縮して自動ダウンロードします。


内部構造について

プロジェクトファイル(*.vott)

プロジェクトの設定情報とアセットに関する情報から構成されます。

下記json例のうち、assetsがアセットに関する情報、それ以外がプロジェクトの設定情報です(本件に関連しないものは省略しています)。

{
    "name": "プロジェクト名",
    "securityToken": "セキュリティトークン名",
    "sourceConnection": {
        "name": "ソース接続名",
        "providerType": "localFileSystemProxy""azureBlobStorage",
        "providerOptions": {
            "encrypted": "暗号化済み接続情報",
        },
        "id": "ソース接続ID"
    },
    "targetConnection": {
        "name": "ターゲット接続名",
        "providerType": "localFileSystemProxy""azureBlobStorage",
        "providerOptions": {
            "encrypted": "暗号化済み接続情報",
        },
        "id": "ターゲット接続ID"
    },
    "lastVisitedAssetId": "最後に閲覧したアセットID",
    "assets": {
        "アセットID1": {
            "id": "アセットID1",
            "name": "アセットのファイル名",
            "path": "アセットの絶対パス等",
            "type": 2,
        },
        "アセットID2": {
            "id": "アセットID2",
            "name": "アセットのファイル名#t=1.2",
            "path": "アセットの絶対パス等#t=1.2",
            "type": 3,
            "parent": {
                "id": "アセットID1",
                "name": "アセットID1のnameと同じ",
                "path": "アセットID1のpathと同じ",
                "type": アセットID1のtypeと同じ,
            },
            "timestamp": 1.2
        },
        ...
    }
}

このうち、書き換えが必要なのは以下のパラメータです。

  • sourceConnectionのproviderType: 保存先がローカルファイルシステム/Azure Blob Storage/Bing画像検索(本ツールでは未サポート)のうちどれか?
  • sourceConnectionのproviderOptions: 暗号化された接続情報(json形式)がencryptedに入っている。base64でエンコードされており、ciphertextが実データ、ivがAES-CBCの初期化ベクトルになっている。
    • ローカルファイルシステムの場合、保存フォルダパス(folderPath)が入る
    • Azure Blob Storageの場合、アカウント名(accountName)・コンテナ名(containerName)・SAS文字列(sas)が入る
  • lastVisitedAssetId: 最後に閲覧したアセットID
  • assetsのアセットID(id), アセット名(name), アセットの保存パス(path)
    • アセットID, idは移動後アセットの絶対パスから計算したsha256ハッシュ値
    • nameは以下2パターン
      • type=1(画像)か2(動画)の場合
        • ローカルファイルシステムの場合: アセットのファイル名(e.g. video1234.mp4)
        • Azure Blob Storageの場合: アセットのファイル名+SAS文字列(e.g. video1234.mp4?sv=...)
      • type=3(動画上のフレーム)の場合
        • ローカルファイルシステムの場合: アセットのファイル名#t=特定時刻(e.g. video1234.mp4#t=1.2)
        • Azure Blob Storageの場合: アセットのファイル名+SAS文字列#t=特定時刻(e.g. video1234.mp4?sv=...#t=1.2)
    • pathは以下2パターン
      • type=1か2の場合
        • ローカルファイルシステムの場合: アセットの絶対パス(e.g. file:/path/to/video1234.mp4)
        • Azure Blob Storageの場合: URL(e.g. https://(account_name).blob.core.windows.net/(container_name)/video1234.mp4?sv=...)
      • type=3(動画上)の場合
        • ローカルファイルシステムの場合: アセットの絶対パス#t=フレームのタイムスタンプ秒(e.g. file:/path/to/video1234.mp4#t=1.2)
        • Azure Blob Storageの場合: URL#t=フレームのタイムスタンプ秒(e.g. https://(account_name).blob.core.windows.net/(container_name)/video1234.mp4?sv=...#t=1.2)

アセット管理ファイル(*-assets.json)

アセットに関する情報およびバージョン情報などからなります。このうち書き換えが必要なのはassetのid, name, pathで、書き換えルールはプロジェクトファイル(*.vott)と同じです。

1. type=1(画像)およびtype=2(動画)の場合

{
    "asset": {
        "id": "アセットID1",
        "name": "アセットのファイル名",
        "path": "アセットの絶対パス等",
        "type": 2,
    },
}

2. type=3(動画上のフレーム)の場合

{
    "asset": {
        "id": "アセットID2",
        "name": "アセットのファイル名#t=フレームのタイムスタンプ秒",
        "path": "アセットの絶対パス等#t=フレームのタイムスタンプ秒",
        "type": 3,
        "parent": {
            "id": "アセットID1",
            "name": "アセットID1のnameと同じ",
            "path": "アセットID1のpathと同じ",
            "type": アセットID1のtypeと同じ,
        },
        "timestamp": 1.2
    }
}

Appendix: Pythonによる変更ツールについて

(2021.12.19の初版ではPython上で動作するツールを展開していましたので、利用説明について以下に残します。)

vott-replace-paths: VoTTファイルパス修正ツール

変換コードはGitHubのNiccari/vott-replace-pathsリポジトリ上にあります。ツール実行後、変換後のプロジェクトファイル(*.vott)およびアセット管理ファイル(*-assets.json)はoutput/下に保存されます。元ファイルをバックアップとして残しておくためです。

プロジェクトがAzure Blob Storage※およびローカルファイルシステムのどちらを使うかによって、実行方法が異なります。なお、いずれの場合でもターミナル上で以下のパラメータの指定が必要です。

-k: プロジェクトのセキュリティトークン。VoTTプロジェクトで設定した値を指定する。
-t: プロジェクトの保存パス。プロジェクトファイル(*.vott)があるパスを指定する。

※ Azure Blob Storageを利用している場合、一度各種ファイルをローカルファイルシステムにダウンロードしてからツールをご利用ください。

ローカルファイルシステム上の保存パスを変更する場合

以下の通りパラメータを指定ください。

$ python main.py \
    -k プロジェクトのセキュリティトークン \
    -s ソース接続におけるアセットの保存パス \
    -t ターゲット接続におけるプロジェクトの保存パス

Azure Blob Storage上のコンテナに移動させる場合

以下の通りパラメータを指定ください。

$ python main.py \
    -k プロジェクトのセキュリティトークン \
    -t プロジェクトの保存パス \
    -a Azure Blob Storageのアカウント名 \
    -c Azure Blob Storageのコンテナ名 \
    -sas コンテナアクセス用のSAS文字列

処理の流れ

大まかな処理の流れは以下の通りです。

  1. アセットに関する情報を書き換え
    1.1. 変更前のアセットIDと変更後のアセットIDのマッピング
    1.2. アセット管理ファイルの名前変更
    1.3. アセットのid, name, path書き換え
  2. ソース接続/ターゲット接続情報の書き換え

プロジェクトファイルおよびアセット管理ファイルにおいては、複数箇所で同じアセットIDが使われることがあります。そのため、1.1.で変更前のアセットIDおよび変更後のアセットIDをマッピングしています。

1.2.では、アセット管理ファイル名自身にアセットIDが含まれているため、これを更新しています。

1.3.では、前述の内部構成に基づいてプロジェクトおよびアセット管理ファイルの書き換えを行います。

最後に、ソース接続/ターゲット接続情報を書き換えます。こちらも前述の内部構造に基づき、移動後の絶対パスもしくはAzure Blob Storageへの接続情報(アカウント名・アカウント名・SAS文字列)を暗号化して保存しています。

Discussion