Skip to content

Repository files navigation

VidFrame

VidFrame · Template Video

Drop in an article, get a 9:16 video.
One command, no editing, reproducible every single time.

Node TypeScript HyperFrames OmniVoice Format License

🌐 English · Tiếng Việt

Quick Start · How It Works · Installation · Usage · Templates

url / .txt → Claude Code (/create-template-video) → pipeline (OmniVoice · SFX · HyperFrames · FFmpeg) → video.mp4 + voice.mp3 + script.txt

Why you can trust it: The AI only handles content (writing the script, picking templates), while the code handles visuals (pixel by pixel). That means the same script.json always produces the exact same video — no guesswork, no manual touch-ups.

You only worry about the words. Templates handle all the design, layout, and motion; the pipeline handles TTS, audio, rendering, and muxing — delivering three ready-to-use files for CapCut / TikTok / Shorts / Reels:

File Purpose
video.mp4 Complete 9:16 video with voiceover + SFX
voice.mp3 Isolated voiceover track — drag straight into CapCut
script.txt Raw transcript — for CapCut auto-caption

🚀 Quick Start

git clone git@github.com:algodaohub/VidFrame.git
cd VidFrame
npm install
cp .env.example .env.local   # set TTS_PROVIDER and matching API key

With Claude Code / OpenCode / Agents CLIrecommended

/create-template-video https://www.youtube.com/shorts/10AjaTFEIwU

The agent fetches the content, writes script.json, and runs the pipeline automatically.

Manualbring your own script.json

npm run pipeline -- output/my-video/script.json

Full control over every scene and template.

A few minutes later → output/<slug>/video.mp4 (1080×1920).


🎥 Live video:


🧠 How It Works

flowchart LR
    A["📰 URL / .txt / video"] -->|/create-template-video| B[AI Agent]
    B -->|read + write text| C["script.json\nrenderer: hyperframes"]
    C -->|Zod validate| D[Template Pipeline]
    D -->|TTS per scene| E[TTS Provider]
    E -->|atempo speed| F1[Speed adjust]
    F1 -->|merge + mix SFX| F[voice.mp3]
    D -->|render each template| G["HyperFrames\nChromium"]
    G -->|fit clip to voice| H["clips/scene-*.mp4"]
    F --> I[mux audio]
    H --> I
    I -->|🎬| J["video.mp4\n1080×1920"]

    style A fill:#0f172a,color:#fff,stroke:#334155
    style B fill:#6366f1,color:#fff,stroke:#6366f1
    style E fill:#f59e0b,color:#fff,stroke:#f59e0b
    style G fill:#ec4899,color:#fff,stroke:#ec4899
    style J fill:#10b981,color:#fff,stroke:#10b981
Loading

The pipeline runs 8 deterministic steps — source at src/render/template-pipeline.ts:

# Step Output
1 Validate script.json checked against Zod schema
2 Caption text script.txt — all voiceText joined (CapCut auto-caption)
3 TTS / scene voice/scene-<id>.mp3 via TTS provider (idempotent)
4 Speed up atempo FFmpeg adjusts speed × TTS_SPEED (default 1.15×)
5 Merge voice voice-raw.mp3 with 0.3s gaps + per-scene time markers
6 Mix SFX voice.mp3 — SFX layered on top of the voiceover
7 Render clip clips/scene-<id>-fit.mp4 — template → MP4, fitted to voice length
8 Mux video-silent.mp4video.mp4 (audio merged in)

⚡ Installation

