콘텐츠로 이동

Remotion에서 넘어오기

Remotion을 알고 있다면, 이 페이지에서 Remotion의 개념을 alpha2의 개념에 대응시키고, 같은 영상을 두 방식으로 작성해 보고, 둘이 어디서 다른지 확인할 수 있습니다.

Remotion에서 영상은 React 컴포넌트입니다. Remotion은 그것을 브라우저에서 프레임마다 렌더링하므로, 브라우저가 그릴 수 있는 것(HTML, CSS, SVG, canvas, WebGL)은 무엇이든 그림에 넣을 수 있고, 여러분의 코드가 프레임마다 실행됩니다.

alpha2에서 영상은 JSON 문서입니다. 소스, 트랙, 클립에 이펙트, 트랜지션, 텍스트·도형·flexbox/grid 레이아웃을 그리는 제너레이터, 자막, 오디오 믹서가 더해집니다. 이 문서를 GPU 엔진이 렌더링합니다. 프레임마다 실행되는 사용자 코드는 없고, 움직임은 문서 안의 키프레임으로 씁니다. 그래서 문서를 저장하고, diff하고, 검증하고, 생성할 수 있으며, 브라우저, Node.js, Python, Rust, CLI에서 같은 프레임이 나옵니다.

Remotion alpha2 참고
<Composition>(width, height, fps, durationInFrames) 프로젝트와 그 settings(width, height, frame_rate) 길이는 타임라인이 끝나는 지점입니다. frame_rate는 유리수이며, 29.97은 { "num": 30000, "den": 1001 }입니다.
프레임 번호 틱(tick) 단위 시간, 1초에 120,000 틱은 흔히 쓰는 프레임 레이트에서 모두 정확하므로, 프로젝트의 시간이 프레임 레이트에 묶이지 않습니다.
<AbsoluteFill> 트랙 위의 클립, 또는 레이아웃 제너레이터의 root 클립의 그림은 캔버스 전체입니다. 레이아웃의 루트 상자가 곧 캔버스이며, justify_content, align_items, padding으로 배치합니다.
<Sequence from durationInFrames> 클립의 timeline_range source_range는 소스의 어느 부분을 재생할지 정합니다.
<Series> 한 트랙에 차례로 놓인 클립
JSX 순서에 따른 겹침 트랙 순서 뒤 트랙이 위에 그려집니다. 한 트랙은 한 번에 클립 하나만 보여 줍니다.
useCurrentFrame() + interpolate() 키프레임: { "mode": "keyframes", "keyframes": [...] } 키프레임의 interpolation(linear, hold, cubic_bezier)이 그 뒤 구간의 모양을 정합니다.
Easing.bezier(...) { "type": "cubic_bezier", "x1", "y1", "x2", "y2" } CSS cubic-bezier()와 같은 곡선입니다.
<Img>, <Video>, <OffthreadVideo> image, video 소스 앱이나 호스트가 디코딩합니다.
<Audio> 오디오 트랙과 클립 게인, 팬, 페이드, 이펙트, 더킹, 마스터 버스.
CSS transform, opacity 클립의 visual(position, anchor, scale, rotation_degrees, opacity) 레이아웃 상자의 translate, scale, rotation_degrees, opacity도 있습니다.
CSS 필터, 커스텀 셰이더 이펙트(내장 62개) 또는 런타임 WGSL 이펙트
@remotion/transitions 트랙 위 두 클립 사이의 트랜지션(내장 122개)
<Player> 브라우저 플레이어, 또는 @alpha2-sh/react의 캔버스
renderMedia() @alpha2-sh/node의 exportProject(), 또는 alpha2-host export
renderStill() @alpha2-sh/node의 still(), 또는 Python의 alpha2.still
Input props 직접 작성한 코드로 JSON 생성 템플릿은 문서를 돌려주는 함수입니다.

흰 배경에 제목이 0.5초부터 1.5초까지 서서히 나타나며 떠오르는 3초짜리 1080p 영상입니다.

