A free, open-source Windows desktop app that streams images, videos, and GIFs to any video-call app as a live, effect-processed virtual webcam β 100% local processing, no cloud, no subscription, no data leaving your machine.
Features Β· Why This Project Β· Quick Start Β· Installation Β· Usage Β· Use Cases Β· Roadmap Β· FAQ
The actual app running: playlist, live preview (LIVE badge, 30 FPS), and the real-time effects panel.
Verified directly against the source in this repository β nothing below is assumed or extrapolated.
- What it is: a Windows desktop GUI application (Python + CustomTkinter) that plays a media playlist, runs every frame through a real-time OpenCV effects pipeline, and streams the result to the OBS Virtual Camera device via
pyvirtualcam. - What it is not: it has no web server, no REST/GraphQL API, no database, no CLI flags, no cloud component, and no AI/ML models in the active code path (a
mediapipedependency exists but is commented out and unused). - Dependencies present but unused in code today:
moviepy,ffmpeg-python,mediapipe(listed inrequirements.txt, not imported anywhere incore/,gui/,effects/, ormedia/). - No secrets, API keys, tokens, or credentials were found anywhere in the codebase, configuration, or logs.
- No
LICENSEfile currently exists in the repository. - No
.gitignore,CONTRIBUTING.md,SECURITY.md, issue templates, PR template, or GitHub Actions workflows currently exist. - This directory is not yet a Git repository (
git statusreturns "not a git repository") and is not yet connected to GitHub β every discoverability/growth recommendation below assumes these setup steps happen first. - One real screenshot was found and is now used as the hero image:
docs/screenshots/main-window.png.
Showing anything other than your raw camera feed on a video call β a looping product demo, a branded holding slide, a promo clip β normally means building an OBS scene with sources, transforms, and filters just to loop one file.
VirtualCam Studio removes that friction: load your media, dial in the look with real-time effects, click Start Webcam, and any app that can select a camera device β Zoom, Google Meet, Microsoft Teams, Discord, browser-based calls, or OBS itself β sees your processed output as a normal webcam.
(Every item below is directly traceable to a function, class, or UI control in the current codebase.)
| Feature | Details |
|---|---|
| Multi-format playlist | Images (.jpg .jpeg .png .webp .bmp), Videos (.mp4 .mov .avi .mkv .wmv .flv .ts), GIFs (.gif) |
| Auto-generated thumbnails | Every playlist item gets a thumbnail (video thumbnails sampled at 10% of duration) |
| Loop & Shuffle | One-click toggles for looped and shuffled playback |
| Configurable image hold time | 1β30 seconds per static image before auto-advancing |
| Seamless video looping | Videos rewind automatically at end-of-file |
| Playlist management | Add, remove, and clear items from the sidebar |
Zoom (0.1Γβ5Γ, centered) Β· Rotation (Β±180Β°) Β· Position D-pad with fine-tune sliders and selectable step size (1/5/10/50 px) Β· Horizontal/vertical flip Β· Side-by-side mirror mode Β· Independent edge cropping (left/right/top/bottom)
Brightness Β· Contrast Β· Saturation Β· Sharpness Β· Gaussian blur Β· Opacity blending Β· Independent Red/Green/Blue channel gains
Grayscale and Sepia (mutually exclusive, applied after color grading)
On-screen text watermark/caption with a drop shadow, positionable in any of the four corners
Selectable output resolution (HD / FHD / QHD / 4K) and frame rate (24 / 30 / 60 fps) Β· Live FPS, CPU, and RAM readout Β· Letterboxed resizing that always preserves aspect ratio
Save and load the entire effects configuration as a JSON preset β instantly recall your "look" for the next stream
Streams the fully-processed frame to the OBS Virtual Camera driver via pyvirtualcam. If the driver isn't installed, the app degrades gracefully to preview-only mode instead of crashing.
In-app real-time preview panel plus a dedicated fullscreen preview window (F11, Esc to exit).
π Full effects parameter reference
| Parameter | Range | Default | Description |
|---|---|---|---|
zoom |
0.1 β 5.0 | 1.0 | Centered zoom level |
rotation |
β180Β° β 180Β° | 0 | Rotation angle |
pos_x |
β800 β 800 px | 0 | Horizontal pan |
pos_y |
β600 β 600 px | 0 | Vertical pan |
flip_h / flip_v |
bool | false |
Horizontal / vertical flip |
mirror_mode |
bool | false |
Side-by-side mirror (overrides flip) |
brightness |
β100 β 100 | 0 | Brightness offset |
contrast |
0.5 β 3.0 | 1.0 | Contrast multiplier |
saturation |
0.0 β 3.0 | 1.0 | HSV saturation scale |
sharpness |
0 β 10 | 0 | Unsharp-mask strength |
blur |
0 β 20 | 0 | Gaussian blur kernel radius |
opacity |
0.0 β 1.0 | 1.0 | Blend with black canvas |
red_gain / green_gain / blue_gain |
0.0 β 3.0 | 1.0 | Per-channel color gain |
grayscale / sepia |
bool | false |
Style filter (sepia takes priority) |
crop_left/right/top/bottom |
0 β 400 px | 0 | Edge crop, applied first |
watermark_text |
string | "" |
Overlay caption text |
watermark_enabled |
bool | false |
Toggle the overlay |
watermark_position |
top-left/top-right/bottom-left/bottom-right |
bottom-right |
Overlay corner |
Reasons grounded in what the code actually does, not marketing claims:
- Purpose-built, not a side feature. Unlike general broadcasting suites where "loop a file as my webcam" is one buried feature among hundreds, this app's entire UI is built around that one workflow β playlist β effects β webcam, in three clicks.
- A real, ordered effects pipeline, not a filter list.
effects/pipeline.pyapplies crop β flip/mirror β zoom β pan β rotation β color/tone β style filter β blur/sharpen β opacity β watermark in a fixed, predictable order on every single frame. - Fails safe, not silently. If the OBS Virtual Camera driver isn't installed,
WebcamEngineautomatically falls back to preview-only mode (core/webcam_engine.py) instead of crashing β you still see your effects working. - Genuinely local. A full read of every source file found zero network calls anywhere in the codebase. Nothing you load or configure leaves your machine.
- Ships with its own build pipeline.
build.pyauto-detects local packages and data folders and generates a working PyInstaller spec β including two extra hardening options (Nuitka native compilation, PyArmor AES-256 source encryption) for anyone distributing the compiled app.
flowchart LR
A["ποΈ Playlist\nImages Β· Videos Β· GIFs"] --> B["MediaManager\nframe reader"]
B --> C["Renderer"]
C --> D["EffectsPipeline\ncrop Β· zoom Β· color Β· filters Β· watermark"]
D --> E["WebcamEngine\nrender loop thread"]
D --> P["π₯οΈ Live Preview Panel"]
E --> F["pyvirtualcam"]
F --> G["OBS Virtual Camera driver"]
G --> H["Zoom Β· Meet Β· Teams Β· Discord Β· OBS Β· any camera app"]
Every frame passes through a fixed, ordered pipeline before reaching the virtual camera or the preview panel:
flowchart TD
S["Raw Frame"] --> P1["1 Β· Crop"]
P1 --> P2["2 Β· Flip / Mirror"]
P2 --> P3["3 Β· Zoom"]
P3 --> P4["4 Β· Position / Pan"]
P4 --> P5["5 Β· Rotation"]
P5 --> P6["6 Β· Brightness Β· Contrast Β· Saturation Β· RGB Gains"]
P6 --> P7["7 Β· Grayscale / Sepia"]
P7 --> P8["8 Β· Blur / Sharpen"]
P8 --> P9["9 Β· Opacity"]
P9 --> P10["10 Β· Watermark"]
P10 --> O["Resize β Output Frame"]
The render loop runs on a dedicated background thread so the GUI stays responsive; FPS/CPU/RAM are sampled once per second and shown live in the preview bar.
The fastest path from clone to a live virtual webcam:
git clone https://github.com/<your-username>/virtualcam-studio.git
cd virtualcam-studio
pip install -r requirements.txt
python main.pyThen, inside the app: πΌ Images / π¬ Videos β βΆ Play β π· Start Webcam. Select OBS Virtual Camera as the camera in any call app.
First time? You need the OBS Virtual Camera driver registered once β see Installation & Setup below.
| Requirement | Notes |
|---|---|
| Windows 10/11 | Primary, tested target β runtime data is written to %APPDATA%\VirtualWebcam and the app ships as a .exe |
| Python 3.10+ | Only required if running from source |
| OBS Studio (free) | Needed once, to register the OBS Virtual Camera driver used by pyvirtualcam |
git clone https://github.com/<your-username>/virtualcam-studio.git
cd virtualcam-studio
pip install -r requirements.txt
python main.pyThe app checks for required packages on startup and prints a pip install hint if anything's missing, instead of crashing silently.
1. Install OBS Studio from obsproject.com
2. Open OBS β Tools β Start Virtual Camera (once)
3. Close OBS β the driver stays registered on your system
4. Launch VirtualCam Studio and click "π· Start Webcam"
If the driver isn't detected, VirtualCam Studio automatically falls back to preview-only mode and shows setup instructions instead of failing silently.
π¦ Building a standalone .exe
VirtualCam Studio ships with an interactive build script that auto-detects local packages, data folders, and hidden imports:
python build.py| Option | Toolchain | Output size | Notes |
|---|---|---|---|
| 1 | PyInstaller | ~45 MB | Stable, fastest build |
| 2 | Nuitka | ~50 MB | Compiles to native C β harder to reverse-engineer |
| 3 | PyArmor + PyInstaller | ~45 MB | AES-256 source encryption before packaging |
Output is written to dist/.
VirtualCam Studio requires no environment variables, API keys, or secrets β it is a fully local, offline desktop application. The only persisted configuration is:
- Effect presets β plain JSON files you save/load via the πΎ Presets panel, stored under
presets/ - Logs β
logs/app.log - Compiled-app data β when running as a built
.exe, writable data (logs, cache, presets) is redirected to%APPDATA%\VirtualWebcamautomatically
Example preset (matches the exact fields written by the app):
{
"zoom": 1.2,
"rotation": 0,
"brightness": 10,
"contrast": 1.1,
"saturation": 1.0,
"sharpness": 0.0,
"blur": 0,
"opacity": 1.0,
"flip_h": false,
"flip_v": false,
"grayscale": false,
"sepia": false,
"mirror_mode": false,
"red_gain": 1.0,
"green_gain": 1.0,
"blue_gain": 1.0,
"crop_left": 0,
"crop_right": 0,
"crop_top": 0,
"crop_bottom": 0,
"watermark_text": "LIVE",
"watermark_enabled": true
}| Resolution | Pixels | Frame rates |
|---|---|---|
| HD | 1280 Γ 720 | 24 / 30 / 60 fps |
| FHD | 1920 Γ 1080 | 24 / 30 / 60 fps |
| QHD | 2560 Γ 1440 | 24 / 30 / 60 fps |
| 4K | 3840 Γ 2160 | 24 / 30 / 60 fps |
- Launch the app (
python main.pyor the built.exe) - Click πΌ Images or π¬ Videos to add files to the playlist (multi-select supported)
- Press βΆ Play β the live preview panel starts rendering immediately
- Fine-tune the look in the Effects & Position panel β zoom, pan with the D-pad, color grade, apply filters, add a watermark
- Click π· Start Webcam β your processed feed is now available as OBS Virtual Camera to any app
- In Zoom / Meet / Teams / Discord β camera settings β select OBS Virtual Camera
- Save the configuration as a preset (πΎ Save) to reload it instantly next time
| Key | Action |
|---|---|
Space |
Play / Pause |
β |
Next media item |
β |
Previous media item |
Delete |
Remove selected playlist item |
F11 |
Toggle fullscreen preview |
Esc |
Exit fullscreen preview |
VirtualCam Studio is currently a GUI-only desktop application. It does not expose a command-line interface, REST API, SDK, or webhook integrations β main.py takes no arguments and there is no server component in this codebase. If you need programmatic control, that would be a new feature (see Roadmap).
Grounded in what the app actually supports (looping media + real-time effects + a virtual camera device) rather than assumed scenarios:
| Who | What they'd use it for |
|---|---|
| Streamers & content creators | Loop a "Be Right Back" graphic or branded intro without leaving OBS scene management to chance |
| Webinar & virtual event hosts | Show a branded holding slide or looping sponsor video before the live segment starts |
| Sales & demo teams | Play a looping product video as their "camera" during a call instead of screen-sharing |
| Educators & trainers | Loop instructional GIFs or diagrams as webcam input for remote lessons |
| Developers testing overlays | Preview watermark/branding placement and color grading before going live in OBS |
virtualcam-studio/
βββ main.py # Entry point β works from source or as a compiled .exe
βββ build.py # Interactive EXE builder (PyInstaller / Nuitka / PyArmor)
βββ requirements.txt
βββ core/
β βββ app_state.py # Central thread-safe application state
β βββ media_manager.py # Playlist + frame-reader lifecycle
β βββ renderer.py # Effects β resize render step
β βββ webcam_engine.py # Render loop thread + pyvirtualcam output
βββ effects/
β βββ pipeline.py # Every frame effect + the fixed pipeline order
βββ media/
β βββ loader.py # Image / Video / GIF readers
βββ gui/
β βββ main_window.py # App shell, layout, hotkeys
β βββ sidebar.py # Playlist panel with thumbnails
β βββ preview.py # Live preview canvas + stats bar
β βββ controls.py # Transport bar (play/stop/webcam/fullscreen)
β βββ effects_panel.py # Effects sliders, D-pad, presets
βββ utils/
β βββ helpers.py # Frame resize/convert utilities
βββ presets/ # Saved effect presets (JSON)
βββ assets/icons/ # App icon, picked up automatically by build.py (currently empty)
βββ docs/screenshots/ # README screenshots
βββ logs/ # Runtime log file (app.log)
| Layer | Technology |
|---|---|
| GUI | CustomTkinter (Tkinter) |
| Image & video processing | OpenCV, NumPy |
| Image I/O & thumbnails | Pillow |
| Virtual camera output | pyvirtualcam (OBS Virtual Camera driver) |
| System stats | psutil |
| Packaging | PyInstaller / Nuitka / PyArmor, orchestrated by build.py |
| Language | Python 3.10+ |
moviepyandffmpeg-pythonare included inrequirements.txtfor future video-export tooling but aren't wired into the current render pipeline yet β see Roadmap.
VirtualCam Studio is a desktop application, not a hosted service β there is nothing here to deploy to a server. "Deployment" means producing a distributable Windows executable via python build.py (see Installation & Setup) and sharing the resulting dist/*.exe with your users. No Docker, CI/CD, or cloud infrastructure currently exists in this repository.
A short GIF/video demo of the playlist β effects β webcam workflow would be a strong addition here β see Roadmap.
Ideas that are not implemented yet β tracked openly so contributors know where to start:
- macOS / Linux packaging (
pyvirtualcamalready supports both platforms; current build tooling targets Windows only) - Video export/trimming using the already-bundled
moviepy/ffmpeg-pythondependencies - Face detection / auto-framing (a
mediapipedependency is scaffolded but currently disabled) - Drag-to-reorder playlist items
- Bundled default app icon (
assets/icons/is currently empty) - One-click virtual-camera driver installer to replace the manual OBS Studio step
- A short animated GIF/video demo for the README
- Optional CLI for scripted/headless playback
Have another idea? Open an issue β contributions and discussion are welcome.
What is a "virtual webcam" and why would I need one?
A virtual webcam is a system camera device that any app can select, but whose video comes from software instead of a physical camera. VirtualCam Studio uses this to let you present a video, image, or GIF as your webcam feed in any call or streaming app.
Which apps can I use this with?
Any application that lets you pick a camera source β Zoom, Google Meet, Microsoft Teams, Discord, browser-based video calls, and OBS Studio itself β since OBS Virtual Camera registers as a standard system camera device.
Do I need to keep OBS Studio open while using VirtualCam Studio?
No. Open OBS once and click Start Virtual Camera to register the driver on your system, then close OBS entirely β VirtualCam Studio talks to the driver directly afterward.
My virtual camera doesn't show up in my video-call app.
The OBS Virtual Camera driver likely isn't registered yet. Reinstall OBS Studio, open it, and run Tools β Start Virtual Camera once. Until the driver is detected, VirtualCam Studio automatically runs in preview-only mode instead of failing.
Does this work on macOS or Linux?
The core Python/OpenCV codebase and pyvirtualcam both support other platforms, but the current packaging (build.py, %APPDATA% paths) targets Windows specifically. Cross-platform packaging is on the roadmap.
Is any of my data uploaded anywhere?
No. There is no network code anywhere in the project β media files, effect presets, and logs are all read from and written to your local disk only.
Can I protect my source code when I share a built app?
Yes β build.py includes a PyArmor + PyInstaller option that AES-256 encrypts your source before bundling it into the final executable.
Does it have a CLI or API?
Not currently. It's a GUI-only application with no command-line arguments, REST API, or SDK. See Roadmap.
- 100% local processing β a full source read found no network requests anywhere in the codebase; nothing is uploaded or tracked.
- Media, presets, and logs stay on your machine (
logs/app.log,presets/*.json). - Optional AES-256 source encryption when building distributable binaries via the PyArmor build option.
- No
SECURITY.mdcurrently exists. Until one is added, please report security issues by opening a GitHub issue marked clearly as a security concern, or via a private GitHub Security Advisory if enabled on the repository β avoid posting exploit details in public issues.
Contributions are welcome β this project benefits from real-world testing across different Windows setups and OBS versions.
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-improvement - Make your changes and test them by actually running
python main.py - Commit with a clear message and open a pull request describing the why, not just the what
No CONTRIBUTING.md exists yet β the steps above are the de facto process until one is added (see recommendations below).
This project is intended to be released under the MIT License β a permissive license well suited to an open-source desktop tool. No LICENSE file currently exists in the repository β add one at the root to make this legally effective (see choosealicense.com/licenses/mit).
- π Found a bug or have a feature request? Open an issue.
- β Star this repo if VirtualCam Studio saves you from fumbling with OBS scenes every stream β it helps other people find it too.
- π΄ Fork it and adapt it for your own workflow.
- π Watch releases to hear about new features first.
- π£ Share it with anyone who streams, presents, or hosts calls for a living.
(No Discord/forum currently exists for this project β GitHub Issues and Discussions are the primary channels once enabled.)
Ready to turn any video into a live webcam feed?
git clone it, pip install -r requirements.txt, and hit Start Webcam.