가로 소스로 세로 영상 만들기
이 레시피를 마치면 16:9 영상을 휴대폰용 9:16 영상으로 바꿀 수 있습니다. 그림 전체를 자기 자신의 흐린 사본 위에 보여 주거나, 화면을 채우도록 잘라 가로로 훑는 두 가지 방법이 있습니다.
캔버스 설정
섹션 제목: “캔버스 설정”출력 크기는 프로젝트의 settings가 정합니다. 1080×1920, 30fps라면 다음과 같습니다.
"settings": { "width": 1080, "height": 1920, "frame_rate": { "num": 30, "den": 1 }, "sample_rate": 48000}프로젝트의 다른 곳에는 픽셀 값이 없습니다. 위치는 캔버스에 대한 비율이고, 길이는 짧은 변에 대한 비율입니다. width와 height만 바꾸면 같은 문서가 720×1280으로도 렌더링됩니다.
소스가 캔버스에 맞춰지는 방식
섹션 제목: “소스가 캔버스에 맞춰지는 방식”visual이 기본값(scale 1)인 클립은 소스를 캔버스 안에 맞춰(contain) 보여 줍니다. 소스 전체가 보이는 범위에서 가장 크게, 가운데에 놓습니다. 1080×1920 캔버스에 1920×1080 소스를 놓으면 너비 1080, 높이 607.5픽셀로 그려지고 위아래가 빕니다.
캔버스를 채우려면(cover) 소스 화면비를 캔버스 화면비로 나눈 값만큼 키웁니다(소스가 캔버스보다 가로로 넓은 경우). 16:9 소스를 9:16 캔버스에 채우면 (16/9) ÷ (9/16) = (16/9)² ≈ 3.1605입니다. 그러면 그림 높이가 1920픽셀, 너비는 약 3413픽셀이 되어 양옆이 잘립니다.
| 소스 | 캔버스 | 채우기 배율 |
|---|---|---|
| 16:9 | 9:16 | 3.1605 |
| 16:9 | 1:1 | 1.7778 |
| 16:9 | 4:5 | 2.2222 |
그림 뒤에 흐린 배경 깔기
섹션 제목: “그림 뒤에 흐린 배경 깔기”트랙 두 개가 같은 소스를 보여 줍니다. 아래 트랙은 캔버스를 채우고, 컴포지션으로 흐리고 어둡게 만듭니다. 위 트랙은 그림 전체를 맞춰서 보여 줍니다.
{ "schema_version": 1, "id": "vertical", "name": "Vertical from landscape", "settings": { "width": 1080, "height": 1920, "frame_rate": { "num": 30, "den": 1 }, "sample_rate": 48000 }, "sources": [ { "id": "coast", "locator": "asset://coast", "kind": "image" } ], "compositions": [ { "id": "backdrop", "output": "darker", "nodes": [ { "id": "clip", "op": { "type": "clip" } }, { "id": "blur", "op": { "type": "effect", "input": "clip", "effect": { "id": "alpha2.effect.gaussian-blur", "version": 1, "params": { "radius": { "mode": "constant", "value": { "type": "float", "value": 0.03 } } } } } }, { "id": "darker", "op": { "type": "effect", "input": "blur", "effect": { "id": "alpha2.effect.color-controls", "version": 1, "params": { "exposure": { "mode": "constant", "value": { "type": "float", "value": -1 } } } } } } ] } ], "timeline": { "tracks": [ { "id": "back", "name": "Blurred fill", "kind": "video", "clips": [ { "id": "fill", "source_id": "coast", "timeline_range": { "start": 0, "end": 480000 }, "source_range": { "start": 0, "end": 480000 }, "visual": { "scale": { "mode": "constant", "value": { "x": 3.1605, "y": 3.1605 } } }, "composition": { "id": "backdrop" } } ], "transitions": [] }, { "id": "front", "name": "Picture", "kind": "video", "clips": [ { "id": "picture", "source_id": "coast", "timeline_range": { "start": 0, "end": 480000 }, "source_range": { "start": 0, "end": 480000 } } ], "transitions": [] } ] }}backdrop 컴포지션은 클립을 alpha2.effect.gaussian-blur에 통과시킨 뒤 exposure −1인 alpha2.effect.color-controls에 통과시킵니다. 컴포지션이 클립의 그림을 만들고, 그다음 클립의 visual.scale이 결과를 키워 캔버스를 채웁니다. 두 클립이 같은 소스를 읽으므로 영상이라면 같은 프레임을 보여 줍니다.
잘라서 채우고 훑기
섹션 제목: “잘라서 채우고 훑기”그림으로 화면을 채우려면 채우는 클립만 남기고 움직이면 됩니다. position은 소스의 중심(기본 anchor)이 캔버스의 어디에 놓이는지 정합니다. 배율 3.1605에서 그림 너비는 캔버스 너비의 약 3.16배이므로, 중심을 약 −0.58에서 1.58 사이로 움직여도 가장자리가 드러나지 않습니다. position.x를 1.2에서 −0.2로 키프레임을 주면 4초 동안 그림의 왼쪽에서 오른쪽으로 훑습니다.
{ "schema_version": 1, "id": "vertical-pan", "name": "Vertical crop and pan", "settings": { "width": 1080, "height": 1920, "frame_rate": { "num": 30, "den": 1 }, "sample_rate": 48000 }, "sources": [ { "id": "coast", "locator": "asset://coast", "kind": "image" } ], "timeline": { "tracks": [ { "id": "picture", "name": "Picture", "kind": "video", "clips": [ { "id": "picture", "source_id": "coast", "timeline_range": { "start": 0, "end": 480000 }, "source_range": { "start": 0, "end": 480000 }, "visual": { "scale": { "mode": "constant", "value": { "x": 3.1605, "y": 3.1605 } }, "position": { "mode": "keyframes", "keyframes": [ { "time": 0, "value": { "x": 1.2, "y": 0.5 }, "interpolation": { "type": "cubic_bezier", "x1": 0.65, "y1": 0, "x2": 0.35, "y2": 1 } }, { "time": 480000, "value": { "x": -0.2, "y": 0.5 }, "interpolation": { "type": "hold" } } ] } } } ], "transitions": [] } ] }}export하기
섹션 제목: “export하기”alpha2-host export --project vertical.json \ --asset coast=coast.jpg \ --out vertical.mp4import { readFile } from "node:fs/promises";import { exportProject } from "@alpha2-sh/node";
const project = JSON.parse(await readFile("vertical.json", "utf8"));await exportProject({ project, assets: { coast: "coast.jpg" }, startTicks: 0, endTicks: 480_000, // 4초 frameRate: { num: 30, den: 1 }, output: "vertical.mp4",});alpha2.compose에는 두 레이아웃이 모두 노드로 있습니다. shorts 캔버스 프리셋은 9:16이고, Reframe은 영상을 흐리게 잘라 낸 자기 사본 위에 맞춰 놓으며, Media(..., fit="cover")는 잘라서 채웁니다.
import alpha2from alpha2 import compose as c
video = c.Video(c.Reframe("talk.mp4"), canvas="shorts")alpha2.export(video.compile(), "talk-vertical.mp4")