System Requirements
Requirement Version Notes
Node.js ≥ 22 node --version
FFmpeg + ffprobe latest must be on PATH (ffmpeg -version)
Chrome / Chromium any HyperFrames uses it to render each template
yt-dlp optional Required for YouTube / TikTok / Facebook URL input
OmniVoice server optional Local TTS at OMNIVOICE_ENDPOINT (default http://127.0.0.1:8123)
Claude Code / OpenCode / Agents CLI optional Only needed for the /create-template-video skill

Install FFmpeg:

  • macOSbrew install ffmpeg
  • Windowswinget install Gyan.FFmpeg
  • Linuxsudo apt install ffmpeg

Install yt-dlp (only if you need YouTube/TikTok input):

  • macOSbrew install yt-dlp
  • Windows / Linuxpip install yt-dlp
Configuration.env.local

Copy the sample file and fill in your credentials:

cp .env.example .env.local

Contents of .env.local:

# ─── Active TTS Provider ──────────────────────────────────────────────────────
# Choose one of: omnivoice | google | openai | elevenlabs
TTS_PROVIDER=omnivoice

# ─── Reading Speed ────────────────────────────────────────────────────────────
# 1.0 = normal · 1.15 = slightly faster (default) · 1.3 = noticeably fast
TTS_SPEED=1.15

# ─── TTS Scene Concurrency ────────────────────────────────────────────────────
# Keep at 1 for local OmniVoice; can increase to 3–5 for cloud APIs
TTS_CONCURRENCY=1

# ─── OmniVoice (local, no API key needed) ────────────────────────────────────
OMNIVOICE_ENDPOINT=http://127.0.0.1:8123

# ─── Google TTS (Unofficial, free, no API key) ───────────────────────────────
# GOOGLE_TTS_LANG=vi
# GOOGLE_TTS_SLOW=false

# ─── OpenAI TTS ───────────────────────────────────────────────────────────────
# OPENAI_API_KEY=sk-...
# OPENAI_TTS_MODEL=tts-1-hd          # tts-1 (fast) | tts-1-hd (quality) | gpt-4o-mini-tts
# OPENAI_TTS_VOICE=nova              # alloy | echo | fable | onyx | nova | shimmer

# ─── ElevenLabs ───────────────────────────────────────────────────────────────
# ELEVENLABS_API_KEY=sk-...
# ELEVENLABS_VOICE_ID=21m00Tcm4TlvDq8ikWAM
# ELEVENLABS_MODEL=eleven_multilingual_v2

TTS Provider Comparison:

Provider Cost Quality Needs internet Notes
OmniVoice Free Good No Requires running local server
Google TTS Free Fair Yes Unofficial API, no key needed
OpenAI TTS Paid Very good Yes $0.015 / 1K characters
ElevenLabs Freemium Excellent Yes Most natural-sounding voice — Try free ↗

🎬 Usage

Option 1 — Via AI Agent CLI (recommended)

Open Claude Code, OpenCode, or Antigravity Agents in the project directory and type a natural-language command:

From a news article URL:

Create a template video from this article: https://techcrunch.com/...

From a YouTube / TikTok URL (requires yt-dlp):

Make a 9:16 poster-style news video from this YouTube video: https://youtube.com/watch?v=...

From an existing .txt file:

Create a news video using the script in file content.txt

From a subtitle .srt file:

Make a template video using the subtitle file transcript.srt

The agent will automatically: fetch content → write script.json → run pipeline → return the video path.


Option 2 — Run the pipeline manually

If you write or edit script.json yourself:

npm run pipeline -- output/<slug>/script.json

script.json structure (template mode)

📄 View full example
{
    "version": "1.0",
    "renderer": "hyperframes",
    "aspect": "9:16",
    "metadata": {
        "title": "Apple launches iPhone 17 with 200MP camera",
        "source": {
            "url": "https://...",
            "domain": "techcrunch.com",
            "image": null
        },
        "channel": "VidFrame"
    },
    "voice": { "provider": "omnivoice", "speed": 1.0 },
    "scenes": [
        {
            "id": "hook",
            "type": "hook",
            "voiceText": "Apple just announced the iPhone seventeen with a two-hundred megapixel camera.",
            "templateId": "frame-liquid-bg-hero",
            "inputs": {
                "kicker": "🔥 Breaking",
                "headline": "iPhone 17",
                "subheadline": "200MP Camera",
                "cta": "Follow now",
                "brand": "VidFrame"
            }
        },
        {
            "id": "body-1",
            "type": "body",
            "voiceText": "The new sensor captures far more light, making night shots noticeably sharper.",
            "templateId": "frame-pentagram-stat",
            "inputs": {
                "label": "Camera",
                "headline": "200MP",
                "subtitle": "Biggest sensor Apple has ever made",
                "anchor": "200"
            }
        },
        {
            "id": "outro",
            "type": "outro",
            "voiceText": "Follow VidFrame for fresh tech news every day.",
            "templateId": "frame-logo-outro",
            "inputs": {
                "brand_name": "VidFrame",
                "tagline": "Tech news, every day",
                "primary_url": "https://vidframe.vn"
            }
        }
    ]
}

Hard rules: 3–12 scenes, first scene must be hook, last scene must be outro, and every templateId must exist inside templates/.


Output directory structure

📁 View output file tree
output/<slug>-<timestamp>/
├── script.json          # input (generated by skill or hand-written)
├── script.txt           # joined voiceText — for CapCut auto-caption
├── voice/
│   ├── scene-hook.mp3    # TTS per scene (idempotent)
│   └── scene-*.mp3
├── voice-raw.mp3        # merged voice, no SFX yet (intermediate)
├── voice.mp3            # final audio, SFX mixed in + speed adjusted
├── clips/
│   ├── scene-hook.mp4     # rendered template clip (idempotent)
│   └── scene-hook-fit.mp4 # fitted to the scene's voice duration
├── video-silent.mp4     # concatenated clips, no audio yet (intermediate)
└── video.mp4            # 🎉 final output — 1080×1920 + voice + SFX

Safe to re-run. To redo TTS for a scene, delete voice/scene-<id>.mp3; to re-render a scene, delete clips/scene-<id>.mp4, then run the pipeline again — everything else is kept as-is.


🎨 Templates

Each template is a standalone HyperFrames project inside templates/index.html for 16:9 and compositions/portrait.html for 9:16. You only fill in inputs; the template takes care of the look. Full slot reference: templates/CATALOG.md.

Template Role Best for
frame-liquid-bg-hero hook Opener — aurora hero with headline + CTA button
frame-vignelli body One striking number — dark charcoal + red accent
frame-pentagram-stat body One stat/benchmark — dark neon + bar chart
frame-bold-poster body Bold multi-line statement + large figure
frame-build-minimal body One big word popping in — dark/orange
frame-creative-voltage body Creative tagline — electric blue split + handwritten text
frame-glitch-title body Breaking news / tech — cyberpunk glitch RGB-split
frame-aicoding-list body List of 2–5 items (icon + severity tag)
frame-aicoding-comparison body Head-to-head comparison of two things
frame-finance-vox body Finance — stocks, gold, economy; navy/gold palette
frame-mom-baby-vox body Parenting — baby care, child health; warm pastels
frame-logo-outro outro Default end-card — glowing logo + name + tagline + URL
frame-statement-outro outro Alternate outro — red card on paper background

Add your own template: create templates/<id>/ with index.html, compositions/portrait.html, hyperframes.json, meta.json (+ NOTICE.md if vendored), then add one line to CATALOG.md. Use a font that supports Vietnamese characters.


🔊 Sound Effects (SFX)

SFX files live in assets/sfx/<category>/<name>.mp3. For each scene, the selector (src/assets/sfx-selector.ts) picks a file using 3 tiers:

1. scene.sfx override    → specified file, or { "name": "none" } to disable
2. semantic match         → keywords in voiceText (warning→alert, record→success, launch→reveal …)
3. type default           → hook→hook · body→callout · outro→outro

The SFX library is large and is not committed to the repo:

npm run sfx:download   # download the SFX library
npm run sfx:filter     # trim / filter

The pipeline renders fine without assets/sfx/ — the video just won't have sound effects.


🛠️ Tech Stack

Layer Technology
Runtime Node ≥22 · TypeScript 6 · ESM · tsx
Render HyperFrames 0.6.94 (HTML→MP4 via Chromium)
TTS OmniVoice (local) · Google TTS · OpenAI TTS · ElevenLabs
TTS Speed FFmpeg atempo — pitch-preserving speed control via TTS_SPEED
Schema Zod ^4
HTTP axios + nock
Concurrency p-limit
A/V FFmpeg + ffprobe
Transcript yt-dlp (subtitles/audio from YouTube, TikTok, Facebook)
Tests Vitest ^4
Orchestration Claude Code / OpenCode / Antigravity Agents skill

🙏 Credits

  • HyperFrames — the HTML-to-video engine powering every template
  • OmniVoice — local Vietnamese text-to-speech
  • html-video — the HTML-to-video concept this project is inspired by
  • Auto-Create-Video — the original project this builds upon

💖 Support the Project

If this project saved you time, buy the author a coffee ☕️!

☕️ Grab a Highlands Coffee Voucher

Click the link below to get your code now 👇

Highlands Coffee Voucher

👉 https://trackecom.asia/GqBsVT8z 👈


🎙️ Try ElevenLabs — the most natural AI voice

ElevenLabs is the highest-quality TTS provider supported by VidFrame. Get started for free!

ElevenLabs

👉 https://try.elevenlabs.io/llzqr93yk2bj 👈


⭐ Star History

Star History Chart

⬆ Back to top

Made with ❤️ by VidFrame · trackecom.asia/GqBsVT8z · ElevenLabs TTS

# VidFrame

About

Auto-generate Vietnamese 9:16 short news videos from URL/txt/video using professional HyperFrames templates — Claude Code skill + multi-provider TTS (OmniVoice, ElevenLabs, OpenAI)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages