Create videos that simulate typing code with a smooth camera following the cursor
Project description
CVRer
A Python library for creating videos that simulate typing code, with a smooth camera that follows the cursor.
Note: This is a reimplementation of the original CodeVideoRenderer and PypiProject by ZhuChongjing. The original uses
manimas its rendering engine, which requires Microsoft C++ Build Tools to install on Windows. This version replacesmanimentirely withPillow+moviepy, so it works out of the box on any Python 3.8+ environment without any C++ compiler.
Differences from the original
| Feature | Original | This version |
|---|---|---|
| Rendering engine | manim | Pillow + moviepy |
| Requires C++ Build Tools | Yes | No |
| Camera follow | Smooth X+Y via manim scene | Smooth X+Y via lerp per frame |
| Cursor blink | Yes | Yes |
| Glow effect | moviepy | moviepy (same) |
reverse_typing |
No | Yes |
| Custom font | Yes (fonts/ folder) |
Yes (fonts/ folder) |
| Line numbers | Yes | Yes |
center layout |
No | Yes |
Known limitations compared to the original:
- No OpenGL renderer option (Cairo only in original, here it's Pillow)
- No random typing interval variation per character (use
interval_range=(0.08, 0.15)for variation — min/max are applied uniformly, not per-character randomly) - Camera follows cursor but does not do the subtle vertical oscillation the original does while typing a long line
formatter_styleonly supports pygments built-in styles — custom VS Code themes require passing color dicts manually
Requirements
Pillow>=9.0
pygments>=2.10
moviepy==1.0.3
rich>=13.0
proglog
Install:
pip install Pillow pygments "moviepy==1.0.3" rich proglog
Quick start
import sys
sys.path.insert(0, '/path/to/folder') # folder containing CVRer/
from CVRer import CameraFollowCursorCV
cv = CameraFollowCursorCV(
code=('string', """
def hello():
name = "World"
print(f"Hello, {name}!")
return name
result = hello()
print(result)
"""),
language='python',
formatter_style='github-dark',
)
cv.render()
Output: CameraFollowCursorCV.mp4 in the current directory.
CameraFollowCursorCV
Constructor parameters
code — required
Source code to animate. Two formats:
# From a string
code=('string', 'print("hello")')
# From a file
code=('file', 'path/to/script.py')
The file must be UTF-8 encoded. Characters \r, \v, \f are not allowed.
language — required
Pygments language alias. Examples:
language='python'
language='html'
language='javascript'
language='typescript'
language='cpp'
language='rust'
language='go'
language='sql'
language='bash'
language='json'
language='yaml'
Full list: run from pygments.lexers import get_all_lexers; print(list(get_all_lexers())) or see CVRer/typing.py.
formatter_style — default: "github-dark"
Syntax highlight color theme. Must be a valid pygments style name.
formatter_style='github-dark' # dark, GitHub-style
formatter_style='monokai' # classic dark
formatter_style='dracula' # purple dark
formatter_style='one-dark' # Atom One Dark
formatter_style='nord' # Nordic blue-grey
formatter_style='gruvbox-dark' # warm retro dark
formatter_style='solarized-dark' # Solarized
formatter_style='vs' # light, Visual Studio-like
formatter_style='xcode' # light, Xcode-like
Full list:
from pygments.styles import get_all_styles
print(list(get_all_styles()))
font_size — default: 26
Font size in pixels. The library first looks for a .ttf file in CVRer/fonts/, then falls back to system fonts (Consolas, Courier New, Lucida Console).
font_size=20 # smaller, more code fits on screen
font_size=26 # default
font_size=32 # larger, easier to read
To use a custom font — place any .ttf file into CVRer/fonts/. It will be picked up automatically.
line_spacing — default: 1.5
Line height multiplier relative to the font's character height.
line_spacing=1.2 # compact
line_spacing=1.5 # default, comfortable
line_spacing=2.0 # spacious
interval_range — default: (0.15, 0.15)
Typing speed as (min_seconds, max_seconds) per character. This also determines the video FPS: fps = round(1 / min_seconds).
interval_range=(0.15, 0.15) # 0.15s per char, ~7 fps — slow, readable
interval_range=(0.08, 0.08) # 0.08s per char, ~12 fps — medium
interval_range=(0.05, 0.05) # 0.05s per char, ~20 fps — fast
interval_range=(0.03, 0.03) # 0.03s per char, ~33 fps — very fast
Currently both values must be equal. Per-character random variation is not yet implemented.
camera_scale — default: 1.0
Output video resolution scale.
camera_scale=1.0 # 1920x1080 (Full HD)
camera_scale=0.5 # 960x540
camera_scale=0.75 # 1440x810
camera_zoom — default: 2.0
How close the camera is to the code. Higher = more zoomed in, fewer characters visible at once.
camera_zoom=1.0 # wide view, lots of code visible
camera_zoom=1.5 # slightly zoomed
camera_zoom=2.0 # default, comfortable close-up
camera_zoom=3.0 # very close, ~20 chars per line visible
Internally this crops a smaller region of the canvas and upscales it to the output resolution.
camera_smooth — default: 0.25
Camera movement smoothing coefficient per frame. Range: 0.0 to 1.0.
camera_smooth=0.05 # very slow, cinematic drift
camera_smooth=0.15 # smooth, natural
camera_smooth=0.25 # default
camera_smooth=0.5 # snappy, follows cursor closely
camera_smooth=1.0 # instant, no smoothing
end_pause — default: 2.0
Seconds the video holds after all characters are typed. During this time the camera continues smoothly settling and the cursor keeps blinking.
end_pause=0.5 # quick cut
end_pause=2.0 # default
end_pause=5.0 # long hold
center — default: True
Whether to center the code block within the viewport. When True, the code appears in the middle of the frame rather than top-left.
center=True # code centered in frame
center=False # code starts at top-left
cursor_blink_rate — default: 0.5
Cursor blink period in seconds. The cursor is visible for half the period, hidden for the other half. Set to 0 to disable blinking.
cursor_blink_rate=0.5 # default, blinks every 0.5s
cursor_blink_rate=1.0 # slow blink
cursor_blink_rate=0.3 # fast blink
cursor_blink_rate=0 # no blinking, always visible
video_name — default: "CameraFollowCursorCV"
Output file name without the .mp4 extension. Can be an absolute path.
video_name='my_video' # saves as my_video.mp4 in cwd
video_name='C:/Users/User/Desktop/output' # absolute path
video_name='renders/python_tutorial' # relative subfolder
line_numbers — default: True
Show line numbers on the left side.
line_numbers=True # show line numbers
line_numbers=False # hide line numbers
glow — default: True
Apply a glow/bloom post-processing effect after rendering. Uses moviepy to process each frame with Gaussian blur + brightness boost. Adds noticeable processing time.
glow=True # apply glow (slower, looks better)
glow=False # skip glow (faster)
render() method
cv.render(
output=True, # print progress to console
reverse_typing=False, # erase code after end_pause
)
output — default: True
Print rendering progress, fps, resolution info and timing to the console.
reverse_typing — default: False
After the end_pause, erase all typed characters one by one in reverse order until the screen is completely empty. The cursor keeps blinking during erasure.
cv.render(reverse_typing=True)
Full example
import sys
sys.path.insert(0, 'C:/Users/User/Desktop/MPCode')
from CVRer import CameraFollowCursorCV
cv = CameraFollowCursorCV(
code=('string', """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- Code -->
</body>
</html>
"""),
language='html',
formatter_style='github-dark',
font_size=26,
line_spacing=1.5,
interval_range=(0.08, 0.08),
camera_scale=1.0,
camera_zoom=2.0,
camera_smooth=0.15,
end_pause=3.0,
center=True,
cursor_blink_rate=0.5,
video_name='C:/Users/User/Desktop/output',
line_numbers=True,
glow=True,
)
cv.render(output=True, reverse_typing=False)
Load from file
cv = CameraFollowCursorCV(
code=('file', 'C:/path/to/folder/script.py'),
language='python',
formatter_style='monokai',
video_name='C:/Users/User/Desktop/script_video',
)
cv.render()
Available highlight styles
from pygments.styles import get_all_styles
print(sorted(get_all_styles()))
# ['abap', 'algol', 'arduino', 'autumn', 'dracula', 'emacs',
# 'friendly', 'fruity', 'github-dark', 'gruvbox-dark', 'gruvbox-light',
# 'inkpot', 'material', 'monokai', 'native', 'nord', 'nord-darker',
# 'one-dark', 'paraiso-dark', 'solarized-dark', 'solarized-light',
# 'tango', 'vim', 'vs', 'xcode', 'zenburn', ...]
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cvrer-0.1.1-py3-none-any.whl.
File metadata
- Download URL: cvrer-0.1.1-py3-none-any.whl
- Upload date:
- Size: 7.3 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a9f6c331047bea1be950f8c701f358238adf58074dd0a537098d51318d02fb52
|
|
| MD5 |
98c6ee63c7cb67063ee6995c8276628e
|
|
| BLAKE2b-256 |
06e3ebd12953ec5207b38467a3df9a4ff07c366638e392d79ea6dd587a1b1c40
|