MultiVideo Recording — guide for OBS Studio 31.1+

MultiVideo Recording

Records every source you tick to its own video file, all frame-aligned, in a single recording pass. The video equivalent of OBS's multi-track audio.

What you get

One recording produces Face Cam_20260810-194846.mkv and Screen Share_20260810-194846.mkv alongside OBS's own recording — same length, same start frame, ready to drop straight onto separate tracks in an editor. Your webcam is captured full-size and uncropped, no matter how it is masked or scaled in the scene.

Click-by-click: install and first recording

Six steps, start to finish

A quick walkthrough of installing the script and making your first recording. Go at your own pace — click Next when you are ready.

MultiVideo Recording (unzipped folder)
GUIDE.html
INSTALL.bat
multivideo_recording.py
README.md
setup-multivideo.ps1
Double-click it.
Nothing needs installing first.
Setup
MultiVideo Recording - setup
[ok]   OBS Studio 32.2.1
[ok]   Python 3.10
[ok]   ffmpeg
Proceed? (y/N) y
Anything missing gets installed for you. Then it copies the script into OBS and sets the Python path.
FileEditViewDocksToolsHelp
Auto-Configuration Wizard
Plugin Manager
Automatic Scene Switcher
Scripts
WebSocket Server Settings
In OBS: Tools → Scripts
Scripts
Loaded Scripts
multivideo_recording.py
+
Description
ENABLE MultiVideo recording
Output folder B:/Recordings/layers Browse
File format MKV
Click +, choose the script, and its settings appear on the right. Then Browse to a folder for the files.
MultiVideo Recording
Face Cam · in 8 scenes
audio Microphone  --  clean, track 5
Screen Share · in 2 scenes
Chat Overlay · in 3 scenes
Tick a source and its audio picker appears underneath. Choose which audio belongs in that file.
MultiVideo Recording
Face Cam · in 8 scenes
audio Microphone  --  clean, track 5
Screen Share · in 2 scenes
audio Desktop Audio  --  clean, track 6
keep this audio OUT of the live mix (still recorded to its layer)
Optional — most people never need this. Keeps the desktop audio out of your stream and out of OBS's own recording, while the layer file still captures it. Useful when a copyrighted video is playing on screen: viewers hear nothing, your own copy keeps it for the edit.
Do not mute the source in OBS. Muting silences it everywhere, the layer file included.
Controls
Start Streaming
Start Recording
Settings
REC 00:42
Use OBS's own button.
Your layers start and stop with it.
Face Cam_…mkv
Screen Share_…mkv
Stop when you are done — one file per source, all exactly the same length.
1Unzip the folder and double-click INSTALL.bat

That is the whole workflow. Everything below is detail, for when you want it.

How it works

Each source gets its own private canvas and its own encoder. All the encoders join a single encoder group, which is what keeps the files in lockstep — measured at 0 frames apart.

SOURCE PRIVATE CANVAS ENCODER FILE Face Cam Screen Share Graphics (group) 1920×1080 native size native size encoder group = synchronised start NVENC NVENC NVENC Face Cam….mkv Screen Share….mkv Graphics….mkv
Sources never touch each other's canvases, so nothing is cropped, overlapped or scaled by the scene layout.

Install

  1. Unzip everything into one folder. The installer looks for its own files next to itself.
  2. Close OBS. It rewrites its config on exit and would undo the Python setting.
  3. Double-click INSTALL.bat. It checks what you have, asks before installing anything, copies the script into OBS's scripts folder and points OBS at a compatible Python.

    Use the .bat, not the .ps1 — Windows often has no "Run with PowerShell" option at all, and the default RemoteSigned policy blocks scripts that arrived in a zip. The .bat clears both.

  4. Start OBS → Tools → Scripts → + → pick multivideo_recording.py.
  5. Click ℹ Log status first. It reports your OBS version, which audio tracks OBS records and streams on, and which are free.

Requirements

OBS 31.1 or newer
obsproject.com/download
Hard floor — the script uses the canvas API, which does not exist before 31.1. Verified on 32.2.1.
Python 3.8 – 3.10
python.org → 3.10.11
Windows OBS is built against 3.8...<3.11. 3.11+ will silently fail to load. Check under Python Settings: it should say Loaded Python Version: 3.10.
ffmpeg
gyan.dev/ffmpeg/builds
Optional, and rarely needed — only as a fallback for "No audio" layers when every mixer track is occupied. The installer fetches all three for you — these links are only for doing it by hand.

The panel, top to bottom

Scripts — settings
ENABLE MultiVideo recording  (master switch)
Presets
Use presetGameplay
NameGameplay
Save these settings under that name Delete the selected preset
Preset file 
Import presets from that file Export all presets to a file
Output folderD:/Recordings/layers
Recording settingsUse OBS's own recording settings

