A standalone Tauri v2 + raw WebGL example that turns four reusable media slots into a compact software video switcher. Each source can be an animated pattern, still image, looping video, or shared live camera. Independent Preview and Program buses feed GPU transitions, a lower-third/logo overlay, MediaRecorder capture, native saving, and PNG export.
npm install
npm run dev
On macOS, approve camera permission only when assigning the camera to a source slot.
Source 1 ┐
Source 2 ├─→ Preview / Program buses ─→ WebGL transition ─→ overlay ─→ stage
Source 3 ┤ ├─→ MediaRecorder
Source 4 ┘ └─→ PNG export
All four source slots support:
Hover or click a source card before dropping a file. The highlighted card becomes the native drop target.
Images and videos intentionally use different loading paths:
Image → Rust bytes → Blob URL → WebGL texture
Video → authorized Tauri asset URL → video element → WebGL texture
The image path avoids WKWebView texture-security errors. The video path preserves streaming and seeking without loading the complete file into IPC memory.
CUT operation that swaps Preview and ProgramAUTO transition using the chosen duration1–4: select PreviewC: cutSpace: automatic transitionThe four source textures remain resident in WebGL. The fragment shader chooses active Program and Preview sources, generates a transition mask, composites the overlay, and applies fade-to-black.
The lower third and logo are drawn into a transparent 2D canvas and uploaded as one WebGL texture.
tauri-plugin-dialog for native open/save dialogstauri::ipc::ResponseWebview::onDragDropEventsrc-tauri/Info.plist includes NSCameraUsageDescription, and entitlements.plist enables camera access. Camera frames remain local to the app.
20-tauri-v2-live-video-switcher/
├── package.json
├── README.md
├── V2-FOLDER-MAP.md
├── src/
│ ├── index.html
│ ├── styles.css
│ └── app.js
└── src-tauri/
├── Cargo.toml
├── Info.plist
├── entitlements.plist
├── tauri.conf.json
├── build.rs
├── capabilities/default.json
├── icons/
└── src/main.rs