チュートリアル / Shotgunスクリプト入門
第1回:ファイルアップローダーを作ってみよう
- Flow Production Tracking
- コラム
- スクリプト・API
- スマイルテクノロジーユナイテッド
- チュートリアル
- 上級者
- 中級者
はじめに
皆さん初めまして。スマイルテクノロジーユナイテッド株式会社(以下、STU)でテクニカルアーティストを務める榎本と申します。STU は、7割強がテクニカルアーティストを占める技術者の集団です。
この度、Shotgun 向けおよび Shotgun と他サービスとの連携を行うツールの開発経験を基に、コラムを執筆させていただくことになりました。よろしくお願いします。
このコラムは、Python を使って Shotgun のカスタマイズをしたいけれど、はじめの一歩が踏み出せないという方の後押しをするためのものです。題材としては、ローカルフォルダから Shotgun プロジェクトへファイルを一括アップロードするファイルアップローダーの実装と機能追加を行っていきます。この連載を通じて、Shotgun での Python スクリプトに興味を持ってもらい、業務改善に役立てて頂けたら幸いです。
読み進めるにあたって必要な条件はできるだけ少なくし、都度説明を行っていきます。しかし、目安として下記の三つが理解できているという前提で進めていきます。不明点があれば、都度、参照して頂ければと思います。
前提知識の目安
● SHOTGUN チュートリアルビデオ Class 1 最初の一歩
● Python チュートリアルの 1~7 程度
● コマンドプロンプトの基本的な使い方
・cd, mkdir, set
以下に、作者が動作確認を行った開発環境を示します。テキストエディタまたは IDE(統合開発環境)については好みのもので構いませんが、JetBrains 社の PyCharm(*1) か、Microsoft 社の Visual Studio Code(*2) を推奨します。
開発環境
● OS
○ Windows 10
● Python 3.7(64bit)
○ py.exe(Python ランチャー)を含む
● テキストエディタまたは IDE(統合開発環境)
○ PyCharm
● コマンドプロンプト
*1 PyCharm
https://www.jetbrains.com/pycharm/
*2 Visual Studio Code
https://azure.microsoft.com/ja-jp/products/visual-studio-code/
1. ファイルアップローダーについて
Shotgun を使う現場では、プロジェクトを新たに開始するときなど、手元にある多くのファイルを一括でアップロードしたい場面が多々あります。もちろん、Shotgun へアップロードする際にはファイルを複数選択することは可能です。しかし、ファイル数があまりに多い場合は Web ブラウザの制限でアップロード作業が大変なときもあるでしょう。また、[説明] (Description) などのファイルに紐づく情報をファイルごとに個別で指定したい場合などは専用ツールとしてファイルアップローダーが欲しくなります。
今回実装するファイルアップローダーは、本体となる Python スクリプトとコマンドラインで実行するための BAT ファイルです。Python スクリプトでは Shotgun Software から提供されている Shotgun Python API3 を使用します。
2. Shotgunでの準備
まず、Python スクリプトから Shotgun へアクセスするために、スクリプトの登録を行い、API(*3) へアクセスするためのトークン(*4) を発行します。
次に、ファイルのアップロード先であるプロジェクトの ID を取得します。
*3 API: Application Programming Interface
アプリケーションとプログラムとの窓口のことです。このコラムでアプリケーションは Shotgun を指し、プログラムは今回作成する Python スクリプトを指します。
*4 トークン: ここでは、Python スクリプトのパスワードのことです。
2.1. APIトークンの発行
Shotgun のサイトへログインし、
① ユーザーのアイコンをクリックして
② 表示されるメニューの [管理者] (ADMIN) → [スクリプト] (Scripts) を選択します。
そうすると、登録されたスクリプト一覧の画面が表示されるので、「+ スクリプト」(+ Script)をクリックして新規作成をします。
Python から API にアクセスするにはスクリプト名(Script Name)と API トークン(Application Key)が必要です。今回は、ファイルアップローダーのスクリプト名を「myuploader」として登録します。
1. [スクリプト名] (Script Name) に「myuploader」を入力し、
2. [クリップボードにコピー] (Copy to Clipboard) をクリックして [アプリケーションキー] (Application Key) をコピーします。
API トークンの値はこの後確認できなくなりますので、分からなくならないようにテキストエディタなどで保存してください。(*5)
3. API トークンが保存できたら [スクリプトを作成] (Create Script) をクリックして登録を完了します。
※ API トークンはパスワードと同様に、GitHub の public リポジトリなどの外部へ公開された場所へ置かないようにしてください。
*5 トークンを取得し忘れた場合は、登録したスクリプトの [アプリケーションキー] (Application Key) フィールド内の [キーを変更] (Change Key) をクリックして新しいトークンを発行し、保存してください。
これでスクリプトが登録できました。
2.2. プロジェクトIDの取得
今回実装するファイルアップローダーは、アップロード先のプロジェクトを決めてそこにファイルをアプロードしていくので、対象プロジェクトを指定するために ID を取得しておく必要があります。Shotgun でプロジェクト ID を確認しましょう。
Shotgun サーバーの [プロジェクト] (Projects) のページで [リストビュー] (List View) を選択します。
そうするとプロジェクトのフィールドが表示されるので、その中の「Id」フィールドから対象プロジェクトの ID を確認します。この例では、「sandbox_enomoto」プロジェクトを対象とした場合、ID は90です。自分の環境の、対象とするプロジェクトの ID を確認しましょう。
Shotgun 側でのセットアップはこれで完了です。
3. Pythonの環境構築
続いて、Python の環境構築を行っていきます。
Python から Shotgun API へアクセスするためのモジュールである shotgun_api3 は、現状 Python 2 と Python 3 に対応しています。
Python の運営団体である Python Software Foundation によると、Python 2 は来年2020年1月1日でサポート終了とし(*6)、また、VFX 業界の標準である VFX Reference Platform の 2020年版である CY2020 でも、Python のバージョンが 3 へ移行します。(*7)
このような背景から、この連載では今後のことを考えて、Python 3 で環境構築を行っていくことにします。ここでは CY2020 に合わせて Python 3.7 をインストールしているものとします。作者は Python 3.7.4 (64bit)で動作確認をしています。
*6 Sunsetting Python 2: https://www.python.org/doc/sunset-python-2/
*7 VFX Reference Platform: https://vfxplatform.com/
3.1. ツールフォルダの準備
まず初めに、アップローダーツールのスクリプトなどを管理するためのフォルダを作成します。
myuploader フォルダを作成し、その中にスクリプトなどを作成していきます。
myuploader
├ cli.py
├ myuploader.bat
└ images
├ 001.png
├ 002.png
.
└ 100.png
Python スクリプトは cli.py に記述していきます。
それが完成したら、スクリプト起動用バッチファイル myuploader.bat を作成します。
images 以下にアップロード用のファイルを保存しているものとします。ここにはフォルダは含まないものとします。実行例では、images 以下に 001.png ~ 100.png の100個の画像ファイルを用意して実行しています。
3.2. venv の作成とshotgun_api3のインストール
次に、今回構築する環境が他の Python スクリプトへ影響を与えないようにするために、閉じた環境である venv(Virtual Environment: 仮想環境 の略)(*8)を作成し、その中に必要なモジュールをインストールしていきます。Windows のスタートメニューから「コマンドプロンプト」を起動し、下記のコマンドを入力して、venv_shotgun_scripting という venv を作成します。
cd %USERPROFILE%
mkdir .virtualenvs
cd .virtualenvs
py -3 -m venv venv_shotgun_scripting
ここでは、py.exe(*9) を使って Python 3 を呼び出し、venv コマンドを実行しています。
*8 venv の詳細については下記リンクを参照ください。
● Python チュートリアル 12. 仮想環境とパッケージ
https://docs.python.org/ja/3.7/tutorial/venv.html
● venv --- 仮想環境の作成
https://docs.python.org/ja/3.7/library/venv.html
*9 py.exe は Windows 用の Python ランチャーで、複数バージョンの Python をインストールしているときに、どのバージョンの Python を使うかを指定することができます。詳細は下記リンクを参照ください。
● 3.7. Windows の Python ランチャ
https://docs.python.org/ja/3.7/using/windows.html#python-launcher-for-windows
続いて、venv_shotgun_scripting に、Python から Shotgun API にアクセスするためのモジュールである shotgun_api3 をインストールします。下記のコマンドを入力してインストールします。
cd venv_shotgun_scripting
Scripts\activate.bat
python -m pip install git+https://github.com/shotgunsoftware/python-api.git
deactivate
仮想環境 venv_shotgun_scripting を有効にし、pip(*10) で shotgun_api3 をインストールします。ここでは、GitHub のリポジトリを直接指定してインストールしています。
*10 pip は Python の標準パッケージ管理ツールです。詳細は下記リンクを参照ください。
● Python モジュールのインストール
https://docs.python.org/ja/3.7/installing/index.html?highlight=wheel
4. ファイルアップローダーの実装
さあ、いよいよファイルアップローダーの実装に入っていきます。一つづつ説明を交えて実装していきたいと思います。今回実装するファイルアップローダーの仕様は、下記の通りです。
1. バッチファイルから実行します
2. 指定したフォルダ内の全てのファイルを指定したプロジェクトのバージョンへアップロードします
今回実装するのは最低限の機能のみですが、これをベースにして自分のプロジェクトに合った用途へとカスタマイズしていくことも可能です。それではやっていきましょう。
4.1. モジュールのインポートとmain関数の作成
まず初めに、スクリプトに必要なモジュールのインポートと、スクリプト実行の起点となる main 関数を書いていきます。
今回必要なモジュールは、os, sys, shotgun_api3 です。
import os
import sys
import shotgun_api3
main 関数と呼び出し部分を作成します。今回は、main 関数にすべての処理を書いていきます。
def main():
return 0
if __name__ == "__main__":
sys.exit(main())
4.2. フォルダの指定とShotgunインスタンスの作成
ここからは、main 関数の中身の実装に移ります。4.1. のdef main():
以下に記述していくものとします。
まずは、アップロードするファイルを保存しているフォルダを指定します。フォルダのパスは、絶対パスか、このスクリプトが保存されているフォルダからの相対パスとします。例えば、このスクリプトと同じフォルダ内の images フォルダを対象としたい場合は
target_dir = "images"
と書きます。
次に、Python スクリプトが Shotgun のサイトとやり取りを行うための Shotgun インスタンスを作成します。ここで、アップロード先の Shotgun サイトの URL と、「2. Shotgun での準備」で登録したスクリプトの名前とトークンを使います。
下記の url 変数の値の smiletechnologyunited を自分の Shotgun サイトに、api_key の fouetfj8uebo3bjflneghqorp(*11) を取得したトークンに置き換えます。
url = "https://smiletechnologyunited.shotgunstudio.com"
script_name = "myuploader"
api_key = "fouetfj8uebo3bjflneghqorp"
# Shotgunインスタンスの取得
shotgun = Shotgun(url, script_name=script_name, api_key=api_key)
*11 この API トークンはダミーです。くれぐれも有効なトークンを公開しないようにしてください。
4.3. アップロード先の指定
アップロード先のプロジェクトの情報もここで作成しておきます。まず、2.2. で確認したプロジェクト ID を変数 project_id にセットします。プロジェクトの情報は、キーにフィールドコードを持つ辞書として用意します。”type” にはエンティティタイプを(ここではプロジェクト)、”id” にはそのエンティティの ID を指定します。
続いて、対象プロジェクトのエンティティのどのフィールドにアップロードしたファイルのリンクを作成するか指定します。今回は、[バージョン] (Version) エンティティの [アップロードしたムービー] (sg_uploaded_movie) フィールドをファイルリンクとして指定します。
# 対象プロジェクト
project_id = 90
project = {"type": "Project", "id": project_id}
# 対象のエンティティをバージョン、ファイルへリンクするフィールドをsg_uploaded_movieとします
entity_type = "Version"
field_code = "sg_uploaded_movie"
4.4. ファイルアップロードとファイルリンクの作成
アップロードしたファイルへのリンクを作成するためのバージョンエンティティを作成します。新規作成の処理ではファイルをアップロードできない仕様となっているため、まずは最低限の情報であるバージョン名とプロジェクト情報を渡してバージョンエンティティを新規作成します。
新規作成が成功すると、作成時に渡した情報と合わせてバージョンエンティティの id が辞書の形で返ってきます。print 関数で受け取った情報を確認してみましょう。次のファイルアップロードの処理で使うため、返り値を変数 version で受け取っておきます。
ファイルをアップロードし、id を指定したバージョンの sg_uploaded_movie フィールドへファイルへのリンクを作成する処理を追加します。version 変数から id を取得し、upload メソッドの引数として渡します。
for _file in os.listdir(target_dir):
# ファイル名と同じ名前のバージョン名と、所属するプロジェクトの情報を持たせます
entity_data = {"code": _file, "project": project}
# バージョンエンティティを作成します
version = shotgun.create(entity_type, entity_data)
# versionにはどのようなデータが入っているでしょうか?
print(version)
# 作成したバージョンのidを取得します
version_id = version["id"]
file_path = os.path.join(target_dir, _file)
# ファイルをアップロードし、バージョンにファイルリンクを作成します
shotgun.upload(
entity_type,
version_id,
file_path,
field_name=field_code,
display_name=_file
)
これで一通り実装できました。
コードの全体像を以下に示します。
import os
import sys
from shotgun_api3 import Shotgun
def main():
target_dir = "images"
url = "https://smiletechnologyunited.shotgunstudio.com"
script_name = "myuploader"
api_key = "fouetfj8uebo3bjflneghqorp"
# Shotgunインスタンスの取得
shotgun = Shotgun(url, script_name=script_name, api_key=api_key)
# 対象プロジェクト
project_id = 90
project = {"type": "Project", "id": project_id}
# 対象のエンティティをバージョン、ファイルへリンクするフィールドをsg_uploaded_movieとします
entity_type = "Version"
field_code = "sg_uploaded_movie"
for _file in os.listdir(target_dir):
# ファイル名と同じ名前のバージョン名と、所属するプロジェクトの情報を持たせます
entity_data = {"code": _file, "project": project}
# バージョンエンティティを作成します
version = shotgun.create(entity_type, entity_data)
# versionにはどのようなデータが入っているでしょうか?
print(version)
# 作成したバージョンのidを取得します
version_id = version["id"]
file_path = os.path.join(target_dir, _file)
# ファイルをアップロードし、バージョンにファイルリンクを作成します
shotgun.upload(
entity_type,
version_id,
file_path,
field_name=field_code,
display_name=_file
)
return 0
if __name__ == "__main__":
sys.exit(main())
4.5. 実行用バッチファイルの作成
Python のスクリプトは完成したので、それをワンタッチで実行できるようにするために、実行用のバッチファイルを作成します。
Python スクリプト(cli.py)と同じフォルダに myuploader.bat という名前でファイルを新規作成し、下記の内容を追加します。
内容としては、作成した仮想環境の venv_shotgun_scripting を有効にし、そこの Python インタプリタから、作成したスクリプトを実行します。
@ECHO OFF
SETLOCAL
SET THISDIR=%~dp0
SET ACTIVATE_VENV=%USERPROFILE%\.virtualenvs\venv_shotgun_scripting\Scripts\activate.bat
SET DEACTIVATE_VENV=%USERPROFILE%\.virtualenvs\venv_shotgun_scripting\Scripts\deactivate.bat
CALL %ACTIVATE_VENV%
python %THISDIR%\cli.py
CALL %DEACTIVATE_VENV%
PAUSE
4.6. 実行
5. 今回のまとめと応用
5.1. まとめ
● スクリプトを使うには、Shotgun に登録してトークンを発行します。
● API トークンの取り扱いには気を付けましょう。
● Python で開発を行う際には、venv を使う癖をつけると他のツール環境から影響を受けなくなり、スムーズな開発ができます。
● Python から Shotgun にアクセスするために、shotgun_api3 をインストールします。
● shotgun_api3 で Shotgun インスタンスを作成し、Shotgun にアクセスします。
● Shotgun インスタンスにはエンティティの作成やファイルアップロード用のメソッドが用意されています。
● バッチファイルで仮想環境をアクティブにしてからスクリプトを実行します。
5.2. 応用
今回作成したファイルアップローダーの機能だけでは十分に実用的ではありませんが、例えば以下の機能を追加していくことで、自分のプロジェクトに合った実用的なツールにしていくことができるでしょう。
● フォルダのパスをコマンドライン引数で指定できるようにする
○ argparse モジュールの利用
● 対象のフォルダにフォルダが含まれていた時に、スキップするか再帰的に階層を降りていく処理を加える
○ os モジュールの利用(os.path.isdir, os.walk)
● GUI を追加して、ドラッグアンドドロップでアップロードするファイルを追加できるようにする
○ Qt for Python, QtDesigner の利用
● Asset にリンクした Version にファイルへのリンクを作成する
● すでにアップロードされているファイルをアップロードしようとしたときに、スキップするか Version からのリンクを更新する
6. 付録
6.1. Shotgun の情報
● Autodesk 様
○ SHOTGUNの機能を理解するには
○ ShotgunSUPPORT
○ Service Status
○ Shotgun REST API v1
○ Shotgun Python API3
○ https://github.com/shotgunsoftware/python-api
● Born Digital 様
○ Born Digital サポート > Shotgun
6.2. Python の情報
● Python.org
https://www.python.org/
● Python チュートリアル
https://docs.python.org/ja/3.7/tutorial/
● Python 標準ライブラリ
https://docs.python.org/ja/3.7/library/index.html
● PEP 8 -- Style Guide for Python Code
https://www.python.org/dev/peps/pep-0008/
● PEP 20 -- The Zen of Python
https://www.python.org/dev/peps/pep-0020/
6.3. よくある質問
6.3.1. ファイルはどこにアップロードされるのか?
4章のファイルをアップロードする処理の説明で、「アップロードしたファイルへのリンクを作成する」という表現に違和感を覚えた方がいるかもしれません。バージョンのフィールドへファイルをアップロードするのではないのか、と。
ShotgunSUPPORT に記述があるように(*12)、通常、ファイルの実体は Amazon の S3 というクラウドストレージへアップロードされます。その際に Shotgun に [ファイル] (Attachment) エンティティというファイルを管理するためのエンティティが作成され、S3 上のファイル保存先を管理します。Version エンティティの sg_uploaded_movie フィールドのファイルリンクはこの Attachment エンティティを指します。図にすると下記の関係になります。
Version
├ code
.
└ sg_uploaded_movie → Attachment
├ this_file → File (S3)
.
└ display_name
6.3.2. サムネイルが表示されない?~トランスコーディングとステータスについて~
ファイルをアップロードした後に、ユーザーから、サムネイルが表示されてないんだけど?という問い合わせを受けることがあります。
この原因として考えられることとして、トランスコーディングの完了待ちがあります。
トランスコーディングとは、アップロードした元画像・元動画などを、サムネイル表示やプレビュー表示に適したサイズやファイル形式に変換する処理のことです。Shotgun はファイルをアップロードするとこのトランスコーディングを行い、サムネイル用とプレビュー表示用のファイルを自動で作成してくれます。元のファイルサイズが大きかったりアップロードしたファイルの数が多いとトランスコーディングに時間がかかるため、アップロードからサムネイルが表示されるまでタイムラグが出ることがあります。
6.3.3. Python2でshotgun_api3がインストールできない
shotgun_api3 のテストフォルダに含まれている画像ファイルの名前の影響で、Windows の Python 2 では公式リポジトリからモジュールをダウンロードすることができません。Python 2 を使用する場合は、公式リポジトリを Fork した弊社のリポジトリからインストールをお試しください。
https://github.com/smiletechnologyunited/python-api