Felo API PlatformFelo API Platform

Nội dung

Tạo video motion graphics bằng HTML và Opus 5.5

Viết beat sheet, nhờ Opus 5.5 viết cảnh HTML tất định qua Felo API, chụp frame bằng Playwright và mã hóa MP4 bằng ffmpeg. Chạy trong WorkBuddy, ChatGPT có thực thi mã, Codex, Pi Agent hoặc Claude Code.

Thời gian45 phútMứcTrung cấpCập nhật2026-10-30
Dành cho aiCreatorMotion designerNhà phát triển độc lập

Sao chép prompt

Thay các trường trong ngoặc vuông rồi dán vào Claude Code, Codex hoặc AI có quyền truy cập terminal. Nó cài skill Felo, hỏi trước khi dùng credit và chạy quy trình.

Tạo video [thời lượng] giây, định dạng [dọc / ngang], về [ý tưởng].
Phong cách: [phong cách]. Độc giả: [độc giả]. Âm thanh: [không / bản nhạc có giấy phép tại ./audio.mp3 / TTS].

Bạn chạy trong thư mục có terminal và [WorkBuddy / ChatGPT có thực thi mã / Codex / Pi Agent / Claude Code]. Nếu không thể chạy Node và trình duyệt headless, hãy dừng lại và nói với tôi thay vì giả vờ đã render.

Thực hiện theo thứ tự:
1. Viết storyboard 3–6 nhịp với giây bắt đầu và kết thúc chính xác.
2. Bước HTML: gọi Claude Opus 5.5 qua Felo API. Dùng ID mô hình claude-opus-5-5 và FELO_API_KEY của tôi. Không yêu cầu tôi mua gói Claude hay dùng khóa Anthropic khác.
3. Yêu cầu Opus tạo một tệp HTML duy nhất, tự chứa: đặt window.DURATION và mở async window.seek(t). Không tài nguyên ngoài, CDN, Date.now(), requestAnimationFrame(), chuyển cảnh CSS hay bộ hẹn giờ. Đặt seed cho mọi giá trị ngẫu nhiên để cùng một t luôn vẽ cùng một khung hình.
4. Xem trước tại t = 0, 25%, 50%, 75% và khung cuối. Kiểm tra tràn, cắt, phông chữ và vùng an toàn trước khi render toàn bộ.
5. Render từng khung bằng Playwright, mã hóa H.264 bằng ffmpeg và ghép âm thanh nếu có.
6. Hiển thị khung đầu, khung cuối và đường dẫn cuối. Không công bố.

Quy tắc:
- Trước khi tiêu tín dụng, hiển thị các lệnh gọi Felo API và ước tính token.
- Chỉ dùng văn bản tôi cung cấp, hoặc ghi rõ văn bản giữ chỗ do bạn bịa.
- Không dùng tư liệu, nhạc, logo hay phông chữ có bản quyền. Chỉ phông hệ thống và hình do bạn tạo.
- Giữ video cuối dưới 30 giây, trừ khi tôi yêu cầu bản dài.
- Ghi mọi thứ vào ./video/ và tóm tắt các lệnh đã chạy.

Bản sao cũng gồm các bước cài đặt và quy tắc an toàn.

Bạn nhận được gì

Kết quả mẫu của một lần chạy. Không phải tạo trực tiếp.

Ví dụ báo cáo render (trích)

Báo cáo render

Cảnh: video/scene.html (18 KB) Thời lượng: 12 giây · 1080x1920 · 30 fps · 360 khung Kiểm tra: window.DURATION = 12 · có seek(t) · không Date.now / rAF / hẹn giờ

Xem trước: preview-0ms.png · preview-3000ms.png · preview-6000ms.png · preview-9000ms.png Mã hóa: video/video.mp4 (H.264, 360 khung) Âm thanh: video/final.mp4 (AAC, 12,0 giây)

Các lệnh gọi chính xác

Dành cho lập trình viên: cùng quy trình dưới dạng mã, theo thứ tự chạy.

