
Python으로 렌더팜 자동화하기: 오늘 스크립트로 할 수 있는 것
개요
클라우드 렌더에서 가장 시간이 걸리는 구간은 렌더 자체가 아니라 그 주변인 경우가 많습니다. 텍스처 하나가 아직 로컬 드라이브를 가리키고 있어서 실패하는 씬, 처음부터 다시 시작해야 하는 업로드, 프레임이 전부 돌아왔는지 아무도 확인하지 않은 채 돌아온 프레임 같은 것들입니다. 유용한 질문은 Python 스크립트가 실제로 어디까지 닿을 수 있는가입니다.
저희는 풀 매니지드 렌더팜인 Super Renders Farm을 운영하며, 이 경계를 정확히 밝히려 합니다. 존재하지 않는 경로 위에 만든 자동화는 첫 무인 실행의 밤에 실패하기 때문입니다. 그래서 먼저 분명하게 정리해 둡니다. 프로젝트 파일을 렌더팜으로 옮기는 일은 스크립트화할 수 있습니다. S3 access(계정의 Cloud Direct Connect)로 액세스 키를 발급받으면, AWS CLI가 그 키로 SRF Space와 파일을 주고받습니다. 반면 작업 제출은 스크립트화할 수 없습니다. 작업은 웹 대시보드, Client App, 또는 3ds Max, Maya, Cinema 4D 안의 제출 플러그인에서 제출합니다. 저희는 SFTP나 FTP 서비스, 공개 API나 SDK, 코드에서 호출할 수 있는 작업 제출 엔드포인트를 제공하지 않습니다. 프로그래밍 방식 제출을 위한 공개 API는 로드맵에 있지만 지금은 사용할 수 없으며, 아래 내용은 그것에 의존하지 않습니다.
이전에 이 페이지를 보신 독자께 알려 드립니다. 이전 버전은 SFTP를 통한 스크립트 전송을 설명했습니다. 그 경로는 저희 렌더팜에서 제공하지 않으며, 이제 스크립트 전송은 아래에서 다루는 S3 access를 통해 이루어집니다.
그래도 Python이 할 수 있는 일은 많습니다. 업로드 이전의 모든 과정, 업로드 자체, 그리고 프레임이 디스크에 도착한 이후의 모든 과정을 스크립트화할 수 있습니다. 헤드리스 및 무인 렌더링의 개념 지도는 헤드리스 렌더팜 무인 워크플로 가이드를 참고하세요. 이 글은 코드 수준에 집중합니다.
매니지드 렌더팜에서 경계가 놓이는 곳
저희 렌더팜에서 파이프라인은 네 구간으로 나뉩니다.
- 업로드 이전: 여러분의 몫이며 전부 스크립트화할 수 있습니다. 씬 검증, 경로 수정, 패키징, 사전 점검, 체크섬이 여기에 속합니다.
- 업로드: S3 access로 스크립트화할 수 있으며, 수동 방법도 있습니다. AWS CLI가 스크립트에서 프로젝트 폴더를 SRF Space로 복사합니다. 수동 방법은 웹 업로드와 SuperRenders Client App입니다. 웹 업로드에는 하드 크기 제한이 없지만 탭을 닫으면 이어서 올릴 수 없으므로, 수 기가바이트가 넘거나 연결이 불안정하다면 Client App(이어받기 지원, 병렬 청크) 또는 S3 access를 사용하세요. 브라우저 업로드 한 번은 일반 가정용 연결에서 약 2 GB를 넘으면 느려지고 약 5 GB를 넘으면 불안정해집니다.
- 제출: 수동입니다. 웹 대시보드, Client App, 또는 제출 플러그인에서 제출하며, 렌더팜은 작업에 요금이 청구되기 전에 업로드된 프로젝트에 Scene Analysis를 실행합니다.
- 렌더 이후: 다시 여러분의 몫입니다. Client App의 자동 다운로드를 켜 두면 프레임이 하나씩 완료될 때마다 로컬 폴더로 내려오며, 스크립트가 S3로 가져올 수도 있습니다. 프레임이 디스크에 도착한 순간부터 모든 점검, 인코딩, 복사, 알림은 로컬 스크립트입니다.
따라서 현실적인 모습은 짧은 수동 단계 하나의 양쪽에 자동화를 두는 것이며, 아래 스크립트는 그 단계를 빠르고 실수하기 어렵게 만듭니다. 매니지드 모델이 대신 처리해 주는 일은 풀 매니지드 렌더팜이란 무엇인가 설명글에서 다룹니다.
스크립트화 가능한 씬 점검과 S3 업로드, 수동 작업 제출, 그다음 스크립트화 가능한 프레임 점검과 인코딩의 세 구간
자동화는 짧은 수동 단계 하나의 양쪽에 놓입니다. 여러분 쪽에서는 검증, 사전 점검, 매니페스트 작성, 업로드를 하고, 제출은 직접 한 다음, 돌아온 결과물을 검증하고 후처리합니다.
1단계: DCC 안에서 씬 검증하기
저희 경험상 실패하는 렌더 작업의 대부분은 렌더러 버그가 아니라 패키징 누락입니다. 렌더팜이 볼 수 없는 드라이브에 있는 텍스처, 수집되지 않은 참조 파일, 프로젝트 루트보다 한 폴더 위에 있는 캐시 같은 것들입니다. 워커는 업로드된 폴더 안에 있는 것만 열 수 있으므로, 첫 번째 스크립트는 씬 자체의 의존성 목록을 읽을 수 있는 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 점검은 씬을 알고, 폴더 점검은 업로드를 압니다. 폴더 점검은 디스크에 있는 문제를 잡아냅니다. 씬 파일이 없는 경우, 누군가 넣어 둔 아카이브, 중단된 복사가 남긴 0바이트 파일, 오래된 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 해시와 함께 나열하며, 업로드에 포함되지 않도록 프로젝트 안이 아니라 프로젝트 옆에 작성합니다. 매니페스트가 있으면 그렇지 않을 때 한나절이 드는 세 가지 질문에 답할 수 있습니다. 어느 버전의 씬이 렌더링되었는지, 지난 제출 이후 무엇이 바뀌었는지, 디스크의 폴더가 업로드된 내용과 여전히 일치하는지입니다.
# 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) diff는 한 줄 요약이 됩니다. "텍스처 두 개 변경, 캐시 하나 추가, 삭제 없음"처럼 말입니다.
AWS CLI로 전송 스크립트화하기
S3 access(계정의 Cloud Direct Connect)로 액세스 키를 발급받은 다음, Cyberduck(프로토콜: Amazon S3) 또는 AWS CLI를 SRF Space에 연결해 파일을 업로드하고 다운로드할 수 있습니다. Cyberduck은 파일 브라우저를 원하는 분께 적합하고, 스크립트가 구동할 수 있는 쪽은 AWS CLI입니다. S3 access는 파일 이동만 담당합니다. 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에 나타나며 다른 업로드와 마찬가지로 제출할 수 있습니다. 사전 점검에서 한 가지 주의할 점이 있습니다. 프로젝트가 렌더 노드로 동기화될 때 *.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/"로 작업 폴더를 나열할 수 있습니다), 명령 하나로 작업 하나를 로컬 폴더로 가져올 수 있습니다.
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도 위에서처럼 환경 변수에 두세요.
- 계정마다 키는 하나이며 만료되지 않습니다. 유출이 의심되거나 키를 바꿔야 한다면 지원팀에 문의하세요.
수동으로 남는 것은 제출입니다. 업로드 후에도 작업은 웹 대시보드, Client App, 또는 DCC 플러그인에서 제출해야 합니다.
4단계: 제출 핸드오프를 짧고 반복 가능하게 만들기
제출은 사람이 폼을 차례로 클릭하는 일이므로, 폼 작성이 가장 쉬운 부분이 되게 만드세요. 검증 단계가 매니페스트 옆에 작은 핸드오프 시트도 함께 작성하게 하세요. 씬 파일, 카메라, 프레임 범위, 해상도, 출력 포맷, 렌더 엔진, 프레임이 저장될 로컬 폴더를 담습니다. 제출하는 사람은 기억에 의존하는 대신 값을 복사하고, 5단계의 감시 스크립트가 같은 시트를 읽으므로 둘이 어긋날 수 없습니다.
세 가지 규칙이 이 체인의 자동화를 쉽게 만듭니다.
- 샷과 버전마다 폴더 하나(
shot010_v003/)를 두고, 씬 파일은 그 루트에 둡니다. 사전 점검, 매니페스트, 업로드 대상, 핸드오프 시트가 모두 이 이름을 기준으로 삼습니다. - 출력 이름의 프레임 번호는 0으로 채웁니다(
shot010.1001.exr). 감시 스크립트는 파싱할 수 없는 범위를 검증할 수 없습니다. - 작업마다 예측 가능한 다운로드 폴더를 정합니다. Client App은 설정에 지정한 기본 경로로 내려받으며, 제출할 때 작업별로 경로를 바꿀 수 있습니다. 해당 샷의 렌더 폴더를 지정하세요.
3ds Max, Maya, Cinema 4D에서는 제출 플러그인이 열려 있는 씬에서 프레임 범위, 출력 경로, 렌더 설정을 읽어 작업 폼을 미리 채우고 자체 에셋 점검을 실행합니다. Blender, Houdini, After Effects에는 DCC 안의 플러그인이 없으므로 이 작업들은 Client App 또는 웹 대시보드를 통해 제출합니다. 어느 쪽이든 작업에 요금이 청구되기 전에 Scene Analysis가 실행되며, 여러분의 스크립트는 이 관문에 걸리는 횟수를 줄여 줍니다.
5단계: 돌아온 프레임 검증하기
Client App이 실행 중이고 자동 다운로드가 켜져 있으면(기본값) 각 프레임은 렌더팜에서 완료되는 즉시 여러분의 머신으로 내려옵니다. S3 access를 쓰는 경우에는 직접 실행하는 aws s3 sync가 로컬 폴더를 채웁니다. 어느 쪽이든 질문은 "모든 프레임이 온전히 도착했는지 어떻게 아는가"가 됩니다. 감시 스크립트는 로컬 파일만으로 이에 답합니다. 프레임은 두 번의 폴링 사이에 크기가 변하지 않고 파일 헤더가 유효할 때만 완료로 간주합니다.
# 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를 별도 파일로 기록한다면 패스마다 감시 스크립트를 하나씩 실행하세요. 그렇지 않으면 끝난 패스가 같은 번호의 누락된 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)
따라 할 만한 습관이 몇 가지 있습니다.
- 디스플레이 참조(display-referred) 프레임에서 인코딩하세요. PNG나 JPEG는 곧바로 리뷰용 영상으로 만들 수 있습니다. 리니어 EXR은 먼저 컬러 파이프라인(보통 OCIO 변환)을 거쳐야 하며, 그렇지 않으면 영상이 어둡고 밋밋해 보입니다.
- 매니페스트를 프레임과 함께 보관하세요. 6개월 뒤에 "이 렌더에 어떤 텍스처가 쓰였는가"는 파일 하나면 확인할 수 있습니다.
- 알림에는 사실을 담으세요. 프레임 수, 동기화가 필요했던 프레임, 총 용량, 리뷰 영상 경로를 스튜디오 채팅이나 트래커에 게시합니다.
- 로컬 사본을 공식 아카이브로 유지하세요. 저희 렌더팜의 파일은 작업을 실행하고 결과를 내려받는 데 필요한 동안 보관되며, 고정된 자동 삭제 기간은 없고 요청하시면 언제든 삭제합니다. 이것은 백업 계획이 아니며, 백업은 로컬 아카이브가 맡아야 합니다.
로컬 작업 예약하기
이 중 어느 것도 새 스케줄러를 필요로 하지 않습니다. Linux의 cron, macOS의 launchd, Windows의 작업 스케줄러(Task Scheduler)로 매일 저녁 "준비 완료"로 표시된 프로젝트에 대해 사전 점검, 매니페스트, AWS CLI 업로드를 실행하면, 누군가 제출하러 앉기 전에 파일이 이미 SRF Space에 올라와 있습니다. 감시 스크립트는 제출 직후에 시작하거나, 4단계의 핸드오프 시트로 채운 감시 목록을 훑는 스캐너로 실행할 수 있습니다.
고려해야 할 의존성이 하나 있습니다. 자동 다운로드는 Client App이 켜져 있고, 절전 상태가 아니며, 온라인인 머신에서 실행 중일 때만 이루어집니다. Windows에서는 Client App이 백그라운드 서비스를 설치하므로 메인 창을 닫아도 전송이 계속됩니다. Client App 또는 예약된 aws s3 sync는 밤새 켜져 있는 머신에서 실행하세요.
요약: 무엇을 어떻게 자동화할 것인가
| 단계 | 저희 렌더팜에서 오늘 스크립트화할 수 있나요? | 방법 |
|---|---|---|
| 씬 검증(누락 경로와 절대 경로) | 예 | DCC 안의 Python(bpy, maya.cmds, pymxs, c4d, hou) |
| 프로젝트 폴더 사전 점검 | 예 | 로컬 스크립트, 아카이브·씬 파일 누락·0바이트 파일이 있으면 차단 |
| 매니페스트와 변경 diff | 예 | 파일별 SHA-256, 프로젝트 옆에 JSON으로 저장 |
| 렌더팜으로 업로드 | 예, S3 access 사용 | Cloud Direct Connect의 키로 AWS CLI(aws s3 cp --recursive 또는 aws s3 sync) 실행. 수동 방법은 웹 업로드(약 2 GB 초과 시 느리고 약 5 GB 초과 시 불안정)와 Client App(이어받기 지원, 병렬 청크) |
| 작업 제출 | 아니요 | 웹 대시보드, Client App, 또는 3ds Max, Maya, Cinema 4D의 플러그인. 공개 API는 로드맵에 있음 |
| 완성된 프레임 다운로드 | 예, S3 access 사용 또는 자동 처리 | SuperRendersOutput/<jobId>/에서 aws s3 sync, 또는 Client App 자동 다운로드(프레임 단위), 또는 웹 다운로드 |
| 프레임 검증 | 예 | 로컬 감시 스크립트: 크기 안정, 헤더 유효, 전체 범위 존재 |
| 인코딩, 아카이브, 알림 | 예 | ffmpeg, 파일 복사, 스튜디오 채팅 또는 트래커 |
양쪽 끝을 자동화하고, 가운데 단계는 짧고 신중하게 유지하고, 돌아오는 모든 것을 검증하세요. 프로젝트 대부분이 Blender 씬이라면 저희 쪽에서 해당 작업이 어떻게 실행되는지는 Blender 클라우드 렌더팜 페이지에서, 수동 단계의 자세한 내용은 Client App 문서와 제출 플러그인 문서에서 다룹니다.
FAQ
Q: Python 스크립트로 프로젝트를 렌더팜에 업로드할 수 있나요?
A: 네, S3 access로 가능합니다. 계정의 Cloud Direct Connect에서 액세스 키를 생성하고, 그 키로 AWS CLI를 설정한 다음(리전 ap-southeast-1), 스크립트가 압축하지 않은 프로젝트 폴더를 Remote Directory로 aws s3 cp --recursive 또는 aws s3 sync 하도록 하세요. 깨진 프로젝트가 올라가지 않도록 먼저 사전 점검을 실행하세요. 그 뒤 작업을 제출하는 것은 여전히 수동입니다.
Q: S3 access와 Client App 중 무엇을 써야 하나요? A: 전송을 스크립트나 스케줄러로 실행해야 하거나 팀이 이미 Cyberduck 같은 S3 클라이언트를 쓰고 있다면 S3 access를 사용하세요. 사람이 직접 업로드한다면 Client App을 사용하세요. 연결이 끊긴 뒤 대용량 전송을 이어받고, 작업을 제출하며, 완료된 프레임을 완료되는 대로 자동으로 내려받습니다. 둘은 함께 쓰기 좋습니다. 스크립트 전송에는 S3 access를, 제출에는 Client App을 쓰면 됩니다.
Q: 파이프라인에서 렌더 작업을 제출할 수 있는 API나 SDK가 있나요? A: 현재는 없습니다. 작업은 웹 대시보드, Client App, 또는 3ds Max, Maya, Cinema 4D의 제출 플러그인에서 제출합니다. 프로그래밍 방식 제출을 위한 공개 API는 로드맵에 있지만 아직 사용할 수 없으므로, 여러분이 담당하는 구간을 중심으로 자동화를 구축하세요. 파이프라인이 이 때문에 막혀 있다면 지원팀에 사용 사례를 알려 주세요.
Q: 대용량 전송을 위한 SFTP나 FTP 접근을 제공하나요? A: 아니요. 저희는 업로드, 다운로드, 대여 머신을 위한 SFTP나 FTP 서비스를 운영하지 않습니다. 대용량 프로젝트는 이어받기가 가능한 병렬 청크로 업로드하는 Client App을 통하거나, Cyberduck 또는 AWS CLI를 사용하는 S3 access를 통해 전송합니다. 완성된 프레임은 Client App 자동 다운로드, 웹 다운로드, 또는 S3 access로 돌아옵니다.
Q: 모든 프레임이 돌아왔는지 어떻게 알 수 있나요?
A: Client App이 작업을 자동으로 내려받는 폴더, 또는 aws s3 sync가 기록하는 폴더에서 감시 스크립트를 실행하세요. 프레임은 크기가 두 번의 확인에 걸쳐 안정적이고 헤더가 유효할 때만 완료로 간주하고, 검증된 집합을 예상 범위와 비교합니다. 작업은 완료되었는데 프레임이 여전히 누락되어 있다면 Client App의 Sync output을 사용하거나 동기화를 다시 실행하세요.
Q: 시간을 아끼려고 업로드 전에 프로젝트를 압축해도 되나요? 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.



