Add remotion-video skill #1
No files matched your search
@@ -76,6 +76,8 @@ export const Hello = ({ title }: { title: string }) => {
|
|||||||
- Rendering needs Chromium and ffmpeg (Remotion installs/handles these); first render can be slow.
|
- Rendering needs Chromium and ffmpeg (Remotion installs/handles these); first render can be slow.
|
||||||
|
|
||||||
## Common problems
|
## Common problems
|
||||||
|
- **Can't download the browser (no internet / locked-down machine)**: point Remotion at an installed Chromium:
|
||||||
|
`npx remotion render <Id> out/video.mp4 --browser-executable=/path/to/chromium --chrome-mode=chrome-for-testing`
|
||||||
- **Blank/white frames**: an asset path is wrong; use `staticFile()`.
|
- **Blank/white frames**: an asset path is wrong; use `staticFile()`.
|
||||||
- **Flicker**: an image or font not loaded; use `<Img>` and `@remotion/google-fonts`.
|
- **Flicker**: an image or font not loaded; use `<Img>` and `@remotion/google-fonts`.
|
||||||
- **Slow render**: lower resolution/fps while testing, or use `--concurrency`.
|
- **Slow render**: lower resolution/fps while testing, or use `--concurrency`.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { AbsoluteFill, useCurrentFrame, useVideoConfig } from "remotion";
|
|||||||
|
|
||||||
type Word = { text: string; start: number; end: number }; // seconds
|
type Word = { text: string; start: number; end: number }; // seconds
|
||||||
|
|
||||||
export const Captions = ({ words }: { words: Word[] }) => {
|
export const Captions = ({ words, background = "#111" }: { words: Word[]; background?: string }) => {
|
||||||
const frame = useCurrentFrame();
|
const frame = useCurrentFrame();
|
||||||
const { fps } = useVideoConfig();
|
const { fps } = useVideoConfig();
|
||||||
const t = frame / fps;
|
const t = frame / fps;
|
||||||
@@ -19,7 +19,7 @@ export const Captions = ({ words }: { words: Word[] }) => {
|
|||||||
const visible = words.slice(Math.floor(i / 5) * 5, Math.floor(i / 5) * 5 + 5);
|
const visible = words.slice(Math.floor(i / 5) * 5, Math.floor(i / 5) * 5 + 5);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AbsoluteFill style={{ justifyContent: "flex-end", alignItems: "center", paddingBottom: 200 }}>
|
<AbsoluteFill style={{ backgroundColor: background, justifyContent: "flex-end", alignItems: "center", paddingBottom: 200 }}>
|
||||||
<div style={{ fontSize: 72, fontWeight: 800, color: "white", textShadow: "0 4px 12px black", textAlign: "center", maxWidth: "80%" }}>
|
<div style={{ fontSize: 72, fontWeight: 800, color: "white", textShadow: "0 4px 12px black", textAlign: "center", maxWidth: "80%" }}>
|
||||||
{visible.map((w, k) => (
|
{visible.map((w, k) => (
|
||||||
<span key={k} style={{ color: t >= w.start && t < w.end ? "#ffd400" : "white", marginRight: 16 }}>
|
<span key={k} style={{ color: t >= w.start && t < w.end ? "#ffd400" : "white", marginRight: 16 }}>
|
||||||
@@ -34,4 +34,5 @@ export const Captions = ({ words }: { words: Word[] }) => {
|
|||||||
|
|
||||||
Tips
|
Tips
|
||||||
- Get word times from a transcription tool (e.g. `@remotion/captions` or Whisper) and save them as JSON in `public/`.
|
- Get word times from a transcription tool (e.g. `@remotion/captions` or Whisper) and save them as JSON in `public/`.
|
||||||
- Layer it over the video: `<AbsoluteFill><OffthreadVideo src={staticFile("clip.mp4")} /><Captions words={words} /></AbsoluteFill>`.
|
- `background` is the backdrop when there is no video. Pass `"transparent"` when layering over a video.
|
||||||
|
- Layer it over the video: `<AbsoluteFill><OffthreadVideo src={staticFile("clip.mp4")} /><Captions words={words} background="transparent" /></AbsoluteFill>`.
|
||||||
Reference in new issue
Block a user