VoTTのファイルを引っ越す方法を考える
VoTTでアノーテーション付けたファイルは絶対パスを使っているので、ディレクトリを移動させると動かなくなるっぽい。せっかく修正が取り込まれているみたいだけど、リリースが無い。よく見ると本家のコミットが去年の11月から動いていないので、データの方を修正する方法を調べてみる。
ここの話はVoTTがv2.2.0であることを想定しています。
↓それっぽい修正
ターゲット接続で指定したディレクトリに出来るvott
の拡張子を持ったファイル。上書き保存しても、プロジェクトを開くと元に戻る。
こんな感じでやれば、一応、引っ越せる。
- 引っ越し先をターゲット、ソースにしてプロジェクトをvottを使って作る
- 元の場所にいた
<id>-asset.json
を1. で作ったidに合わせてターゲットディレクトリにコピーする
各画像に対するidは、以下のようにmd5で生成している。
import MD5 from "md5.js"
console.log(new MD5().update("file:/path/to/img.png").digest("hex"));//=> 66f4274a78d046eea54cee35b91e934d
xxxx-asset.json
のxxxx
の部分とそのファイルのid
キーの値にする。パスを変えたとき、変える必要があるのはこの部分と.vott
ファイルのassets
くらい。
.vott
ファイルで暗号化されている情報があって、セキュリティトークンで復号化できる。crypto-js
で暗号化されているので、復号化はこれを使えば、何も考えなくても出来る。
↓参照
activeLearningSettings
は暗号化されていないのに、exportFormat
が暗号化されているのが不便。sourceConnection
とtargetConnection
でパスが暗号化されているのは分かるけども。
(後から分かりましたが、VoTTで使われているiv
が24byteなのでgoのcrypto/aes
で復号化しようとしてもブロックサイズが合わなくて出来てない(ブロックサイズは16で固定)。iv
は24byteだけれども暗号化、復号化で使われているのは先頭の16byteまでなのでGoの標準ライブラリで対応可能)
import c from "crypto-js"
const AES = c.AES
const enc = c.enc
const lib = c.lib
function decrypt(encodedMessage, secret) {
const secretBytes = enc.Base64.parse(secret);
const json = enc.Base64.parse(encodedMessage).toString(enc.Utf8);
const params = JSON.parse(json);
const iv = enc.Hex.parse(params.iv);
const cipherParams = lib.CipherParams.create({
ciphertext: enc.Hex.parse(params.ciphertext),
iv: enc.Hex.parse(params.iv),
});
const decrypted = AES.decrypt(cipherParams, secretBytes, { iv });
return decrypted.toString(enc.Utf8);
}
const secret = "secret_key";
//"sourceConnection"."providerOptions"."encrypted"
const encodedMessage1 = "xxx";
console.log(decrypt(encodedMessage1, secret)) //=> {"folderPath":"/path/to/src"}
//"targetConnection"."providerOptions"."encrypted"
const encodedMessage2 = "yyy";
console.log(decrypt(encodedMessage2, secret))// => {"folderPath":"/path/to/dist"}
//"exportFormat"."providerOptions"
const encodedMessage3 = "zzz";
console.log(decrypt(encodedMessage3, secret))//=> {"assetState":"visited","includeImages":true}
セキュリティトークンの確認の仕方
- ホームで歯車をクリック
- セキュリティトークン一覧が出るのでコピー(キーは"<プロジェクト名> Token"になる)
goで各jsonを読み込むのに使った構造体を公開しておきます(分かりきった内容なのに書くと手が疲れるので)。
こちらは.vott
ファイル用
type fileConnection struct {
Name string `json:"name"`
ProviderType string `json:"providerType"`
ProviderOptions providerOptions `json:"providerOptions"`
ID string `json:"id"`
}
type asset struct {
Format string `json:"format"`
ID string `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
Size struct {
Width int `json:"width"`
Height int `json:"height"`
} `json:"size"`
State int `json:"state"`
Type int `json:"type"`
}
type vottFile struct {
Name string `json:"name"`
SecurityToken string `json:"securityToken"`
SourceConnection fileConnection `json:"sourceConnection"`
TargetConnection fileConnection `json:"targetConnection"`
VideoSettings struct {
FrameExtractionRate int `json:"frameExtractionRate"`
} `json:"videoSettings"`
Tags []struct {
Name string `json:"name"`
Color string `json:"color"`
} `json:"tags"`
ID string `json:"id"`
ActiveLearningSettings struct {
AutoDetect bool `json:"autoDetect"`
PredictTag bool `json:"predictTag"`
ModelPathType string `json:"modelPathType"`
} `json:"activeLearningSettings"`
ExportFormat struct {
ProviderType string `json:"providerType"`
ProviderOptions providerOptions `json:"providerOptions"`
} `json:"exportFormat"`
Version string `json:"version"`
LastVisitedAssetId string `json:"lastVisitedAssetId"`
Assets map[string]asset `json:"assets"`
}
こちらは*-asset.json
用
type assetFile struct {
Asset asset `json:"asset"`
Regions []struct {
ID string `json:"id"`
Type string `json:"type"`
Tags []string `json:"tags"`
BoundingBox struct {
Height float64 `json:"height"`
Width float64 `json:"width"`
Left float64 `json:"left"`
Top float64 `json:"top"`
} `json:"boundingBox"`
Points []struct {
X float64 `json:"x"`
Y float64 `json:"y"`
} `json:"points"`
} `json:"regions"`
Version string `json:"version"`
}
nodeを使えば、セキュリティトークンを渡せばエクスポートの設定まで引っ越せる事がわかった。
Goで復号化する場合は次のリンクが参考になる。
セキュリティトークンを次のコードで生成して使えるか試してみた。一応、使えるみたい。
func generateRandomKey(length int) (string, error) {
k := make([]byte, length)
if _, err := io.ReadFull(rand.Reader, k); err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(k), nil
}
セキュリティトークンの数を減らしたくて、途中で設定変えて大丈夫か確認。
とりあえずOKみたい。
vottファイル読み込んだときに、未登録の接続があれば自動で新規登録されるのか。
次のように実行するとtargetオプションで指定した場所に修正したものが出来るようになった。
go run . -target /path/to/project -src /path/to/file.vott -src-key base64_encoded_security_token
あとはアプリにセキュリティトークンのキーとバリューを設定して、ローカルプロジェクトを開く
から生成したvottファイルを選択するとロードされる。
今の所images
に画像をtarget
にvottファイルと*-asset.json
をなどを置くという決め打ちになっている。
project
├── images
└── target
macOSとwindowsで動くのを確認
セキュリティトークンとコマンドラインで渡すとhistoryに残るので止めよう。パスワードモードで入力受け付けるのと、ファイルから読み込む方法の両方をサポートすることにした。
改めてコマンドを考え直してみたい。だいたいこんな感じのことできたら嬉しいかな
-
go fix
みたいに壊れたファイルを上書きして直す - 壊れたファイルを参照しながら、別に直したのを生成する
- ターゲット接続または画像ソース接続だけ移動させる
- 指定した場所に含む全てのプロジェクトを直す(その都度セキュリティトークン入力求める?)
上書きするスタイルに変更して、公開。target
オプションでvott
ファイルがあるディレクトリを指定する(オプション指定じゃなくて良いなぁ)。
vott-fix -target /path/to/target
アクセストークンが聞かれるのでコピペで変換完了。アクセストークンはアプリに登録されてないと、開くときエラーになる。変換後、ローカルプロジェクトを開くで.vott
ファイルを選択。