SRT 파일로 자막 만들기
This content is for v0.4. Switch to the latest version for up-to-date documentation.
이 레시피를 마치면 .srt나 .vtt 파일을 자막(caption) 트랙으로 가져와 스타일을 입힐 수 있습니다. 파일은 엔진이 파싱하므로 브라우저, Node.js, Python이 같은 파일에서 같은 큐를 읽습니다.
파일 가져오기
섹션 제목: “파일 가져오기”다음과 같은 자막 파일이 있다고 합시다.
100:00:00,300 --> 00:00:02,000Every frame is rendered on the GPU.
200:00:02,200 --> 00:00:04,000The same project, in every target.alpha2/captions의 parseCaptions는 WebAssembly로 된 엔진의 파서로 이 파일을 읽고, captionTrack은 큐를 트랙으로 감쌉니다.
import init, * as wasm from "alpha2/wasm";import { captionTrack, parseCaptions } from "alpha2/captions";
await init();const text = await (await fetch("/talk.srt")).text();const { rows, skipped } = parseCaptions(wasm, text, "srt"); // .vtt 파일이면 "webvtt"
const style = { font_family: "Hanken Grotesk", font_size: 0.055, background: { color: "#000000b3", padding: 0.3 },};const tracks = rows.map((cues, i) => captionTrack(`subs-${i}`, "Subtitles", cues, style));project.timeline.tracks.push(...tracks);rows의 한 행은 트랙 하나에 들어갈 큐입니다. 한 행의 큐는 서로 겹치지 않으므로, 큐가 겹치는 파일은 행이 여러 개 나옵니다. 행마다 자막 트랙을 하나씩 추가하십시오.skipped는 파서가 읽지 못한 블록 수입니다. 마크업(<b>,<i>, WebVTT 태그)은 버립니다.- 타임스탬프는 정확하게 변환됩니다. 1ms는 120틱이므로
00:00:00,300은36000이 됩니다.
이렇게 만든 트랙을 사진 위에 얹은 프로젝트입니다.
{ "schema_version": 1, "id": "captions-srt", "name": "Captions from SRT", "settings": { "width": 1280, "height": 720, "frame_rate": { "num": 30, "den": 1 }, "sample_rate": 48000 }, "sources": [ { "id": "forest", "locator": "asset://forest", "kind": "image" } ], "timeline": { "tracks": [ { "id": "picture", "name": "Picture", "kind": "video", "clips": [ { "id": "photo", "source_id": "forest", "timeline_range": { "start": 0, "end": 540000 }, "source_range": { "start": 0, "end": 540000 } } ], "transitions": [] }, { "id": "subs", "name": "Subtitles", "kind": "caption", "clips": [], "captions": { "style": { "font_family": "Hanken Grotesk", "font_size": 0.055, "background": { "color": "#000000b3", "padding": 0.3 } }, "cues": [ { "timeline_range": { "start": 36000, "end": 240000 }, "text": "Every frame is rendered on the GPU." }, { "timeline_range": { "start": 264000, "end": 480000 }, "text": "The same project, in every target." } ] } } ] }}자막 트랙은 kind: "caption"이고, 클립 없이 style과 cues를 담은 captions 객체를 가집니다. 생략한 스타일 필드는 기본값을 따릅니다. 가운데 정렬, position 0.5, 0.92에 아래쪽 가운데(anchor 0.5, 1)를 맞추고, 흰색, 그림 짧은 변의 0.05인 font_size, max_width 0.9에서 줄바꿈합니다. 여기서는 폰트와 조금 더 큰 크기, 그리고 background를 더했습니다. background는 줄마다 뒤에 깔리는 상자이며, padding은 폰트 크기에 대한 비율입니다.
박스 대신 외곽선 쓰기
섹션 제목: “박스 대신 외곽선 쓰기”박스를 깔면 어떤 그림 위에서도 자막이 잘 읽힙니다. outline은 그림을 덜 가리면서 같은 효과를 냅니다. 글리프 둘레에 띠를 그려 글자 뒤에 깔며, width는 폰트 크기에 대한 비율입니다(최대 0.5).
{ "schema_version": 1, "id": "captions-outline", "name": "Outlined captions", "settings": { "width": 1280, "height": 720, "frame_rate": { "num": 30, "den": 1 }, "sample_rate": 48000 }, "sources": [ { "id": "wall", "locator": "asset://wall", "kind": "image" } ], "timeline": { "tracks": [ { "id": "picture", "name": "Picture", "kind": "video", "clips": [ { "id": "photo", "source_id": "wall", "timeline_range": { "start": 0, "end": 300000 }, "source_range": { "start": 0, "end": 300000 } } ], "transitions": [] }, { "id": "subs", "name": "Subtitles", "kind": "caption", "clips": [], "captions": { "style": { "font_family": "Hanken Grotesk", "font_size": 0.08, "font_weight": 700, "position": { "x": 0.5, "y": 0.85 }, "outline": { "color": "#000000", "width": 0.12 } }, "cues": [ { "timeline_range": { "start": 36000, "end": 144000 }, "text": "Every frame" }, { "timeline_range": { "start": 144000, "end": 240000 }, "text": "is rendered live." } ] } } ] }}이 스타일은 굵기를 bold로, 크기를 조금 크게 하고, 폰트 크기의 0.12 너비인 검은 outline을 두르며, 텍스트를 조금 위로 올립니다(position 0.5, 0.85). 트랙의 모든 큐는 이 한 스타일로 그려집니다. 자막 트랙에는 style이 하나뿐입니다.
export하기
섹션 제목: “export하기”alpha2-host export --project captions.json \ --asset forest=forest.jpg \ --font HankenGrotesk.ttf \ --out captions.mp4기본 범위는 타임라인에서 마지막으로 보이는 것이 끝나는 지점까지이며, 자막 큐도 포함합니다.
import { readFile } from "node:fs/promises";import { exportProject } from "@alpha2-sh/node";
const project = JSON.parse(await readFile("captions.json", "utf8"));await exportProject({ project, assets: { forest: "forest.jpg" }, fonts: ["HankenGrotesk.ttf"], startTicks: 0, endTicks: 540_000, // 4.5초 frameRate: { num: 30, den: 1 }, output: "captions.mp4",});alpha2.compose는 노드 하나로 자막 파일을 읽어 영상 위에 얹습니다. CaptionedVideo는 영상을 캔버스에 맞추고(기본값 cover) 그 위에 자막을 놓습니다. Captions는 .srt나 .vtt 파일 경로와 style을 받습니다. style은 outline(기본값), boxed, bar-bottom, bold-center 중 하나입니다.
import alpha2from alpha2 import compose as c
video = c.Video(c.CaptionedVideo("talk.mp4", c.Captions("talk.srt", style="boxed")))compiled = video.compile(fonts=["HankenGrotesk.ttf"])alpha2.export(compiled, "talk-captioned.mp4")컴파일할 때 영상의 크기와 길이는 호스트의 conform에 묻습니다(GPU는 필요 없습니다). 음성 인식 도구가 준 단어 시간이 있으면 파일 대신 words로 넘기십시오. 단어는 max_chars 글자까지의 큐로 묶입니다.
words = [ {"start": 0.0, "end": 0.5, "text": "Sing"}, {"start": 0.5, "end": 1.0, "text": "along"},]captions = c.Captions(words=words, style="bold-center")함께 보기
섹션 제목: “함께 보기”- 자막: 큐, 트랙, 스타일.
- 자막 스키마: 자막의 모든 필드.
- Python:
alpha2.compose와 다른 노드. - 애니메이션 로어 서드: 레이아웃 상자 안의 텍스트.
