A tool that transforms markdown files with code blocks into beautifully animated videos perfect for YouTube Shorts and other vertical video platforms.
Write code examples in markdown, and Code-to-Video generates smooth, syntax-highlighted animations using shiki-magic-move with Puppeteer-powered video recording.
Note: This project was vibe coded with AI to meet my specific requirements as part of a video production workflow. It was designed for local use, not to be exposed to the internet. If it doesn't fit your needs, fork it and have AI make your own changes. This comment is the only part of the codebase written by a human.
code-to-video.mp4
- Web GUI: Visual editor with live preview and drag-and-drop step reordering
- Smooth Code Transitions: Animated morphing between code steps using shiki-magic-move
- Animated First Step: The first code block animates in from a blank screen
- Syntax Highlighting: Full Shiki theme support (dracula, github-dark, nord, synthwave-84, and more)
- Monaco Editor: Code editing with matching Shiki syntax themes
- Python Formatting: Automatic formatting with Ruff, including comment and docstring wrapping to respect line width
- YouTube Shorts Ready: 1080x1920 (9:16) portrait format output
- Flexible Configuration: Global defaults, frontmatter, and per-block settings
- MP4 Output: Automatic conversion from WebM via ffmpeg
- Node.js 18+
- ffmpeg (for MP4 conversion)
npm install
npm run buildLaunch the visual editor:
npm run dev:allThis starts both the API server and web interface at http://localhost:5173.
Web GUI Features:
- Two-panel interface: step editor (left) and live preview (right)
- Monaco code editor with Shiki syntax highlighting
- Real-time preview with ShikiMagicMove animations
- Drag-and-drop step reordering
- Global settings (theme, language, dimensions, timing)
- Per-step settings (duration, pause)
- Import/export markdown files
- One-click video recording
npm start -- input.md -o output.mp4npm start -- input.md \
--output output.mp4 \
--theme dracula \
--font-size 22 \
--duration 800 \
--pause 500 \
--line-numbers \
--verbose| Option | Description | Default |
|---|---|---|
-o, --output <path> |
Output file path | <input>.mp4 |
-t, --theme <name> |
Shiki syntax theme | dracula |
-w, --width <pixels> |
Video width | 1080 |
-H, --height <pixels> |
Video height | 1920 |
-f, --font-size <pixels> |
Code font size | 48 |
-d, --duration <ms> |
Animation duration | 800 |
-p, --pause <ms> |
Pause between steps | 500 |
-l, --line-numbers |
Show line numbers | false |
-v, --verbose |
Enable verbose logging | false |
Create markdown files with code blocks marked with magic-move:
---
theme: dracula
defaultDuration: 800
defaultPause: 500
lineNumbers: false
---
```typescript magic-move duration=1000
const greeting = "Hello"
```
```typescript magic-move
const greeting = "Hello"
function sayHello() {
console.log(greeting)
}
sayHello()
```| Attribute | Description | Example |
|---|---|---|
magic-move |
Required marker for animated blocks | typescript magic-move |
duration=N |
Animation duration in ms | duration=1000 |
pause=N |
Pause after animation | pause=500 |
---
theme: github-dark # Shiki theme name
defaultDuration: 800 # Default animation duration
defaultPause: 500 # Default pause between steps
lineNumbers: true # Show line numbers
fontSize: 24 # Font size in pixels
---Settings are applied in this order (highest priority last):
- Built-in defaults
config.jsonin working directory- CLI arguments
- Markdown frontmatter (YAML)
- Per-block attributes
See the /examples directory for sample markdown scripts:
example-1.md- Basic code transitions
Create a file demo.md:
---
theme: dracula
---
```python magic-move
x = 1
```
```python magic-move
x = 1
y = 2
```
```python magic-move
x = 1
y = 2
print(x + y)
```Run:
npm start -- demo.md -o demo.mp4- Parse: Markdown is parsed to extract code blocks and metadata
- Serve: Vite dev server hosts the React renderer
- Connect: WebSocket synchronizes CLI and browser
- Record: Puppeteer captures video while stepping through animations
- Output: Video is saved directly as MP4
# Start web GUI (recommended)
npm run dev:all
# Start web GUI components separately
npm run dev:server # API server on port 3001
npm run dev:web # Web UI on port 5173
# Start renderer dev server (for CLI testing)
npm run dev
# Build everything
npm run build
# Build CLI only
npm run build:cli
# Build web GUI only
npm run build:webcode-to-video/
├── bin/ # CLI entry point
├── src/
│ ├── cli/ # Command-line interface
│ ├── parser/ # Markdown parsing (legacy)
│ ├── recorder/ # Puppeteer & video capture
│ ├── renderer/ # React app for video recording
│ ├── server/ # Express API server
│ ├── shared/ # Shared types, parsing, serialization
│ └── web/ # Web GUI application
│ ├── components/ # React components
│ ├── hooks/ # Custom React hooks
│ └── store/ # Zustand state management
├── examples/ # Example markdown scripts
└── plan.md # Implementation specification
MIT