Metadata-Version: 2.1
Name: cvrer
Version: 0.1.0
Summary: Create videos that simulate typing code with a smooth camera following the cursor
Author-email: Beginnercodinggamer228 <genkaprostotak@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/Beginnercodinggamer228/CVRer
Project-URL: Repository, https://github.com/Beginnercodinggamer228/CVRer
Keywords: code,video,typing,animation,syntax-highlighting,camera
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Video
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: Pillow>=9.0
Requires-Dist: pygments>=2.10
Requires-Dist: moviepy==1.0.3
Requires-Dist: rich>=13.0
Requires-Dist: proglog

<p align="center">
  <img src="CodeVideoRendererLogo.png" width="160" alt="CVRer logo">
</p>

# 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](https://github.com/ZhuChongjing/CodeVideoRenderer) and [PypiProject](https://pypi.org/project/codevideorenderer/) by ZhuChongjing. The original uses `manim` as its rendering engine, which requires **Microsoft C++ Build Tools** to install on Windows. This version replaces `manim` entirely with `Pillow` + `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_style` only 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:
```bash
pip install Pillow pygments "moviepy==1.0.3" rich proglog
```

---

## Quick start

```python
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:

```python
# 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:

```python
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.

```python
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:
```python
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`).

```python
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.

```python
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)`.

```python
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.

```python
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.

```python
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`.

```python
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.

```python
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.

```python
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.

```python
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.

```python
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.

```python
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.

```python
glow=True    # apply glow (slower, looks better)
glow=False   # skip glow (faster)
```

---

### `render()` method

```python
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.

```python
cv.render(reverse_typing=True)
```

---

## Full example

```python
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

```python
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

```python
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', ...]
```

---
