Tự động tạo video tin tức ngắn 9:16 (~60s) tiếng Việt cho TikTok / YouTube Shorts / Instagram Reels từ URL bài báo hoặc file
.txt.Auto-generate Vietnamese 9:16 short news videos (~60s) for TikTok / YouTube Shorts / Instagram Reels from a news URL or
.txtfile.
Auto News Video là một dự án mã nguồn mở giúp bạn biến bất kỳ bài báo công nghệ tiếng Việt nào thành một video ngắn motion-graphic chuyên nghiệp chỉ với 1 lệnh duy nhất trong Claude Code.
Pipeline tự động làm các bước:
- Đọc URL bài báo (hoặc file
.txt) và phân tích nội dung - Sinh kịch bản JSON với 6 loại template visual khác nhau (hook, comparison, stat-hero, feature-list, callout, outro) — chọn theo nội dung bài viết
- Tổng hợp giọng đọc tiếng Việt qua LucyLab hoặc ElevenLabs
- Render video MP4 với HyperFrames (Puppeteer + GSAP + FFmpeg) — phong cách studio shell + animation hiện đại
- Xuất kèm script.txt và voice.mp3 để bạn import vào CapCut Pro thêm caption / nhạc nền
- ✅ Phong cách HeyGen-quality: persistent brand shell (icon, channel, handle), grain texture, gradient navy + cyan + purple
- ✅ 6 loại scene template tự pick theo nội dung — không rập khuôn
- ✅ Đa nhà cung cấp TTS: LucyLab (giọng Việt tự nhiên + SRT free) hoặc ElevenLabs (đa ngôn ngữ, nhiều voice library)
- ✅ Tích hợp Claude Code skill — chỉ cần
/create-news-video <url>là xong - ✅ Mở rộng được: schema rõ ràng, code modular, có test suite
| Lớp | Công nghệ |
|---|---|
| Runtime | Node.js ≥ 22, TypeScript 5+, ESM |
| Render engine | HyperFrames (Puppeteer + GSAP + FFmpeg) |
| TTS providers | LucyLab.io (JSON-RPC, Vietnamese cloning) hoặc ElevenLabs (REST, multilingual) |
| Validation | Zod (discriminated union schema) |
| HTTP | axios + nock (mocking) |
| Testing | Vitest |
| Audio | FFmpeg + ffprobe (mix, concat với silence) |
| AI/Skill | Claude Code skill (/create-news-video) |
| Visual blocks | HyperFrames registry: grain-overlay, shimmer-sweep, tiktok-follow |
| Fonts | Inter + Anton (Google Fonts) |
HyperFrames là framework HTML-to-video do HeyGen phát triển và mã nguồn mở. Khác với cách dùng After Effects hay Premiere thủ công, HyperFrames cho phép bạn viết video bằng HTML/CSS/JS rồi render thành MP4 chất lượng cao một cách deterministic (cùng input → cùng output frame-by-frame).
Cách nó hoạt động trong dự án:
- Pipeline sinh ra một file
index.htmlchứa toàn bộ scenes + GSAP timeline - HyperFrames spawn headless Chrome (Puppeteer) để load file đó
- Capture từng frame ở đúng timestamp (30fps × 60s = 1800 frames)
- Encode tất cả frames + audio thành MP4 dùng FFmpeg
Tại sao chọn HyperFrames?
- ✅ Có sẵn 50+ pre-built blocks trong registry (transitions, social cards, data viz, kinetic typography...) — dùng
npx hyperframes add <name> - ✅ GSAP timeline đã được tích hợp sẵn cho animations mượt mà
- ✅ Skill-friendly cho AI agent — Claude/GPT có thể tự sinh composition HTML
- ✅ Lint built-in (
npx hyperframes lint) phát hiện lỗi composition trước khi render - ✅ Aspect ratio 9:16 native — sinh ra cho short-form video
Các blocks/components dùng trong dự án:
grain-overlay— film grain texture xuyên video (cảm giác "analog warmth")shimmer-sweep— light pass animation cho text headlinetiktok-follow— outro CTA card (đã sẵn 1080×1920)
| Tiêu chí | LucyLab | ElevenLabs |
|---|---|---|
| Giọng tiếng Việt | ⭐⭐⭐⭐⭐ Tự nhiên (voice cloning) | ⭐⭐⭐⭐ Tốt (multilingual) |
| Chi phí | Rẻ (~25k VND / 1M ký tự) | Đắt hơn (~$5 / 30k ký tự) |
| Voice library | Tự clone giọng | 1000+ voices có sẵn |
| API style | JSON-RPC async (poll) | REST sync (instant) |
| SRT subtitle | ✅ Free, kèm theo response | ❌ Không có |
| Concurrency | 1 export/account | Parallel OK |
| Languages khác | ❌ Chỉ tiếng Việt | ✅ 30+ ngôn ngữ |
Khuyến nghị:
- 🇻🇳 Chỉ làm video tiếng Việt → chọn LucyLab (rẻ + giọng tự nhiên + có SRT)
- 🌍 Làm đa ngôn ngữ hoặc cần voice library lớn → chọn ElevenLabs
- 🔄 Không chắc → bắt đầu với LucyLab, đổi sang ElevenLabs sau (chỉ cần đổi
TTS_PROVIDERtrong.env.local)
Zod là TypeScript-first schema library. Trong project này, Zod đảm bảo script.json (do Claude sinh) luôn đúng cấu trúc trước khi pipeline chạy.
// Discriminated union: 6 loại template, mỗi loại có data shape khác nhau
const TemplateData = z.discriminatedUnion("template", [
HookData, ComparisonData, StatHeroData, FeatureListData, CalloutData, OutroData
]);Lợi ích:
- Phát hiện ngay nếu Claude sinh script sai (vd:
template: "stat"không tồn tại) — fail Step 1 với error message rõ ràng - TypeScript types được suy ra tự động từ Zod schema → composer không cần khai báo type lại
- Schema = source of truth cho cả validation runtime + type compile-time
Project tích hợp với Claude Code qua skill markdown đặt tại .claude/skills/create-news-video/SKILL.md. Skill này hướng dẫn Claude:
- WebFetch URL bài báo
- Phân tích nội dung tiếng Việt
- Pick template phù hợp cho từng scene (comparison nếu có "vs", stat-hero nếu có số liệu...)
- Sinh
script.jsonđúng schema - Run pipeline qua Bash
Ưu điểm: bạn chỉ cần gõ /create-news-video <url> — Claude tự làm hết phần "creative" (viết kịch bản tiếng Việt, chọn template, viết câu hook hấp dẫn). Phần "deterministic" (gọi API, render) do Node CLI lo.
Vitest (ESM-native, replacement cho Jest) cho 35 unit tests:
- Schema validation tests với fixtures (valid + invalid scripts)
- TTS client tests với
nockmock HTTP (không gọi API thật, không tốn quota) - Audio tools tests với fixture mp3 files (440Hz/2s, 880Hz/3s sine waves)
- HTML composer snapshot test — đảm bảo output HTML không bị break khi refactor
Chạy npm test để verify mọi thứ work trước khi push.
FFmpeg + ffprobe được dùng để:
ffprobe: đo duration của mp3 từng scene (để compute timing trong composition)ffmpeg: concat các scene mp3 với 0.3s silence gap →voice.mp3cuốiffmpeg(qua HyperFrames): encode 1800 frame PNG + audio thành MP4
Phải có trong PATH (ffmpeg -version). Trên Windows: winget install Gyan.FFmpeg.
| Mục | Phiên bản | Ghi chú |
|---|---|---|
| Node.js | ≥ 22 | node --version |
| FFmpeg + ffprobe | bất kỳ phiên bản hiện đại nào | trong PATH (ffmpeg -version) |
| Chrome / Chromium | bất kỳ | HyperFrames Puppeteer cần — sẽ auto-download lần đầu chạy |
| Claude Code CLI | latest | cài tại đây |
| Tài khoản TTS | một trong hai | LucyLab.io HOẶC ElevenLabs |
# 1. Clone repo
git clone <repo-url> auto_create_video
cd auto_create_video
# 2. Cài dependencies
npm install
# 3. Tạo file env và điền API key
cp .env.example .env.local
# → mở .env.local, chọn TTS provider (lucylab hoặc elevenlabs) và điền key
# 4. Verify cài đặt
node --version # ≥ 22
ffmpeg -version # in version OK
ffprobe -version
npm test # all tests pass (35 tests)Mở .env.local và chọn một trong hai provider:
- Đăng ký tại https://lucylab.io
- Lấy API key + voice ID (UUID 22 ký tự)
- Đặt
TTS_PROVIDER=lucylab - ✅ Ưu điểm: giọng Việt tự nhiên (voice cloning), trả kèm file SRT subtitle miễn phí
⚠️ Hạn chế: chỉ 1 export/account đồng thời (pipeline tự xử lý)
TTS_PROVIDER=lucylab
VIETNAMESE_API_KEY=sk_live_xxxxxxxxxxxxxxxxxxxx
VIETNAMESE_VOICEID=22charvoiceiduuidhere- Đăng ký tại https://elevenlabs.io
- Lấy API key tại https://elevenlabs.io/app/settings/api-keys
- Chọn voice tại https://elevenlabs.io/app/voice-library (lấy voice ID)
- Đặt
TTS_PROVIDER=elevenlabs - ✅ Ưu điểm: đa ngôn ngữ, thư viện voice phong phú, chất lượng cao
⚠️ Hạn chế: đắt hơn LucyLab, không có SRT đi kèm
TTS_PROVIDER=elevenlabs
ELEVENLABS_API_KEY=sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ELEVENLABS_VOICE_ID=EXAVITQu4vr4xnSDxMaL
ELEVENLABS_MODEL_ID=eleven_multilingual_v2Mỗi video tự động kết thúc với một TikTok follow card (slide từ dưới lên + animation click follow) — chuẩn HyperFrames style. Tất cả là tùy chọn — defaults work out of the box:
TIKTOK_DISPLAY_NAME=Công nghệ 24h
TIKTOK_HANDLE=@congnghe24h
TIKTOK_FOLLOWERS=1.2M followers
# Tùy chọn: URL ảnh avatar TikTok thật của bạn (jpg/png, vuông, ≥256x256)
# Nếu không set → dùng default `assets/avatar.jpg` đã bundled
TIKTOK_AVATAR_URL=https://example.com/your-avatar.jpgCách thay avatar:
- Cách 1 (đơn giản): thay file
assets/avatar.jpgbằng ảnh của bạn (square, ~256x256+) - Cách 2 (URL): set
TIKTOK_AVATAR_URLtrong.env.local→ pipeline tự download mỗi lần render
Card xuất hiện ở giây thứ ~1.6 trong scene outro với chuỗi animation:
- Card slide từ bottom lên (0.5s)
- Hold ~0.9s để người xem đọc
- Button "Follow" press-in + chuyển sang "Following ✓" với màu chuyển từ đỏ → xám đen
- Card stay visible đến hết video
Mỗi video tự có sound effect mix layer vào voice (volume thấp, không lấn voice). Không phải random — pipeline pick theo loại template:
| Template | Default SFX | Khi nào nghe |
|---|---|---|
hook |
transition/whoosh-soft |
Đầu video, entrance dramatic |
comparison |
transition/swoosh |
Khi 2 cards xuất hiện |
stat-hero |
emphasis/ding |
Lúc số/% xuất hiện |
feature-list |
transition/pop |
Mỗi bullet appear |
callout |
alert/notification |
Statement quan trọng |
outro |
outro/tada |
Ending signature |
Library sounds đã sẵn trong assets/sfx/ (download từ myinstants.com, royalty-free use):
assets/sfx/
├── transition/ (whoosh-soft, swoosh, pop)
├── emphasis/ (ding, tick, chime)
├── alert/ (notification)
└── outro/ (tada)
Tự thêm SFX của bạn:
- Download mp3 từ myinstants.com hoặc pixabay sound effects
- Đặt vào folder phù hợp
assets/sfx/<category>/<name>.mp3 - Reference trong script.json:
"sfx": { "name": "transition/your-sound", "volume": 0.4 }
Smart override theo nội dung (Claude tự pick khi sinh script):
- "cảnh báo", "rủi ro" →
alert/notification - "vượt", "kỷ lục", "xuất sắc" →
emphasis/chime - Disable cho scene đó →
"sfx": { "name": "none" }
Mở Claude Code trong thư mục project và gõ:
/create-news-video https://vnexpress.net/iphone-17-200mp
Hoặc với file .txt:
/create-news-video news/my-article.txt
Sau ~3-5 phút (TTS + render):
✓ Video: output/<slug>-<timestamp>/video.mp4 ← video cuối
✓ Audio: output/<slug>-<timestamp>/voice.mp3 ← để import CapCut
✓ Script: output/<slug>-<timestamp>/script.txt ← cho CapCut auto-caption
Nếu đã có sẵn script.json (vd để debug hoặc tự viết kịch bản):
npm run pipeline -- output/<slug>-<timestamp>/script.jsonNếu đã có voice files trong voice/ và muốn render lại visual:
npm run rerender -- output/<slug>-<timestamp>output/<slug>-<timestamp>/
├── script.json # Input JSON (Claude sinh hoặc bạn viết tay)
├── script.txt # Plain text cho CapCut auto-caption
├── images/bg.jpg # og:image đã tải (nếu có)
├── voice/
│ ├── scene-hook.mp3 # TTS từng scene
│ ├── scene-hook.srt # SRT subtitle (chỉ LucyLab)
│ └── scene-body-1.mp3
├── voice.mp3 # Voice đã concat (cho CapCut)
├── index.html # HyperFrames composition
├── styles.css # CSS (copied từ template)
├── animations.js # GSAP timeline (copied)
├── hyperframes.json # HyperFrames project config
├── meta.json # HyperFrames metadata
└── video.mp4 # 🎉 Output cuối — 1080×1920 MP4
Mỗi video gồm:
- Persistent shell xuyên suốt (header brand
>_icon + tên channel + tag, footer handle TikTok, grain texture, gradient navy) - 5–8 scene với template được Claude pick theo nội dung:
| Template | Khi nào dùng | Ví dụ |
|---|---|---|
hook |
Scene đầu tiên (3-5s) | "GPT 5.5" + "AI mạnh nhất!" trên ảnh og:image với shimmer |
comparison |
Khi có "X vs Y" / "vượt xa" / "so với" | 2 cards: "GPT 5.4 75.1%" cyan vs "GPT 5.5 82.7%" purple (winner) |
stat-hero |
Khi có số/% nổi bật | "1M" giant gradient + "Tokens / cửa sổ ngữ cảnh" |
feature-list |
Liệt kê tính năng | Card có 4 bullets dot cyan glow |
callout |
Statement / cảnh báo / quote | Glow purple card với "Cảnh báo: AI tự chủ cần cân nhắc" |
outro |
Scene cuối (3-5s) | "Theo dõi ngay" pill + "Công nghệ 24h" giant + underline gradient |
npm test # chạy 35 unit tests
npm run test:watch # watch mode
npx tsc --noEmit # type-check không build| Lỗi | Cách khắc phục |
|---|---|
Missing VIETNAMESE_API_KEY / Missing ELEVENLABS_API_KEY |
Kiểm tra .env.local đã có và đúng TTS_PROVIDER |
hyperframes render failed |
Chạy npx hyperframes render --help verify CLI; Chrome cài chưa? |
LucyLab polling timeout |
Tăng LUCYLAB_POLL_TIMEOUT_MS trong .env.local (default 120000ms) |
ElevenLabs 401 Invalid API key |
Verify key trên dashboard ElevenLabs, paste lại vào .env.local |
Tổng duration ngoài [48s, 72s] |
Re-trigger skill, hoặc chỉnh script.json viết dài/ngắn hơn |
ffprobe: command not found |
Cài FFmpeg: Windows winget install Gyan.FFmpeg, Mac brew install ffmpeg |
- Caption burned-in (forced alignment với Whisper)
- Auto-select background music theo mood
- Multi-news compilation mode (
digest) - AI-generated images (Flux/Stable Diffusion khi không có og:image)
- Auto-upload TikTok / YouTube Shorts / Reels qua API
- Logo overlay tùy chỉnh
- Multi-language (English, Chinese)
- Web UI standalone (không cần Claude Code)
MIT — sử dụng tự do, fork tự do, đóng góp PR tự do.
Auto News Video is an open-source project that transforms any Vietnamese tech news article into a professional motion-graphic short video with a single command in Claude Code.
The pipeline automates the following steps:
- Reads the article URL (or
.txtfile) and analyzes the content - Generates a JSON script picking from 6 visual template types (hook, comparison, stat-hero, feature-list, callout, outro) based on content nature
- Synthesizes Vietnamese voice via LucyLab or ElevenLabs
- Renders MP4 video using HyperFrames (Puppeteer + GSAP + FFmpeg) with studio shell style and modern animation
- Exports script.txt and voice.mp3 alongside, ready to import into CapCut Pro for captions / BGM
- ✅ HeyGen-quality look: persistent brand shell (icon, channel name, handle), grain texture, navy gradient with cyan + purple accents
- ✅ 6 scene template types auto-picked by content — never monotonous
- ✅ Multi-provider TTS: LucyLab (natural Vietnamese + free SRT) or ElevenLabs (multilingual, large voice library)
- ✅ Claude Code skill integration — just type
/create-news-video <url>and you're done - ✅ Extensible: clean schema, modular code, full test suite
| Layer | Technology |
|---|---|
| Runtime | Node.js ≥ 22, TypeScript 5+, ESM |
| Render engine | HyperFrames (Puppeteer + GSAP + FFmpeg) |
| TTS providers | LucyLab.io (JSON-RPC, Vietnamese cloning) or ElevenLabs (REST, multilingual) |
| Validation | Zod (discriminated union schema) |
| HTTP | axios + nock (mocking) |
| Testing | Vitest |
| Audio | FFmpeg + ffprobe (mix, concat with silence) |
| AI/Skill | Claude Code skill (/create-news-video) |
| Visual blocks | HyperFrames registry: grain-overlay, shimmer-sweep, tiktok-follow |
| Fonts | Inter + Anton (Google Fonts) |
HyperFrames is an open-source HTML-to-video framework by HeyGen. Unlike traditional editors (After Effects, Premiere), HyperFrames lets you author videos with HTML/CSS/JS then render to high-quality MP4 deterministically (same input → identical output frame-by-frame).
How it works in this project:
- Pipeline generates an
index.htmlcontaining all scenes + GSAP timeline - HyperFrames spawns headless Chrome (Puppeteer) to load it
- Captures each frame at the precise timestamp (30fps × 60s = 1800 frames)
- Encodes all frames + audio into MP4 via FFmpeg
Why HyperFrames?
- ✅ 50+ pre-built blocks in registry (transitions, social cards, data viz, kinetic typography...) — installable via
npx hyperframes add <name> - ✅ GSAP timeline built-in for smooth animations
- ✅ AI-agent friendly — Claude/GPT can author compositions in HTML
- ✅ Built-in lint (
npx hyperframes lint) catches composition errors before render - ✅ 9:16 native — designed for short-form video
Blocks/components used in this project:
grain-overlay— film grain texture throughout video (analog warmth feel)shimmer-sweep— light pass animation for headline texttiktok-follow— outro CTA card (already 1080×1920)
| Criteria | LucyLab | ElevenLabs |
|---|---|---|
| Vietnamese voice | ⭐⭐⭐⭐⭐ Natural (voice cloning) | ⭐⭐⭐⭐ Good (multilingual) |
| Cost | Cheap (~$1 / 1M chars) | Pricier (~$5 / 30k chars) |
| Voice library | Self-clone voices | 1000+ voices ready |
| API style | JSON-RPC async (poll) | REST sync (instant) |
| SRT subtitle | ✅ Free, included in response | ❌ Not provided |
| Concurrency | 1 export/account | Parallel OK |
| Other languages | ❌ Vietnamese only | ✅ 30+ languages |
Recommendation:
- 🇻🇳 Vietnamese-only videos → use LucyLab (cheap + natural + with SRT)
- 🌍 Multilingual or need large voice library → use ElevenLabs
- 🔄 Not sure → start with LucyLab, switch later (just change
TTS_PROVIDERin.env.local)
Zod is a TypeScript-first schema library. In this project, Zod ensures script.json (generated by Claude) always has correct structure before pipeline runs.
// Discriminated union: 6 template types, each with different data shape
const TemplateData = z.discriminatedUnion("template", [
HookData, ComparisonData, StatHeroData, FeatureListData, CalloutData, OutroData
]);Benefits:
- Detects immediately if Claude generates wrong script (e.g.
template: "stat"doesn't exist) — fails Step 1 with clear error - TypeScript types are inferred from Zod schema → composer doesn't need to redeclare types
- Schema = single source of truth for both runtime validation + compile-time types
The project integrates with Claude Code via a skill markdown at .claude/skills/create-news-video/SKILL.md. This skill instructs Claude to:
- WebFetch the article URL
- Analyze Vietnamese content
- Pick the right template per scene (comparison if "vs", stat-hero if numbers...)
- Generate
script.jsonmatching schema - Run pipeline via Bash
Benefit: just type /create-news-video <url> — Claude handles all "creative" work (writing Vietnamese script, picking templates, crafting catchy hooks). The "deterministic" parts (API calls, rendering) are handled by Node CLI.
Vitest (ESM-native Jest replacement) provides 35 unit tests:
- Schema validation tests with fixtures (valid + invalid scripts)
- TTS client tests with
nockHTTP mocking (no real API calls, no quota wasted) - Audio tools tests with fixture mp3 files (440Hz/2s, 880Hz/3s sine waves)
- HTML composer snapshot test — ensures output HTML doesn't break on refactor
Run npm test to verify everything works before pushing.
FFmpeg + ffprobe is used to:
ffprobe: measure mp3 duration per scene (to compute timing in composition)ffmpeg: concat scene mp3s with 0.3s silence gap → finalvoice.mp3ffmpeg(via HyperFrames): encode 1800 PNG frames + audio into MP4
Must be in PATH (ffmpeg -version). On Windows: winget install Gyan.FFmpeg.
| Item | Version | Notes |
|---|---|---|
| Node.js | ≥ 22 | node --version |
| FFmpeg + ffprobe | any modern version | in PATH (ffmpeg -version) |
| Chrome / Chromium | any | required by HyperFrames Puppeteer — auto-downloaded on first render |
| Claude Code CLI | latest | install here |
| TTS account | one of two | LucyLab.io OR ElevenLabs |
# 1. Clone the repo
git clone <repo-url> auto_create_video
cd auto_create_video
# 2. Install dependencies
npm install
# 3. Create env file and fill in API keys
cp .env.example .env.local
# → open .env.local, choose TTS provider (lucylab or elevenlabs) and fill key
# 4. Verify installation
node --version # ≥ 22
ffmpeg -version # any version OK
ffprobe -version
npm test # all 35 tests should passOpen .env.local and pick one of two providers:
- Sign up at https://lucylab.io
- Get API key + voice ID (22-char UUID)
- Set
TTS_PROVIDER=lucylab - ✅ Pros: natural Vietnamese voice (cloning), free SRT subtitle file included
⚠️ Cons: only 1 concurrent export per account (pipeline handles this)
TTS_PROVIDER=lucylab
VIETNAMESE_API_KEY=sk_live_xxxxxxxxxxxxxxxxxxxx
VIETNAMESE_VOICEID=22charvoiceiduuidhere- Sign up at https://elevenlabs.io
- Get API key at https://elevenlabs.io/app/settings/api-keys
- Browse voices at https://elevenlabs.io/app/voice-library (copy the voice ID)
- Set
TTS_PROVIDER=elevenlabs - ✅ Pros: multilingual, rich voice library, high quality
⚠️ Cons: pricier than LucyLab, no SRT included
TTS_PROVIDER=elevenlabs
ELEVENLABS_API_KEY=sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ELEVENLABS_VOICE_ID=EXAVITQu4vr4xnSDxMaL
ELEVENLABS_MODEL_ID=eleven_multilingual_v2Every video automatically ends with a TikTok follow card (slides up from bottom + follow-button click animation) — built from the official HyperFrames tiktok-follow block. All fields optional — defaults work out of the box:
TIKTOK_DISPLAY_NAME=Công nghệ 24h
TIKTOK_HANDLE=@congnghe24h
TIKTOK_FOLLOWERS=1.2M followers
# Optional: URL to your real TikTok avatar (jpg/png, square, ≥256x256)
# If not set → uses bundled default `assets/avatar.jpg`
TIKTOK_AVATAR_URL=https://example.com/your-avatar.jpgTo change the avatar:
- Option 1 (simple): replace
assets/avatar.jpgwith your image (square, ~256x256+) - Option 2 (URL): set
TIKTOK_AVATAR_URLin.env.local→ pipeline auto-downloads on every render
Card appears at ~1.6s into the outro scene with this animation sequence:
- Card slides up from bottom (0.5s)
- Hold ~0.9s for viewer to read
- "Follow" button press-in + transitions to "Following ✓" with red→dark-gray color shift
- Card stays visible until end of video
Every video automatically gets a sound effect layer mixed into the voice (low volume, doesn't overpower speech). Not random — the pipeline picks based on template type:
| Template | Default SFX | When you hear it |
|---|---|---|
hook |
transition/whoosh-soft |
Start of video, dramatic entrance |
comparison |
transition/swoosh |
When 2 cards appear |
stat-hero |
emphasis/ding |
When number/% reveals |
feature-list |
transition/pop |
Each bullet appears |
callout |
alert/notification |
Important statement |
outro |
outro/tada |
Ending signature |
Bundled sounds in assets/sfx/ (downloaded from myinstants.com):
assets/sfx/
├── transition/ (whoosh-soft, swoosh, pop)
├── emphasis/ (ding, tick, chime)
├── alert/ (notification)
└── outro/ (tada)
Add your own SFX:
- Download mp3 from myinstants.com or pixabay sound effects
- Drop into
assets/sfx/<category>/<name>.mp3 - Reference in script.json:
"sfx": { "name": "transition/your-sound", "volume": 0.4 }
Smart override by content (Claude auto-picks when generating script):
- "warning", "risk" →
alert/notification - "exceed", "record", "outstanding" →
emphasis/chime - Disable for this scene →
"sfx": { "name": "none" }
Open Claude Code in the project directory and type:
/create-news-video https://vnexpress.net/iphone-17-200mp
Or with a .txt file:
/create-news-video news/my-article.txt
After ~3-5 minutes (TTS + render):
✓ Video: output/<slug>-<timestamp>/video.mp4 ← final video
✓ Audio: output/<slug>-<timestamp>/voice.mp3 ← for CapCut
✓ Script: output/<slug>-<timestamp>/script.txt ← for CapCut auto-caption
If you already have a script.json (e.g. for debugging or hand-written script):
npm run pipeline -- output/<slug>-<timestamp>/script.jsonIf voice files already exist in voice/ and you only want to re-render visuals:
npm run rerender -- output/<slug>-<timestamp>output/<slug>-<timestamp>/
├── script.json # Input JSON (Claude-generated or hand-written)
├── script.txt # Plain text for CapCut auto-caption
├── images/bg.jpg # og:image downloaded (if available)
├── voice/
│ ├── scene-hook.mp3 # TTS per scene
│ ├── scene-hook.srt # SRT subtitles (LucyLab only)
│ └── scene-body-1.mp3
├── voice.mp3 # Concatenated voice (for CapCut)
├── index.html # HyperFrames composition
├── styles.css # CSS (copied from template)
├── animations.js # GSAP timeline (copied)
├── hyperframes.json # HyperFrames project config
├── meta.json # HyperFrames metadata
└── video.mp4 # 🎉 Final output — 1080×1920 MP4
Each video consists of:
- Persistent shell throughout (header brand
>_icon + channel name + tag, footer TikTok handle, grain texture, navy gradient) - 5–8 scenes with templates picked by Claude based on content:
| Template | When to use | Example |
|---|---|---|
hook |
First scene (3-5s) | "GPT 5.5" + "AI mạnh nhất!" over og:image with shimmer |
comparison |
When content has "X vs Y" / "exceeds" / "compared to" | 2 cards: "GPT 5.4 75.1%" cyan vs "GPT 5.5 82.7%" purple (winner) |
stat-hero |
When there's a key number/% | "1M" giant gradient + "Tokens / context window" |
feature-list |
When listing features | Card with 4 bullets, cyan glow dots |
callout |
Statement / warning / quote | Purple glow card with "Warning: agentic AI needs caution" |
outro |
Last scene (3-5s) | "Follow now" pill + "Công nghệ 24h" giant + gradient underline |
npm test # run 35 unit tests
npm run test:watch # watch mode
npx tsc --noEmit # type-check without build| Error | Fix |
|---|---|
Missing VIETNAMESE_API_KEY / Missing ELEVENLABS_API_KEY |
Check .env.local exists and TTS_PROVIDER matches |
hyperframes render failed |
Run npx hyperframes render --help to verify CLI; is Chrome installed? |
LucyLab polling timeout |
Increase LUCYLAB_POLL_TIMEOUT_MS in .env.local (default 120000ms) |
ElevenLabs 401 Invalid API key |
Verify key on ElevenLabs dashboard, re-paste into .env.local |
Total duration outside [48s, 72s] |
Re-trigger skill, or edit script.json to make text longer/shorter |
ffprobe: command not found |
Install FFmpeg: Windows winget install Gyan.FFmpeg, Mac brew install ffmpeg |
- Burned-in captions (forced alignment with Whisper)
- Auto-select background music by mood
- Multi-news compilation mode (
digest) - AI-generated images (Flux/Stable Diffusion when og:image unavailable)
- Auto-upload TikTok / YouTube Shorts / Reels via API
- Custom logo overlay
- Multi-language (English, Chinese)
- Standalone Web UI (no Claude Code required)
MIT — use freely, fork freely, PRs welcome.
Pull requests welcome! For major changes, please open an issue first to discuss what you'd like to change.
# Fork → clone → branch
git checkout -b feature/my-improvement
# Make changes, ensure tests pass
npm test
# Commit (Conventional Commits style)
git commit -m "feat: add Google TTS provider support"
# Push and open PR
git push origin feature/my-improvement- HyperFrames by HeyGen — the HTML-to-video framework that makes this possible
- LucyLab.io — Vietnamese voice cloning API
- ElevenLabs — multilingual TTS
- Anthropic Claude — the LLM that generates scripts via Claude Code skill