
Pythonでレンダーファームを自動化:現時点でスクリプト化できること
概要
クラウドレンダリングで時間がかかる部分は、レンダリングそのものではなく、その周辺の作業であることが少なくありません。テクスチャが1つだけローカルドライブを指しているせいで失敗するシーン、最初からやり直しになるアップロード、全フレームが戻ってきたかどうかを誰も確認しないまま届いたフレームなどです。知りたいのは、Pythonのスクリプトが実際にどこまで届くのか、という点でしょう。
弊社はフルマネージドのファームであるSuper Renders Farmを運営しており、その境界を正確にお伝えしたいと考えています。存在しない経路の上に組んだ自動化は、無人で迎える最初の夜に止まってしまうからです。そこで、最初に率直な結論を述べます。プロジェクトファイルをファームへ移す作業は、スクリプト化できます。S3アクセス(アカウント内のCloud Direct Connect)でアクセスキーを生成すると、AWS CLIを使ってSRF Spaceとの間でファイルをコピーできます。一方、ジョブの提出はスクリプト化できません。ジョブは、Webダッシュボード、Client App、または3ds Max・Maya・Cinema 4D内の提出用プラグインから提出します。弊社は、SFTPやFTPのサービス、公開API・SDK、コードから呼び出せるジョブ提出用のエンドポイントを提供していません。プログラムからの提出を可能にする公開APIはロードマップに載っていますが、現時点では利用できず、以下の内容はそれに依存しません。
以前このページをご覧になった方へ。以前のバージョンでは、SFTPによるスクリプト化した転送を紹介していました。しかし、その経路は弊社のファームでは提供されていません。現在、スクリプト化できる転送はS3アクセスを通じて行います。詳しくは後述します。
それでも、Pythonの出番は多く残っています。アップロード前の作業すべて、アップロードそのもの、そしてフレームがお使いのディスクに届いてからの作業すべてをスクリプト化できます。ヘッドレス・無人レンダリングの考え方の全体像は、ヘッドレスレンダーファームの無人ワークフローのガイドをご覧ください。本記事ではコードのレベルに絞って解説します。
マネージド型ファームで境界がどこにあるか
弊社のファームでは、パイプラインは4つの区間に分かれます。
- アップロード前:お客様側で、完全にスクリプト化できます。 DCC内でのシーン検証、パスの修正、パッケージング、プリフライトチェック、チェックサムが含まれます。
- アップロード:S3アクセスでスクリプト化できます。手動でも可能です。 AWS CLIを使えば、スクリプトからプロジェクトフォルダをSRF Spaceへコピーできます。手動の方法は、WebアップロードとSuperRenders Client Appです。Webアップロードにはサイズの厳密な上限はありませんが、タブを閉じると再開できません。そのため、数ギガバイトを超える場合や接続が不安定な場合は、Client App(再開可能、並列チャンク)またはS3アクセスをお使いください。家庭用回線では、ブラウザ1回のアップロードは約2GBを超えると遅くなり、約5GBを超えると不安定になります。
- 提出:手動です。 Webダッシュボード、Client App、または提出用プラグインから提出します。ジョブに料金が発生する前に、ファームがアップロードされたプロジェクトに対してScene Analysisを実行します。
- レンダリング後:再びお客様側です。 Client Appの自動ダウンロードをオンにしていれば、フレームは1枚ずつ完了するたびにローカルフォルダへ届きます。あるいは、スクリプトでS3経由で取得することもできます。フレームがお使いのディスクに届いた時点から先は、確認、エンコード、コピー、通知のすべてがローカルのスクリプトになります。
現実的な形は、短い手動ステップの前後を自動化することです。以下のスクリプトは、そのステップを素早く、間違いにくくします。マネージド型モデルで何が代行されるかについては、フルマネージドのレンダーファームとはの解説をご覧ください。
3つの区間:スクリプト化できるシーンチェックとS3アップロード、手動のジョブ提出、そしてスクリプト化できるフレーム確認とエンコード
自動化は、短い手動ステップの前後に置きます。お客様側で検証、プリフライト、マニフェスト作成、アップロードを行い、提出は手動で行い、その後、戻ってきたものを確認して後処理します。
ステップ1:DCC内でシーンを検証する
弊社の経験では、失敗するレンダージョブの大半は、レンダラーのバグではありません。パッケージングの漏れです。ファームから見えないドライブにあるテクスチャ、収集されなかった参照ファイル、プロジェクトルートの1つ上のフォルダにあるキャッシュなどです。ワーカーが開けるのはアップロードされたフォルダの中にあるものだけなので、最初のスクリプトは、シーン自身の依存関係リストを読み取れるDCCの内部に置きます。
主要なDCCはいずれもPythonでこれを扱えます。Mayaではmaya.cmds、3ds Maxではpymxs、Cinema 4Dではc4dモジュール、Houdiniではhou、Blenderではbpyです。まず、DCC自身の収集機能を実行します(3ds MaxではResource Collector、またはArchiveを実行して書き出されたアーカイブを展開して使う方法、Cinema 4DではSave Project with Assets、Blenderでは、アセットを.blendのあるフォルダの下に置いてMake Paths Relativeを実行します)。収集機能がファイルを集め、スクリプトがその結果を確かめます。Blender版は、Scriptingワークスペース内で、またはヘッドレスで blender -b scene.blend --python check_paths.py として実行できます。
# check_paths.py: runs inside Blender, reads the open .blend, touches nothing remote
import os
import sys
import bpy
def inside(path, root):
try:
a, b = os.path.normcase(path), os.path.normcase(root)
return os.path.commonpath([a, b]) == b
except ValueError:
return False # different drive on Windows
def main():
if not bpy.data.filepath:
if bpy.app.background:
sys.exit("save the .blend first")
print("save the .blend first")
return
bpy.ops.file.make_paths_relative() # rewrite paths under the .blend's folder to // form
blend_dir = os.path.dirname(bpy.data.filepath)
refs = [("image", i) for i in bpy.data.images
if i.source == "FILE" and not i.packed_file] # skip generated, sequence, UDIM, packed
refs += [("library", lib) for lib in bpy.data.libraries]
refs += [("cache", c) for c in bpy.data.cache_files] # Alembic and USD caches
refs += [("volume", v) for v in bpy.data.volumes] # OpenVDB volumes
issues = []
for kind, block in refs:
full = os.path.abspath(bpy.path.abspath(block.filepath))
if not os.path.exists(full):
issues.append((f"missing {kind}", block.name, block.filepath))
elif not inside(full, blend_dir):
issues.append(("outside project", block.name, block.filepath))
for kind, name, path in issues:
print(f"{kind:16} {name:32} {path}")
if not issues:
bpy.ops.wm.save_mainfile() # keep the relative paths only when the scene is clean
if bpy.app.background:
sys.exit(1 if issues else 0)
main()
このパターンはどのDCCにも応用できます。すべてのファイル参照を解決し、見つからないものと、プロジェクトルートの外に解決されるものにフラグを立てます。
プロジェクトによっては、相対パスにできないものがあります。スキャッタライブラリ、人物ライブラリ、一部のキャッシュは、内部に絶対パスを保持しているためです。その場合は、Client AppのAuto keep local pathオプションが、アップロード時に絶対パスのフォルダ構成を維持します。また、ファーム側のパスをお使いのローカルのパスと変えなければならない場合は、弊社のSimulate Local Pathユーティリティが、シーンが想定するパスを再現します。そのときスクリプトは、「プロジェクトルートの下にすべてある」ではなく、「維持するルートの下にすべてある」を確認するようにします。3ds Maxについては、3ds Maxファイルをパッケージングする方法のガイドで収集の手順を解説しています。
ステップ2:プロジェクトフォルダをプリフライトチェックする
DCC側のチェックはシーンを把握しており、フォルダ側のチェックはアップロードを把握しています。後者は、ディスク上にある問題を拾い上げます。シーンファイルがない、誰かがアーカイブを入れてしまった、コピーの中断でサイズがゼロのファイルが生じた、古いWindowsアプリケーションが扱えないほどパスが長い、といった問題です。
アーカイブのチェックは、見た目以上に重要です。ファームはアーカイブ(.zip、.rar、.7z、.tar、.tar.gz)を展開しないため、アーカイブの中にあるものはレンダリングされません。プロジェクトフォルダは、シーンファイルと参照アセットをすべて所定の位置に置き、展開した状態でアップロードしてください。
#!/usr/bin/env python3
"""preflight.py: check a project folder before upload. Reads local disk only."""
import json
import sys
from pathlib import Path
SCENE_SUFFIXES = {".max", ".ma", ".mb", ".c4d", ".blend", ".hip", ".hiplc", ".aep"}
ARCHIVE_SUFFIXES = {".zip", ".rar", ".7z", ".tar", ".tgz"} # the farm does not extract these
SINGLE_BROWSER_UPLOAD_GB = 2 # above this, use the Client App or S3 access instead
LONG_PATH = 240 # headroom under the classic 260-character Windows limit
def preflight(root: Path) -> dict:
files = [p for p in root.rglob("*") if p.is_file()]
scenes = [p for p in files if p.suffix.lower() in SCENE_SUFFIXES]
total = sum(p.stat().st_size for p in files)
problems, warnings = [], []
if not scenes:
problems.append("no scene file found in the folder")
for p in files:
rel = p.relative_to(root)
if p.suffix.lower() in ARCHIVE_SUFFIXES or p.name.lower().endswith(".tar.gz"):
problems.append(f"archive will not be unpacked: {rel}")
if p.stat().st_size == 0:
warnings.append(f"zero-byte file: {rel}")
if len(str(p)) > LONG_PATH:
warnings.append(f"long path ({len(str(p))} chars): {rel}")
if total > SINGLE_BROWSER_UPLOAD_GB * 1024**3:
warnings.append("over ~2 GB: use the Client App or S3 access, not one browser upload")
return {"root": str(root), "files": len(files), "gigabytes": round(total / 1024**3, 2),
"scenes": [str(p.relative_to(root)) for p in scenes],
"problems": problems, "warnings": warnings}
if __name__ == "__main__":
report = preflight(Path(sys.argv[1]).resolve())
print(json.dumps(report, indent=2))
sys.exit(1 if report["problems"] else 0)
終了コードが0以外になることが要点です。このスクリプトを、アーティストの一日の終わりにすでに動いている仕組み(パブリッシュツール、保存フック、「ファーム投入準備完了」ボタンなど)に組み込めば、問題のあるプロジェクトがアップロードに到達することはありません。警告は表示されるだけで、問題はアップロードを止めます。
ステップ3:何を送ったかを正確に把握できるようにマニフェストを書く
プロジェクトがプリフライトを通過したら、記録を残します。マニフェストは、すべてのファイルについてサイズとSHA-256ハッシュを一覧にしたものです。アップロードの対象に含まれてしまわないよう、プロジェクトの中ではなく隣に書き出します。マニフェストがあれば、通常なら午後いっぱいかかる次の3つの疑問に答えられます。どのバージョンのシーンがレンダリングされたのか、前回の提出から何が変わったのか、ディスク上のフォルダがアップロードしたものとまだ一致しているのか、です。
# manifest.py: hash a project folder and compare two snapshots. Local files only.
import hashlib
import json
import time
from pathlib import Path
def sha256(path: Path, chunk: int = 8 * 1024 * 1024) -> str:
h = hashlib.sha256()
with open(path, "rb") as f:
while block := f.read(chunk):
h.update(block)
return h.hexdigest()
def write_manifest(root: Path, out: Path) -> dict:
files = [{"path": p.relative_to(root).as_posix(), "bytes": p.stat().st_size, "sha256": sha256(p)}
for p in sorted(root.rglob("*")) if p.is_file()]
manifest = {"project": root.name, "created": time.strftime("%Y-%m-%dT%H:%M:%S"), "files": files}
out.write_text(json.dumps(manifest, indent=2))
return manifest
def diff_manifests(old: dict, new: dict):
a = {f["path"]: f["sha256"] for f in old["files"]}
b = {f["path"]: f["sha256"] for f in new["files"]}
changed = sorted(k for k in a.keys() & b.keys() if a[k] != b[k])
return sorted(b.keys() - a.keys()), sorted(a.keys() - b.keys()), changed
マニフェストはショットとバージョンごとに保存します(shot010_v003.manifest.json)。そうすると差分は「テクスチャ2点が変更、キャッシュ1点が追加、削除なし」という1行の要約になります。
AWS CLIで転送をスクリプト化する
S3アクセス(アカウント内のCloud Direct Connect)では、アクセスキーを生成し、Cyberduck(プロトコル:Amazon S3)またはAWS CLIをSRF Spaceに接続して、ファイルのアップロードとダウンロードを行えます。ファイルブラウザで操作したい方にはCyberduckが向いており、スクリプトから操作できるのはAWS CLIです。S3アクセスが行うのはファイルの移動だけです。SFTPやFTPのサービスではなく、ジョブの提出も行いません。
設定はマシンごとに一度だけです。アカウントでCloud Direct Connectを開いてアクセスキーを生成し、Access Key ID、Secret Access Key、Remote Directoryをコピーします。そのうえで、名前付きのAWSプロファイルにキーを保存します。
aws configure --profile srf # both keys; region ap-southeast-1; output format blank or json
export AWS_PROFILE=srf # the AWS CLI and boto3 both read this
展開した状態のプロジェクトフォルダ、つまりプリフライトを通過した同じフォルダを、Remote Directoryにアップロードします。
aws s3 cp ./shot010_v003 "s3://<your Remote Directory>/shot010_v003/" --recursive
aws s3 syncは、--recursiveなしで同じコピー元とコピー先を指定でき、新規または変更されたファイル(サイズまたはタイムスタンプで判定)だけをコピーします。そのため、転送が中断されたあとに再実行すれば、すでに届いたものはスキップされます。大きなファイルは、自動的に並列のマルチパートアップロードに分割されます。この方法でアップロードしたファイルはSRF Spaceに表示され、ほかの方法でアップロードしたものと同じように提出できます。プリフライトで1点注意があります。プロジェクトがレンダーノードに同期される際、*.ini、*.db、*.tmp、*.temp、*.lnk、*.swap、*.partialに一致するファイルと、rendertemp/フォルダはスキップされます。そのため、シーンがこれらに依存していてはいけません。
Python側は薄いラッパーです。プリフライトを実行し、問題があればアップロードを拒否し、問題がなければフォルダをAWS CLIに渡します。
# upload_project.py: pre-flight, then copy the folder to your SRF Space with the AWS CLI.
import os
import subprocess
import sys
from pathlib import Path
from preflight import preflight # the Step 2 script
def upload(project: Path, remote_dir: str) -> None:
report = preflight(project)
if report["problems"]:
sys.exit("pre-flight failed: " + "; ".join(report["problems"]))
target = f"s3://{remote_dir.removeprefix('s3://').strip('/')}/{project.name}/"
subprocess.run(["aws", "s3", "sync", str(project), target,
"--region", "ap-southeast-1"], check=True)
if __name__ == "__main__":
upload(Path(sys.argv[1]).resolve(), os.environ["SRF_REMOTE_DIR"])
Pythonの中で完結させたい場合は、boto3のupload_fileでも、Remote Directoryにあるバケットとプレフィックスに対して同じことができます。プロファイルとリージョンも同じものを使います。
同じキーは、逆方向にも使えます。レンダリングされた出力は、SpaceのSuperRendersOutput/<jobId>/フォルダに置かれます(aws s3 ls "s3://<your Remote Directory>/SuperRendersOutput/"でジョブのフォルダを一覧できます)。次のコマンド1つで、ジョブをローカルフォルダに取得できます。
aws s3 sync "s3://<your Remote Directory>/SuperRendersOutput/<jobId>/" ./renders/shot010_v003/
キーはパスワードと同じように扱ってください。
- キーを持っている人は、誰でもSRF Spaceにアクセスできます。 キーはスクリプトの中には書かず、アップロードを実行するマシンのAWSプロファイル、または
AWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEYの環境変数に保管します。 - リポジトリにコミットしたり、共有のパイプライン設定に貼り付けたりしないでください。 Remote Directoryも、上記のとおり環境変数に置いてください。
- キーはアカウントごとに1つで、有効期限はありません。 漏えいしたおそれがある場合や、キーを変更する必要がある場合は、弊社のサポートチームにご連絡ください。
手動のままなのは提出です。アップロードのあと、ジョブはWebダッシュボード、Client App、またはDCCプラグインから提出します。
ステップ4:提出時の引き継ぎを短く、繰り返せるものにする
提出は、人がフォームを順に入力する作業です。そのため、フォームへの入力が簡単な作業になるようにしておきます。検証の手順で、マニフェストの隣に小さな引き継ぎシートも書き出しましょう。記載する項目は、シーンファイル、カメラ、フレーム範囲、解像度、出力形式、レンダーエンジン、フレームの保存先のローカルフォルダです。提出する人は、記憶に頼らず値をコピーするだけで済みます。ステップ5のウォッチャーも同じシートを読むので、両者がずれることはありません。
次の3つの取り決めがあると、一連の流れを自動化しやすくなります。
- ショットとバージョンごとに1つのフォルダ(
shot010_v003/)とし、シーンファイルはその直下に置きます。プリフライト、マニフェスト、アップロード先、引き継ぎシートは、すべてこの名前を基準にします。 - 出力ファイル名のフレーム番号はゼロ埋めにします(
shot010.1001.exr)。ウォッチャーは、解析できない範囲を検証できません。 - ジョブごとに予測しやすいダウンロードフォルダを決めます。 Client Appは、設定で決めた既定のパスにダウンロードし、提出時にジョブごとにパスを上書きできます。そのショット専用のレンダーフォルダを指定してください。
3ds Max、Maya、Cinema 4Dでは、提出用プラグインが開いているシーンからフレーム範囲、出力パス、レンダー設定を読み取り、ジョブのフォームに入力し、独自のアセットチェックを実行します。Blender、Houdini、After EffectsにはDCC内のプラグインがないため、これらのジョブはClient AppまたはWebダッシュボードから提出します。いずれの場合も、ジョブに料金が発生する前にScene Analysisが実行されます。スクリプトによって、このゲートで止められる頻度を減らせます。
ステップ5:戻ってきたフレームを検証する
Client Appを起動して自動ダウンロードをオンにしておくと(既定でオンです)、各フレームはファームで完了した時点でお使いのマシンにダウンロードされます。S3アクセスの場合は、代わりにご自身のaws s3 syncの実行でローカルフォルダに取得します。どちらの場合も、問題は「すべてのフレームが破損なく届いたことをどう確認するか」になります。ウォッチャーは、ローカルのファイルだけを使ってそれに答えます。フレームが完了したとみなされるのは、2回のポーリングの間でサイズが変化しておらず、かつファイルヘッダーが有効な場合に限られます。
# watch_frames.py: verify frames arriving in a local folder. Reads local disk only.
import re
import time
from pathlib import Path
MAGIC = {".exr": b"\x76\x2f\x31\x01", ".png": b"\x89PNG\r\n\x1a\n"}
def header_ok(path: Path) -> bool:
magic = MAGIC.get(path.suffix.lower())
with open(path, "rb") as f:
head = f.read(8)
return head.startswith(magic) if magic else len(head) > 0
def watch(job_dir: Path, first: int, last: int, poll: int = 60, give_up_hours: float = 24,
name_re: str = r"\.(\d{4,})\.(exr|png)$") -> list:
# name_re: default matches any frame-numbered file. Anchor it to one pass's file
# prefix (e.g. r"^shot010_beauty\.(\d{4,})\.(exr)$") when the job writes render
# elements or AOVs as separate files, so this watcher tracks a single pass.
pattern = re.compile(name_re, re.IGNORECASE)
expected = set(range(first, last + 1))
last_size, done = {}, {}
deadline = time.time() + give_up_hours * 3600
while True:
for p in job_dir.rglob("*"):
m = pattern.search(p.name) if p.is_file() else None
if not m or int(m.group(1)) not in expected or int(m.group(1)) in done:
continue
size = p.stat().st_size
if size > 0 and last_size.get(p) == size and header_ok(p):
done[int(m.group(1))] = p # stable across two polls, valid header
last_size[p] = size
missing = sorted(expected - done.keys())
print(f"{len(done)}/{len(expected)} frames verified, {len(missing)} outstanding")
if not missing:
return [done[f] for f in sorted(done)]
if time.time() > deadline:
raise TimeoutError(f"frames still missing: {missing[:20]}")
time.sleep(poll)
検索は再帰的に行うので、ダウンロード先のサブフォルダ構成がどうであっても、名前でフレームを見つけられます。ジョブが完了と表示されているのにウォッチャーがまだ欠番を報告する場合は、Client AppでそのジョブのSync outputを使って欠けているフレームを再ダウンロードします(aws s3 syncを再実行しても構いません)。そのうえで、ウォッチャーをもう一度実行してください。フレームのサイズが短く見える場合も同様にしてください。途中で止まった部分的なダウンロードも、サイズが安定しているように見えることがあるためです。ポーリングよりイベントを使いたい場合は、watchdogパッケージが、オペレーティングシステムのファイル変更通知をラップしています。その場合でも、安定性のチェックは残してください。ジョブがレンダーエレメントやAOVを別々のファイルとして書き出す場合は、パスごとにウォッチャーを1つずつ実行してください。そうしないと、完了したパスのファイルが、同じ番号のbeautyフレームの欠落を覆い隠してしまうことがあります。
ステップ6:レンダリング後のローカル処理
ウォッチャーが検証済みのリストを返したら、あとは通常のパイプラインコードです。
import subprocess
def encode_review(frames_dir, pattern, start, out, fps=24): # pattern e.g. "shot010.%04d.png"
subprocess.run(["ffmpeg", "-y", "-framerate", str(fps), "-start_number", str(start),
"-i", f"{frames_dir}/{pattern}", "-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2",
"-c:v", "libx264", "-pix_fmt", "yuv420p", "-crf", "18", str(out)], check=True)
身につけておくとよい習慣を挙げます。
- 表示参照のフレームからエンコードします。 PNGやJPEGは、そのままレビュー用ムービーにできます。リニアのEXRは、先にカラーパイプライン(通常はOCIOトランスフォーム)を通す必要があります。通さないと、ムービーが暗く平板に見えます。
- マニフェストをフレームと一緒にアーカイブします。 6か月後に「このレンダリングにどのテクスチャが使われたか」を調べるとき、必要なファイルが1つ見つかるだけで済みます。
- 通知には事実を書きます。 フレーム数、同期が必要だったフレーム、合計サイズ、レビュー用ムービーのパスを、スタジオのチャットやトラッカーに投稿します。
- ご自身のコピーをアーカイブの正本にします。 弊社のファーム上のファイルは、ジョブの実行とレンダリング結果のダウンロードに必要な期間、保管されます。自動削除の期間は固定されておらず、ご依頼があればいつでも削除します。ただし、これはバックアップの代わりにはなりません。アーカイブの正本は、お手元のローカルのものです。
ローカル側の処理をスケジュールする
これらのどれにも、新しいスケジューラーは必要ありません。Linuxではcron、macOSではlaunchd、WindowsではTask Schedulerで、「準備完了」とマークされたプロジェクトに対して、毎晩プリフライト、マニフェスト、AWS CLIによるアップロードを実行できます。そうすれば、誰かが提出のために席に着く前に、ファイルはSRF Spaceに届いています。ウォッチャーは、提出の直後に開始することも、ステップ4の引き継ぎシートから作った監視リストを走査するスキャナーとして動かすこともできます。
計画しておくべき依存関係が1つあります。自動ダウンロードが行われるのは、Client Appが、スリープしておらずオンラインのマシンで動いている間だけです。Windowsでは、バックグラウンドサービスがインストールされ、メインウィンドウを閉じたあとも転送が続きます。Client App、またはスケジュールしたaws s3 syncは、夜間も電源が入ったままのマシンで実行してください。
まとめ:何を、どのように自動化するか
| 段階 | 現時点で弊社のファームでスクリプト化できるか | 方法 |
|---|---|---|
| シーンの検証(欠落パスと絶対パス) | 可能 | DCC内のPython(bpy、maya.cmds、pymxs、c4d、hou) |
| プロジェクトフォルダのプリフライトチェック | 可能 | ローカルのスクリプト。アーカイブ、シーンファイルなし、サイズゼロのファイルで停止 |
| マニフェストと変更の差分 | 可能 | ファイルごとのSHA-256を、プロジェクトの隣にJSONで保存 |
| ファームへのアップロード | S3アクセスで可能 | Cloud Direct Connectのキーを使ったAWS CLI(aws s3 cp --recursiveまたはaws s3 sync)。手動の方法は、Webアップロード(約2GBを超えると遅く、約5GBを超えると不安定)とClient App(再開可能、並列チャンク) |
| ジョブの提出 | 不可 | Webダッシュボード、Client App、または3ds Max・Maya・Cinema 4D用のプラグイン。公開APIはロードマップ上 |
| 完成フレームのダウンロード | S3アクセスで可能。または自動で処理 | SuperRendersOutput/<jobId>/からのaws s3 sync。またはClient Appの自動ダウンロード(フレームごと)、Webからのダウンロード |
| フレームの検証 | 可能 | ローカルのウォッチャー:サイズが安定、ヘッダーが有効、全範囲がそろっている |
| エンコード、アーカイブ、通知 | 可能 | ffmpeg、ファイルコピー、お使いのチャットやトラッカー |
両端を自動化し、真ん中の手動ステップは短く意図的にとどめ、戻ってきたものはすべて検証します。Blenderのシーンが大半を占める場合は、Blenderクラウドレンダーファームのページで、弊社側でそれらのジョブがどのように実行されるかを解説しています。手動の手順の詳細は、Client Appのドキュメントと提出用プラグインのドキュメントをご覧ください。
FAQ
Q: Pythonスクリプトからレンダーファームにプロジェクトをアップロードできますか?
A: はい、S3アクセスを使えば可能です。アカウントのCloud Direct Connectでアクセスキーを生成し、そのキーでAWS CLIを設定し(リージョンはap-southeast-1)、スクリプトから展開済みのプロジェクトフォルダに対してaws s3 cp --recursiveまたはaws s3 syncを実行して、Remote Directoryにコピーします。壊れたプロジェクトがアップロードされないよう、先にプリフライトチェックを実行してください。アップロード後のジョブの提出は、引き続き手動です。
Q: S3アクセスとClient Appのどちらを使うべきですか? A: 転送をスクリプトやスケジューラーから実行したい場合や、チームがすでにCyberduckなどのS3クライアントを使っている場合は、S3アクセスをお使いください。人が手作業でアップロードする場合は、Client Appをお使いください。接続が切れても大きな転送を再開でき、ジョブを提出でき、完成したフレームを完了のたびに自動でダウンロードします。両者は組み合わせて使えます。スクリプトによる転送にはS3アクセスを、提出にはClient Appを使います。
Q: パイプラインからレンダージョブを提出するためのAPIやSDKはありますか? A: 現時点ではありません。ジョブは、Webダッシュボード、Client App、または3ds Max・Maya・Cinema 4D内の提出用プラグインから提出します。プログラムからの提出を可能にする公開APIはロードマップに載っていますが、利用できる状態ではないため、お客様側で担当する区間を中心に自動化を組んでください。パイプラインがそれを必要としてお困りの場合は、ユースケースを弊社のサポートチームにお知らせください。
Q: 大きな転送のために、ファームはSFTPやFTPのアクセスを提供していますか? A: いいえ。アップロード、ダウンロード、レンタルマシンのいずれについても、SFTPやFTPのサービスは運用していません。大きなプロジェクトは、再開可能な並列チャンクでアップロードするClient App、またはCyberduckやAWS CLIを使ったS3アクセスで転送します。完成したフレームは、Client Appの自動ダウンロード、Webからのダウンロード、またはS3アクセスで受け取れます。
Q: すべてのフレームが戻ってきたかどうかは、どう確認できますか?
A: Client Appがジョブを自動ダウンロードするフォルダ、またはaws s3 syncの書き込み先のフォルダで、ウォッチャーを実行します。フレームを完了とみなすのは、2回のチェックの間でサイズが安定し、かつヘッダーが有効な場合だけにして、検証済みのセットを想定するフレーム範囲と比較してください。ジョブが完了しているのにフレームが欠けている場合は、Client AppでSync outputを使うか、同期を再実行してください。
Q: 時間を節約するために、アップロード前にプロジェクトをzipで圧縮すべきですか? A: いいえ。ファームはアーカイブ(.zip、.rar、.7z、.tar、.tar.gz)を展開しないため、アーカイブの中にあるものはレンダリングされません。どのアップロード方法を使う場合でも、プロジェクトフォルダは、シーンファイルと参照アセットをすべて所定の位置に置き、展開した状態でアップロードしてください。
Q: レンダリングされたフレームは、ファームにどのくらいの期間保管されますか? A: 自動削除の期間は固定されていません。ファイルは、ジョブの実行とレンダリング結果のダウンロードに必要な期間、保管され、ご依頼があればいつでも削除します。お手元のストレージをアーカイブの正本として扱い、フレームが完了のたびにお使いのディスクへ届くよう、Client Appの自動ダウンロードをご利用ください。
About Alice Harper
Blender and V-Ray specialist. Passionate about optimizing render workflows, sharing tips, and educating the 3D community to achieve photorealistic results faster.