OBS: Advanced output, mkv → .mkv, encoder obs_nvenc_hevc_tex

Triggers & output
Start with OBS 'Start Recording'
Also start when streaming starts
★  Full scene — everything together
audioEverything (full mix, track 1)

Master switch

Turns everything off without losing your source selection. Useful when you want a plain OBS recording for once.

Presets

Named sets of everything on this panel — folder, format, quality, triggers, and every ticked source with its audio choice. Switch between a podcast setup and a gaming setup from one dropdown.

Presets live inside the current scene collection and are tied to the script's file path, so moving or re-adding the script loses them. Export to a file before you move anything, or to hand a setup to someone else.

Output folder

Leave it blank and it uses OBS's own recording folder. The log prints WRITING TO: at the start and SAVED TO: at the end, so there is never any doubt.

Recording settings

Use OBS's own is the default: format, encoder and quality all come from your OBS recording settings, so the layers look exactly like OBS's file. The grey line underneath shows what was detected.

Switch to Custom and you get File format, Video encoder, Quality and Encoder speed of your own.

★ Full scene

Records the finished mix as its own file. Unlike OBS's recording it sits inside the encoder group, so it is frame-exact with your layers — drop everything on a timeline and it lines up with no nudging.

Recording through OBS gives you OBS's file as well, so tick this only if you want the aligned copy.

Recommended

Leave both trigger boxes ticked. Then OBS's normal Start Recording and Start Streaming buttons drive everything and you never open this panel again. If you stream without recording and the streaming box is unticked, nothing arms.

Custom quality, and encoder load

Each layer is a full encoder at its source's native size. A 4K capture costs four times what a 1080p webcam costs, and OBS's own recording runs on top of all of it. This is the one setting that can tip a machine over.

Quality-based (CQP/CRF)Targets a quality level, so each layer gets the bitrate its resolution needs. The right choice when layers are different sizes. Lower number = better = bigger.
Match OBS's settingsReads your recording encoder config and applies it verbatim.
Fixed bitrateThe same kbps regardless of resolution — which starves a 4K layer while wasting bits on a webcam.
Encoder speedFastest → Best. Defaults to Balanced. This is the first knob to turn if OBS says Encoding overloaded.
"Encoding overloaded!"

OBS telling you the encoder cannot keep up. The script prints its own estimate at the start of every recording — Encoder load: 3 layer(s), about 8.0x 1080p in total — and warns when that gets heavy.

In order: lower Encoder speed, untick a layer (the 4K one costs the most), or raise the quality number. Switching to Use OBS's own settings also helps, since those are tuned for one encoder rather than several.

Choosing sources

Scripts — source picker

Will record 2 layer(s): Screen Share ('Desktop Audio' isolated on track 5) | Face Cam ('Microphone' isolated on track 6)

Show sourcesCurrent scene only (Main)
Chat Overlay · in 3 scenes
Screen Share · in 2 scenes
audioDesktop Audio  --  clean, track 5
keep this audio OUT of the live mix (still recorded to its layer)
Face Cam [via Face Cam Group] · in 8 scenes

The Show sources filter keeps the list short — default is the current scene only. Anything you have ticked stays visible whatever the filter says.

What it does with your scenes

Source ClonesResolve to the original. Face Cam CloneFace Cam, recorded once.
Single-item groupsCollapse to the source inside. Face Cam GroupFace Cam. These are almost always positioning wrappers.
Multi-item groupsStay whole — one file for the whole composite. A Graphics group of five images becomes one graphics layer.
A source in 10 scenesListed once, produces one file, recorded continuously across scene changes.
Hidden sources are still recorded

A source with its eye toggled off in the Sources list — or one sitting in a scene you are not currently showing — still records to its own layer file.

This is deliberate. Each layer renders on its own private canvas with the ACTIVATE flag, and the script never reads the scene item's visibility. The eye icon controls what appears in your program output, not what the layer captures.

Why it is useful: park a second camera off-screen and it is captured clean for the edit without ever appearing on stream. Hide the graphics group mid-show and you still get an unbroken graphics track. Cut to a screen share while the webcam keeps rolling in the background.

The flip side: ticking a source you never show still costs a full encoder and writes a full-size file. Untick what you do not need.

Audio — the part worth reading

The one rule

OBS encodes audio per mixer track, never per source. Two files can only carry different audio if their sources sit on different tracks. Everything below follows from that.

By default OBS puts every new source on all six tracks, which is why picking "track 2" and "track 3" by hand gives you the same mix twice. The script handles this for you: at record start it borrows a mixer track that OBS itself does not record or stream on, puts your chosen source alone on it, and restores your routing when recording stops.

The audio dropdown