import { AbsoluteFill, Composition, Easing, interpolate, Sequence, useCurrentFrame } from "remotion";
const Title = () => {
const frame = useCurrentFrame();
const opacity = interpolate(frame, [0, 30], [0, 1], { extrapolateRight: "clamp" });
const rise = interpolate(frame, [0, 30], [54, 0], {
easing: Easing.bezier(0.2, 0, 0, 1),
extrapolateRight: "clamp",
});
return (
<AbsoluteFill style={{ justifyContent: "center", alignItems: "center" }}>
<h1 style={{ opacity, transform: `translateY(${rise}px)` }}>Hello from alpha2</h1>
</AbsoluteFill>
);
};
export const Root = () => (
<Composition
id="Title"
width={1920}
height={1080}
fps={30}
durationInFrames={90}
component={() => (
<AbsoluteFill style={{ backgroundColor: "white" }}>
<Sequence from={15}>
<Title />
</Sequence>
</AbsoluteFill>
)}
/>
);

alpha2 버전에서 제목은 단색 fill 위, 자기 트랙에 놓인 text 제너레이터입니다. 클립은 <Sequence from={15}>처럼 0.5초(60000틱)에 시작합니다. opacity와 position 키프레임이 두 interpolate 호출과 같은 일을 합니다. 클립의 visual 키프레임은 타임라인 시간 기준이므로 클립 시작인 0.5초에서 시작합니다. 첫 키프레임 전과 마지막 키프레임 뒤에는 가장 가까운 키의 값이 유지되며, extrapolateRight: "clamp"와 같습니다. y의 0.55에서 0.5까지는 캔버스 높이의 5%로, Remotion 버전의 54픽셀에 해당합니다.

import { exportProject } from "@alpha2-sh/node";
await exportProject({
project, // 위의 문서
assets: {}, // 파일 없음: 모든 소스가 생성 소스
fonts: ["HankenGrotesk.ttf"],
startTicks: 0,
endTicks: 360_000,
frameRate: { num: 30, den: 1 },
output: "title.mp4",
});

Remotion이 헤드리스 브라우저를 구동하는 자리에, alpha2-host는 GPU(Vulkan, Metal, Direct3D 12)로, GPU가 없으면 CPU로 렌더링하고 FFmpeg로 인코딩하는 네이티브 프로그램입니다. 서버에서 렌더링하기를 참고하십시오.

  • React나 DOM을 렌더링하지 않습니다. 그림 안에 HTML, CSS 캐스케이드, SVG DOM, canvas API가 없습니다. 레이아웃 제너레이터가 텍스트와 도형을 담은 flexbox·grid 상자를 지원하고 SVG와 Lottie 파일을 소스로 쓸 수 있지만, 임의의 웹 콘텐츠는 그릴 수 없습니다.
  • 프레임마다 코드를 실행하지 않습니다. 렌더링 중에 프레임 번호로 값을 계산할 수 없습니다. 미리 계산해 키프레임으로 쓰거나(레이아웃 text는 문자열 키프레임을 받으므로 카운터는 hold 키 목록이 됩니다), 픽셀 단위 작업은 런타임 WGSL 이펙트로 작성하십시오.
  • 렌더링 중에 데이터를 가져오지 않습니다. 렌더링에 필요한 것은 모두 문서에 있거나 함께 넘겨집니다(에셋 파일, 폰트, 이펙트 리소스).
  • 폰트는 넘겨준 파일만 씁니다. 엔진은 시스템 폰트를 읽지 않습니다. 넘겨준 폰트 중 어느 것에도 없는 패밀리를 지정한 텍스트는 넘겨준 폰트의 대체 순서대로 그려지며, 네이티브 export는 그 패밀리를 unmatchedFontFamilies에 알려 줍니다.

그 대신 얻는 것은 어디서나 똑같이 로드되는 스키마 검사 문서, 브라우저 프리뷰와 서버 export에서 같은 프레임, 그리고 서버에서 브라우저 없이 하는 GPU 렌더링입니다.