Hiện lệnh gọi API thật
  1. Viết beat sheet trước

    Đặt thời lượng và 3–6 beat, mỗi beat có bắt đầu, kết thúc, chữ trên màn hình và thay đổi hình ảnh chính.

  2. Tạo cảnh HTML bằng Opus 5.5

    Trỏ Anthropic SDK vào base URL Felo, dùng claude-opus-5-5 và chỉ yêu cầu HTML với window.DURATION và async seek(t).

    generate-scene.ts
    import { mkdir, writeFile } from "node:fs/promises";
    import Anthropic from "@anthropic-ai/sdk";
    
    const SYSTEM = `You write a single, self-contained HTML video scene.
    Requirements:
    - 1080x1920 (or 1920x1080), no external assets, system fonts only.
    - set window.DURATION = <seconds>.
    - expose async window.seek(t) that draws the frame for time t.
    - no Date.now(), no requestAnimationFrame(), no CSS transitions, no timers.
    - seed every random value; the same t must always produce the same frame.
    - return only the HTML file, no markdown fences.`;
    
    const brief = `12-second vertical motion graphic about [idea].
    Beats: [0-3s hook], [3-7s point], [7-10s proof], [10-12s CTA].
    Palette: [colors]. Type: system sans. Keep text inside a 64px safe area.`;
    
    const anthropic = new Anthropic({
      apiKey: process.env.FELO_API_KEY,
      baseURL: "https://openapi.felo.ai/api",
    });
    
    const message = await anthropic.messages.create({
      model: "claude-opus-5-5",
      max_tokens: 32000,
      system: SYSTEM,
      messages: [{ role: "user", content: brief }],
    });
    
    const raw = message.content
      .filter((block) => block.type === "text")
      .map((block) => block.text)
      .join("");
    
    const html = raw.replace(/^```(?:html)?\s*/i, "").replace(/```\s*$/, "").trim();
    await mkdir("video", { recursive: true });
    await writeFile("video/scene.html", html);
    console.log(`scene.html: ${html.length} bytes`);

    Kết quả mẫu

    scene.html: 18432 bytes
  3. Kiểm tra tính tất định và xem trước

    Chụp ảnh tại t=0, 25%, 50%, 75% và frame cuối, kiểm tra tràn chữ, font và vùng an toàn.

    preview.ts
    import { chromium } from "playwright";
    import { pathToFileURL } from "node:url";
    
    const browser = await chromium.launch();
    const page = await browser.newPage({
      viewport: { width: 1080, height: 1920 },
      deviceScaleFactor: 1,
    });
    
    await page.goto(pathToFileURL("video/scene.html").href);
    await page.waitForFunction(() => typeof (window as any).seek === "function");
    
    const duration = await page.evaluate(() => (window as any).DURATION as number);
    for (const t of [0, duration * 0.25, duration * 0.5, duration * 0.75]) {
      await page.evaluate(async (time) => {
        await (window as any).seek(time);
      }, t);
      await page.screenshot({ path: `video/preview-${Math.round(t * 1000)}ms.png` });
    }
    
    await browser.close();
    console.log(`duration ${duration}s`);

    Kết quả mẫu

    duration 12s
    video/preview-0ms.png
    video/preview-3000ms.png
    video/preview-6000ms.png
    video/preview-9000ms.png
  4. Render toàn bộ frame và mã hóa

    Gọi seek(t) với t = frame / fps, chụp frame và mã hóa H.264 bằng ffmpeg.

    render.ts
    import { spawn } from "node:child_process";
    import { mkdir, rm } from "node:fs/promises";
    import { pathToFileURL } from "node:url";
    import { chromium } from "playwright";
    
    const FPS = 30;
    
    const browser = await chromium.launch();
    const page = await browser.newPage({
      viewport: { width: 1080, height: 1920 },
      deviceScaleFactor: 1,
    });
    await page.goto(pathToFileURL("video/scene.html").href);
    await page.waitForFunction(() => typeof (window as any).seek === "function");
    
    const duration = await page.evaluate(() => (window as any).DURATION as number);
    const frames = Math.ceil(duration * FPS);
    
    await rm("video/frames", { recursive: true, force: true });
    await mkdir("video/frames", { recursive: true });
    
    for (let frame = 0; frame < frames; frame++) {
      await page.evaluate(async (time) => {
        await (window as any).seek(time);
      }, frame / FPS);
      await page.screenshot({
        path: `video/frames/${String(frame).padStart(5, "0")}.png`,
      });
    }
    await browser.close();
    
    const ffmpeg = spawn("ffmpeg", [
      "-y",
      "-framerate", String(FPS),
      "-i", "video/frames/%05d.png",
      "-c:v", "libx264",
      "-pix_fmt", "yuv420p",
      "-movflags", "+faststart",
      "video/video.mp4",
    ], { stdio: "inherit" });
    
    await new Promise<void>((resolve, reject) => {
      ffmpeg.on("exit", (code) => {
        if (code === 0) resolve();
        else reject(new Error(`ffmpeg exited with ${code}`));
      });
    });
    
    console.log(`${frames} frames -> video/video.mp4`);

    Kết quả mẫu

    360 frames -> video/video.mp4
  5. Mux audio và xem toàn bộ

    Thêm track có bản quyền bằng -c:v copy, kiểm tra thời lượng, âm lượng và xem từ đầu đến cuối.

    mux.sh
    ffmpeg -i video/video.mp4 -i video/audio.wav \
      -c:v copy -c:a aac -b:a 192k -shortest \
      video/final.mp4
    
    ffprobe -v error -show_entries format=duration \
      -of default=nw=1:nk=1 video/final.mp4

    Kết quả mẫu

    12.000000
  6. Lặp với cùng model

    Chỉ mô tả frame lỗi và thay đổi mong muốn, đưa HTML hiện tại cho Opus và chạy lại xem trước trước khi render đầy đủ.

