콘텐츠로 이동

프로젝트 모델

이 페이지에서는 프로젝트 문서를 이루는 부분들과 그 부분들이 서로를 참조하는 방식을 살펴봅니다. 다 읽고 나면 어떤 프로젝트든 읽을 수 있고, 각 필드가 어디에 속하는지 알 수 있습니다.

  • 디렉터리project
    • schema_version 항상 1
    • id, name
    • settings 캔버스 크기, 프레임 레이트, 샘플 레이트, 배경, 색
    • sources[] 미디어, 제너레이터, 컴포지션 소스
    • compositions[] 이미지 연산 그래프
    • effect_resources[] 이펙트가 읽는 LUT
    • 디렉터리timeline
      • 디렉터리tracks[] video, audio, caption
        • clips[] 시간 구간 위에 놓인 소스
        • transitions[] 겹친 클립 사이의 트랜지션
        • captions 자막 트랙의 큐와 스타일
    • audio 마스터 버스

schema_version, id, name, settings, sources, timeline은 필수입니다. 나머지 필드는 모두 기본값이 있어 생략할 수 있습니다. 알 수 없는 필드는 거부됩니다.

이 프로젝트에는 소스 세 개, 컴포지션 하나, 종류가 다른 트랙 세 개가 있습니다.

{
"schema_version": 1,
"id": "model-tour",
"name": "Model tour",
"settings": { "width": 1280, "height": 720, "frame_rate": { "num": 30, "den": 1 }, "sample_rate": 48000 },
"sources": [
{ "id": "coast", "kind": "image", "locator": "asset://coast" },
{ "id": "music", "kind": "audio", "locator": "asset://music" },
{
"id": "label",
"kind": "generated",
"generator": {
"type": "text",
"text": "Coast",
"style": { "font_family": "Hanken Grotesk", "font_size": 0.08 }
}
}
],
"compositions": [
{
"id": "soft",
"nodes": [
{ "id": "in", "op": { "type": "clip" } },
{
"id": "blur",
"op": {
"type": "effect",
"input": "in",
"effect": { "id": "alpha2.effect.gaussian-blur", "version": 1 }
}
}
],
"output": "blur"
}
],
"timeline": {
"tracks": [
{
"id": "picture",
"name": "Picture",
"kind": "video",
"clips": [
{
"id": "coast-clip",
"source_id": "coast",
"timeline_range": { "start": 0, "end": 480000 },
"source_range": { "start": 0, "end": 480000 },
"composition": { "id": "soft" }
},
{
"id": "label-clip",
"source_id": "label",
"timeline_range": { "start": 480000, "end": 720000 },
"source_range": { "start": 0, "end": 240000 }
}
]
},
{
"id": "subtitles",
"name": "Subtitles",
"kind": "caption",
"captions": {
"style": { "font_family": "Hanken Grotesk" },
"cues": [
{
"timeline_range": { "start": 60000, "end": 360000 },
"text": "Waves on the coast."
}
]
}
},
{
"id": "score",
"name": "Score",
"kind": "audio",
"clips": [
{
"id": "music-clip",
"source_id": "music",
"timeline_range": { "start": 0, "end": 720000 },
"source_range": { "start": 1200000, "end": 1920000 }
}
]
}
]
}
}

위에서부터 차례로 읽어 보면 다음과 같습니다.

  1. settings: 30fps의 1280x720 캔버스이고, 오디오는 48kHz로 믹싱합니다. 프레임 레이트는 분수(num/den)이므로 29.97fps는 { "num": 30000, "den": 1001 }입니다.
  2. sources: coast는 이미지, music은 오디오 파일이며 둘 다 호스트가 해석하는 locator가 있습니다. label은 제너레이터 소스입니다. 엔진이 generator를 보고 직접 그리므로 locator가 없습니다.
  3. compositions: soft는 노드 두 개로 된 그래프입니다. 클립 자신의 그림을 받고, 그 그림에 가우시안 블러를 겁니다. output은 클립이 보여 줄 노드를 가리킵니다.
  4. 트랙 picture(kind video): coast-clip이 soft를 거친 사진을 4초 동안 보여 줍니다. 이어서 label-clip이 텍스트를 2초 동안 보여 줍니다.
  5. 트랙 subtitles(kind caption): 0.5초부터 3초까지 큐 하나가 있습니다. 자막 트랙에는 클립 대신 큐가 들어갑니다.
  6. 트랙 score(kind audio): music-clip이 파일의 10초 지점부터(source_range) 타임라인 시작에 맞춰(timeline_range) 음악을 재생합니다.