No audioGives the file a silent audio track. libobs refuses to start a video-only output at all, so the encoder is pointed at an empty mixer track instead. If every track is occupied it falls back to recording the full mix and stripping it with ffmpeg afterwards.
Everything (full mix, track 1)The complete mix, exactly what OBS's own recording gets.
A named sourceJust that source, isolated. The label tells you the truth up front — clean, track 5 or shares track 3 with Media, Browser.

Muting does not do what you want

Do not use the mute button for this

OBS's mute is a source-level gain of zero applied to all six tracks. A muted source is silent everywhere, including in its own layer file. There is no way around it.

Use "keep this audio OUT of the live mix" instead. It routes the source away from every track OBS records and streams, while its layer file still captures it clean. Stream and main recording lose it; your edit keeps it.

For live control mid-stream, bind Settings → Hotkeys → "MultiVideo: toggle live mix for layer-only audio".

Two things look odd but are correct: the source stays unmuted in the Audio Mixer with meters moving (it is routed away, not silenced), and if you monitor it you will still hear it locally. Neither reaches your audience.

Buttons
⟳  Rescan sources 💾  Save diagnostic log to a .txt file ℹ  Log status
⟳ Rescan sourcesPick up scenes or sources added since the panel was opened.
ℹ Log statusStart here when something looks wrong. Prints the script version and the file it was loaded from, the output folder, what is ticked, what each audio choice resolves to, which tracks OBS uses, which are free, and any muted sources.
💾 Save diagnostic logWrites a full report to a .txt — settings, presets, every timestamped OBS event, per-file results and the whole script log. Send this when asking for help. It also writes itself to multivideo-last-session.txt in your output folder after every recording, so a log exists even if OBS closes.

Recording

Record with OBS's own Start Recording button

That is the intended way to use this, and the only way you should record anything real. With the trigger boxes ticked, OBS's Start Recording starts your layers too, its Stop Recording stops them, and its Pause is mirrored so every file ends up the same length.

You also get OBS's own record timer and red indicator in the main window — the reliable at-a-glance confirmation that everything is rolling.

The script has no start button of its own, deliberately. There is nothing to press twice, and nothing to leave running by accident.

Seeing that it is recording

Use OBS's own record timer and red indicator in the main window — that is your confirmation that everything is rolling, layers included. The script deliberately has no start button of its own, so there is no second thing to remember to press or to leave running by accident.

For detail while it runs, the Script Log prints a heartbeat every five seconds:

Progress in the Script Log:

MULTIVIDEO START (recording) - 3 layer(s), obs_nvenc_h264_tex, 10000 kbps each
WRITING TO:  B:/OBS Recordings/multi video layer
Isolating audio sources onto their own tracks:
  'Desktop Audio' -> borrowed track 5 (OBS uses [1, 2, 3, 4]); restored on stop
  ● REC  00:35   3 layers   123 MB
  || paused
> RESUMED
SAVED TO:  B:/OBS Recordings/multi video layer

Files are named <Source name>_<date>-<time>.mkv (or .mp4, depending on the format you picked), so every file from one take shares a timestamp.

Checking alignment

python check_sync.py "B:/OBS Recordings/multi video layer"

Compares frame counts and start times across the newest take. You want PASS — all streams within 2 frames.

Updating the script

Only multivideo_recording.py changes between versions. Replace that one file, then in OBS press the ↻ refresh button next to +.

Do not remove and re-add

Settings and presets are stored per file path. Removing the script and adding it again — especially from a different folder — starts you from scratch, with nothing ticked and no presets.

The panel shows version and loaded from: at the top. After refreshing, check the version changed. If it did not, you replaced a different copy than the one OBS is running, and the path on that line tells you which one to overwrite.

Watch out for Windows saving repeat downloads as multivideo_recording (1).py, (2).py and so on. Keep exactly one copy, in %APPDATA%\obs-studio\scripts.

Known limitations

No status inside the script panelOBS gives scripts no way to refresh their own properties panel, so a live clock there is impossible. OBS's own recording timer and the Script Log heartbeat cover it.
Encoder countEach layer is a full encoder. NVENC has a concurrent session limit; the log says so plainly if you hit it.
Disk throughputBitrate × layers, all at once. NVMe recommended.
Crash mid-recordingAudio routing is not restored. Normal stop, script unload and OBS exit all restore correctly — after a crash, check Advanced Audio Properties.
vs OBS's own fileYour layers are aligned with each other, not with OBS's recording — OBS's encoder is not in the group. OBS’s own file may start a fraction of a second off; align on a clap or cut from the layers.
Long sessionsNot yet soak-tested for drift over many hours. Run check_sync.py after a 60+ minute recording before trusting it with something you cannot re-shoot.
Presets are per collectionThey live in the scene collection and are keyed by the script's path. Export them to a file to move or share them.
Renaming a sourceLayers are keyed by source name, so renaming one drops it from existing presets. Re-save the preset afterwards.

Prototype OBS script — not a released plugin. Requires OBS 31.1+ and Python 3.8–3.10.