Bao gồm

  • Storyboard và timeline viết trước
  • Cảnh HTML tất định của Opus 5.5
  • Script render Playwright và mã hóa ffmpeg
  • MP4 cuối với track audio tùy chọn
  • Vòng duyệt và sửa từng frame

Không làm gì

  • Opus 5.5 tạo mã, không tạo frame; trình duyệt render chụp frame
  • Không cần gói Claude, nhưng dùng model Felo tính theo mức dùng
  • Vẫn cần Node, Playwright Chromium và ffmpeg
  • Không asset ngoài hay CDN; chỉ HTML/CSS/SVG/Canvas hoặc tệp cục bộ
  • Video dài cần chia cảnh; đây không phải ghi màn hình thời gian thực
  • Thuyết minh và nhạc là bước riêng; quy trình chỉ mux audio bạn cung cấp

Câu hỏi

Opus 5.5 tạo video trực tiếp không?

Không. Nó tạo văn bản và mã, viết cảnh HTML; trình duyệt và ffmpeg biến cảnh thành frame và MP4.

Có cần gói Claude không?

Không. Dùng key Felo gọi `claude-opus-5-5` qua Felo API, tính theo mức dùng; không cần gói Claude riêng.

Chạy trong agent nào?

WorkBuddy, ChatGPT có thực thi mã, Codex, Pi Agent, Claude Code hoặc agent chạy được Node và trình duyệt headless.

Vì sao cần seek(t)?

Chụp frame không theo thời gian thực: frame 400 có thể được chụp rất lâu sau 399, nên mỗi frame phải là hàm thuần của t.

Có dùng HyperFrames hay Remotion không?

Có, cho composition dài hoặc dự án có cấu trúc. Công thức này giữ một tệp HTML để kiểm tra lệnh gọi model và vòng render.

Video 12 giây tốn bao nhiêu?

Tùy prompt, token đầu ra và số lần lặp. Model Felo tính theo token; xem giá trước khi render dài.

Có dùng nhạc và thuyết minh của mình không?

Có, nếu có quyền. Render video trước rồi mux track có bản quyền hoặc TTS bằng ffmpeg. Quy trình không tạo thuyết minh.

Tham khảo

Hướng dẫn và dự án mà quy trình này dựa trên.

Quy trình liên quan

Tùy biến

Cùng công thức, điều chỉnh theo cách bạn thực sự triển khai.

Dự án HyperFrames hoặc Remotion

Với composition dài dùng các framework này; lệnh gọi model giữ nguyên, chỉ lệnh render đổi.

Bản vuông cho mạng xã hội

Giữ beat sheet, chuyển sang 1080x1080 và chỉnh typography, vùng an toàn.

Ba biến thể từ một brief

Tạo ba cảnh với màu và nhịp khác nhau, xem trước và chỉ render bản tốt nhất.

Các trang tham chiếu đằng sau công thức và nơi đi tiếp.