검증과 오류
This content is for v0.4. Switch to the latest version for up-to-date documentation.
프로젝트는 JSON 형태부터 프레임을 그릴 때 필요한 것까지 여러 층에서 검사됩니다. 이 페이지에서는 각 층과 실행 위치, 메시지의 모습을 설명합니다. 다 읽고 나면 잘못된 문서를 렌더링 전에 잡아내고, 오류가 나면 그 내용을 읽어 낼 수 있습니다.
1층: 형태
섹션 제목: “1층: 형태”JSON Schema(schema/project.v1.schema.json)는 형태만 기술합니다. JSON 타입, 필수 필드, 열거형과 태그된 값, 알 수 없는 필드의 거부입니다. 스키마가 거부하는 문서는 절대 유효한 프로젝트가 아닙니다. 하지만 스키마가 받아들이는 문서도 유효하지 않을 수 있습니다.
에디터나 자체 도구에서 활용하세요. 엔진은 스키마가 필요 없습니다. 문서를 파싱할 때 형태를 직접 검사합니다.
2층: 모델의 불변 조건
섹션 제목: “2층: 모델의 불변 조건”형태가 맞는 문서도 의미가 맞아야 합니다. 엔진의 모델은 미디어를 열지 않고 구간, 한도, 항목 간 참조, 키프레임 순서, 트랜지션 범위를 검사합니다. 같은 검사가 문서를 불러올 때(loadProject, Project::from_json)와 직접 요청할 때 실행됩니다.
import { validateProject, validateProjectJson } from "alpha2/project";
const problems = validateProject(project); // 유효하면 []. 예외를 던지지 않음if (problems.length > 0) console.error(problems.join("\n"));validateProject는 엔진의 검사를 TypeScript로 그대로 따라 하므로, 에디터가 문서를 불러오기 전에 거부할 수 있습니다. validateProjectJson(text)는 텍스트에서만 보이는 문제도 알려 줍니다. 크기 초과, 중복된 필드, 소수점이나 지수로 쓴 정수(1920.0), 127단계보다 깊은 중첩입니다. alpha2/builder의 ProjectBuilder.build()는 validateProject를 실행하고 문제가 있으면 예외를 던집니다.
@alpha2-sh/node는 호스트를 시작하기 전에 validateProject를 실행합니다. 유효하지 않은 프로젝트는 무엇이 잘못되었는지 problems에 담은 Alpha2ProjectValidationError로 거부됩니다.
import { Alpha2ProjectValidationError, exportProject } from "@alpha2-sh/node";
try { await exportProject(request);} catch (error) { if (error instanceof Alpha2ProjectValidationError) console.error(error.problems); else throw error;}import alpha2
problems = alpha2.validate_project(project) # 유효하면 []엔진의 검증기를 프로세스 안에서 그대로 실행하며, 메시지도 엔진의 것입니다.
let project = alpha2::Project::from_json(&json)?; // 파싱하고 검증project.validate()?; // 코드에서 만들거나 고친 프로젝트를 검사Project::validate는 처음 발견한 불변 조건 위반을 돌려줍니다.
메시지 읽기
섹션 제목: “메시지 읽기”메시지는 문제가 된 항목을 가리키고, 형태 문제라면 그 항목까지의 경로를 알려 줍니다. 다음은 validateProject가 내는 메시지의 예입니다.
| 문제 | 메시지 |
|---|---|
| 스키마에 없는 필드 | project.timeline.tracks[1].clips[0] has unknown field "duration" |
| 잘못된 타입 | project.settings.width must be integer |
| 끝이 시작보다 앞선 구간 | project.timeline.tracks[0].clips[0].timeline_range.end must not precede its start |
| 없는 소스를 가리키는 클립 | clip forest-clip refers to unknown source beach |
| 트랜지션 없이 겹친 클립 | clips coast-clip and forest-clip overlap without a transition |
| 순서가 어긋난 키프레임 | clip coast-clip has invalid visual properties |
loadProject, alpha2-host, Python이 내는 엔진 자체의 메시지는 같은 내용을 엔진의 표현으로 전하며, 형태 문제에는 JSON 텍스트 안의 위치가 붙습니다.
invalid project JSON: unknown field `duration`, expected one of `id`, `source_id`, `timeline_range`, ... at line 1 column 1276invalid project: clips coast-clip and forest-clip overlap without a covering transition on track photos3층: 프레임을 렌더링할 때
섹션 제목: “3층: 프레임을 렌더링할 때”어떤 것은 그것을 그리는 렌더러만 검사할 수 있으므로, 프로젝트를 불러올 때는 걸러지지 않습니다.
- 이펙트. 어떤 이펙트가 있는지는 문서가 아니라 렌더러의 레지스트리가 압니다. 등록되지 않은 이펙트나 정의의 범위를 벗어난 이펙트 파라미터를 그리는 프레임은
EFFECT_ERROR로 실패합니다. CPU 렌더러에서는 런타임 WGSL 이펙트도 같은 방식으로 실패합니다. - 폰트. 폰트를 하나도 등록하지 않은 채 텍스트나 자막을 보여 주는 프로젝트는
MISSING_INPUT(“the project shows text, but no fonts were registered”)으로 실패합니다. - 미디어.
renderAt은 실패하는 대신 프레임이 없었던 소스를 알려 줍니다(missingSources,missingFrames). export는waiting티켓으로 필요한 프레임을 요청합니다. 네이티브에서는alpha2-host conform과client.conform이 렌더링 없이 프로젝트의 미디어를 점검하며, Node.js에서 미디어가 준비되지 않은 export는Alpha2ConformError로 실패합니다.
유효한 프로젝트에도 실수일 가능성이 높은 부분이 있을 수 있습니다. 린터는 아무것도 막지 않고 이를 알려 줍니다.
import init, * as wasm from "alpha2/wasm";import { lintProject } from "alpha2/project";
await init();const issues = lintProject(wasm, project); // 프로젝트가 유효하지 않으면 loadProject처럼 예외를 던짐Python에서는 alpha2.lint_project(project)입니다. 각 항목에는 kind가 있습니다.
kind |
뜻 |
|---|---|
unreached_keyframe |
주인이 보이는 어떤 시각에도 쓰이지 않는 키프레임. 대개 시간 기준을 잘못 고른 경우입니다. |
hidden_clip |
위쪽의 불투명한 전체 화면 클립에 내내 가려지는 클립. |
short_transition |
어떤 프레임에도 보이지 않는 트랜지션. 한 프레임보다 짧거나, 한 프레임 길이인데 그리드에서 벗어난 경우입니다. |
off_frame_boundary |
프레임 사이에 놓인 경계. 그 변화는 다음 프레임에서야 보입니다. |
unused_source |
어떤 클립이나 도달 가능한 media 노드도 읽지 않는 소스. |
hdr_source |
색 파이프라인이 HDR을 거부하는 프로젝트의 HDR 소스. |
empty_subpath, paint_without_geometry |
아무것도 그리지 않는 셰이프. |
예를 들어 자신을 보여 주는 클립의 끝을 넘어서 키프레임한 셰이프 제너레이터는 다음과 같이 보고됩니다.
{ "kind": "unreached_keyframe", "owner": { "type": "source", "source": "dot" }, "property": "items[0].center", "time": 480000 }엔진은 모든 문서에 고정된 한도를 적용합니다. 트랙 256개, 트랙당 클립 4,096개, 전체 클립 100,000개, 64 MiB의 JSON 문서, 한 변 최대 16,384픽셀·전체 최대 67,108,864픽셀의 캔버스 등입니다. 한도를 넘는 문서는 불러올 때 한도 이름을 담은 오류로 거부됩니다. 이 숫자들은 alpha2/project의 TypeScript 상수와 Python 상수로도 제공되므로, 보내기 전에 미리 확인할 수 있습니다. 전체 목록은 한도에 있습니다.