ProjectSettings는 출력 전체에 적용됩니다. 픽셀 단위의 width와 height, frame_rate, sample_rate가 있고, 그 밖에 background(모든 레이어 아래에 깔리는 불투명한 색, 기본값은 검정), blend_space(블렌드 모드를 계산하는 공간, 기본값은 linear_light), color(HDR 소스를 다루는 방식, 색과 HDR 참고)가 있습니다.

소스는 클립이 id로 참조하는 리소스입니다. kind가 소스의 종류를 나타냅니다.

kind 무엇인가 누가 공급하는가
video 비디오 스트림. 오디오가 있을 수도 있습니다. 비디오 트랙의 클립 소리를 믹스에 넣으려면 has_audio: true를 지정합니다. 호스트가 디코딩
audio 오디오 스트림 호스트가 디코딩
image 정지 이미지 호스트가 디코딩
generated generator로 그리는 채우기, 셰이프, 텍스트, 레이아웃 그림. 제너레이터 참고 엔진이 그림
composition 프로젝트의 컴포지션 하나를 소스로 쓰는 것. 소스 시간을 자신의 시간으로 삼아 그립니다. 엔진이 그리고, 노드가 읽는 미디어는 호스트가 공급

locator는 엔진이 절대 열지 않는 불투명한 URI입니다. 브라우저에서는 앱이 소스의 id로 프레임을 업로드하고, 네이티브에서는 id를 파일에 대응시킵니다(--asset coast=coast.jpg).

소스에는 그 밖에도 provider(SVG, 애니메이션 이미지, Lottie, OpenEXR, 이미지 시퀀스. 호스트 자체 디코더가 읽지 못하는 형식의 프레임을 공급하는 확장을 지정), 프로젝트가 기록해 둔 미디어의 fingerprint, 비디오의 색 태그를 덮어쓰는 **color_metadata**를 둘 수 있습니다.

타임라인은 트랙의 목록입니다. 시각적 트랙은 목록 순서대로 뒤에서 앞으로 그려집니다. 트랙에는 kind가 하나 있습니다.

  • video: 합성되는 그림. 클립에는 비디오, 이미지, 제너레이터, 컴포지션 소스를 쓸 수 있습니다.
  • audio: 믹싱되는 소리.
  • caption: 시간이 지정된 텍스트. 앞에 있는 트랙들 위에, 뒤에 있는 트랙들 아래에 그려집니다. 클립 없이 captions를 가집니다. 자막 참고.

클립은 두 구간에 걸쳐 소스를 보여 줍니다.

  • timeline_range: 프로젝트 타임라인에서 클립이 놓이는 구간.
  • source_range: 소스에서 읽어 오는 구간.

둘 다 틱 단위의 반열린 구간 [start, end)입니다. 두 구간의 길이가 다르면 클립이 빠르게 또는 느리게 재생됩니다. time_map으로 역재생, 한 순간 정지, 반복도 할 수 있습니다. 시간과 틱을 참고하세요.

한 트랙은 한 번에 클립 하나만 보여 줍니다. 한 트랙의 클립은 트랜지션이 이어 주는 구간에서만 겹칠 수 있습니다. 레이어를 쌓으려면 레이어마다 트랙을 하나씩 쓰거나, 레이어를 합치는 컴포지션 하나를 쓰세요.

시각적 클립에는 구간 외에도 visual(위치, 앵커, 크기, 회전, 불투명도), composition, masks, matte, blend_mode, cache 힌트를 둘 수 있습니다. 모든 클립에는 audio 설정이 있습니다.

컴포지션은 output이 하나인, 순환 없는 이미지 연산 그래프입니다. 클립은 "composition": { "id": ... }으로 컴포지션을 사용하며, 지정하지 않으면 소스를 그대로 보여 줍니다. 노드는 클립의 그림을 받거나, 다른 소스를 읽거나, 제너레이터를 그리거나, 이펙트와 트랜지션을 적용하거나, 배치하고 합치고 매트와 마스크를 씌울 수 있습니다. 이펙트와 컴포지션을 참고하세요.

effect_resources는 이펙트가 읽는 미디어 아닌 데이터입니다. 지금은 lut3d 한 종류뿐이며, 보통 .cube 파일로 만드는 3D LUT입니다. 이펙트는 resources에서 이를 지정하고, 파일은 호스트가 공급합니다(명령줄에서는 --effect-asset, Node.js에서는 effectAssets).

최상위 audio는 마스터 버스입니다. 모든 트랙을 합친 소리에 게인, 이펙트, 마지막 피크 리미터를 적용합니다. 오디오를 참고하세요.