Installing VDM on a fresh laptop

Take a new Windows 11 laptop from out-of-the-box to ready for a ski-jump tournament. Written for a technical operator — comfortable with Device Manager, PowerShell and editing text files, but not compiling source.

The order matters

Two steps in this sequence fail silently and expensively if done out of order:

  1. The antivirus exclusion goes on before the files are copied in. If you extract first and exclude second, Norton may already have quarantined capture.exe and you will spend an afternoon chasing a phantom bug.
  2. Camera and GPU selection happen on the target machine, not in a config file you bring with you. Those values are machine-specific by design and no amount of copying a known-good settings.txt will produce them.

Check the machine against Prerequisites before you start. In particular, verify the USB controller topology — a laptop that routes all three USB ports through one root hub cannot run three 1080p60 feeds, and that is not something you can fix once you are at the venue.

1. Software prerequisites

Install these before copying VDM onto the machine.

Visual C++ 2015–2022 Redistributable (x64)

Every VDM binary links against the MSVC runtime. Without it VDM.exe will not launch — Windows shows VCRUNTIME140.dll not found, or the process exits silently with code 0xc0000135.

winget install --id Microsoft.VCRedist.2015+.x64

Alternatively download vc_redist.x64.exe from aka.ms/vs/17/release/vc_redist.x64.exe and run it.

NVIDIA driver R570 or newer

Required by the NVENC encoder path in videogen.exe. An older driver fails with a version error along the lines of Required: 13.0 Found: 12.0 when videogen tries to load the NVENC interface.

Download the latest Studio or Game Ready driver from nvidia.com. Verify at a command prompt:

nvidia-smi

The Driver Version column must read 570.xx or higher.

You do not need the build tools

Visual Studio, CMake, SDL3, FFmpeg, Git and Python are build-from-source tools. A deployment laptop needs none of them — the package ships the compiled binaries and every runtime DLL they need. Those tools only matter if you are building from source.

2. Antivirus exclusion (do this before copying files)

Critical — this fails silently

Without an antivirus exclusion on the install folder, VDM will not work reliably, and the failure modes do not look like antivirus problems. Two distinct ones have cost real hours:

The installer does not add this exclusion for you. It is yours to do.

Norton 360

  1. Open Norton 360.
  2. Settings → Antivirus → the Scans and Risks tab.
  3. Find Items to Exclude from Auto-Protect, SONAR and Download Intelligence DetectionConfigureAdd Folders.
  4. Browse to C:\VDM\ → OK.
  5. Find Items to Exclude from ScansConfigureAdd Folders → the same path.
  6. Apply → OK → close Norton.
  7. Restart the laptop. SONAR caches the old exclusion list and only re-reads it at boot.

Windows Defender

  1. Settings → Privacy & securityWindows Security.
  2. Virus & threat protection → Manage settings.
  3. Scroll to Exclusions → Add or remove exclusions → Add an exclusion → Folder.
  4. Browse to C:\VDM\ → Select Folder.

Defender applies exclusions immediately with no reboot. Sanity-check by re-extracting the package — the files should persist on disk.

If both are installed, exclude in both

Some Norton installations leave Defender's real-time protection running as a fallback. A folder excluded only in Norton can still be deleted by Defender.

3. Running the installer

Unpack the install package somewhere convenient — Downloads is fine, it is only a staging directory. If it arrived as a zip, right-click the zip → Properties → Unblock → OK before extracting, to clear the mark-of-the-web flag.

The unpacked package looks like this:

vdm-install-package\
    app\                  executables, SDL3.dll, the FFmpeg libav DLLs,
                          numbers.txt, NorgeLogo.png, jumpers.csv
    config\               settings.txt, settings_sample.txt, pixel_frames.txt,
                          jumpers.csv, netrc.template
    doc\                  this documentation
    Install-VDM.ps1
    Verify-Install.ps1
    README.txt
    MANIFEST.json         every shipped file with its size and SHA-256

Open PowerShell, change into that directory, and run:

powershell -ExecutionPolicy Bypass -File .\Install-VDM.ps1

Administrator rights are not required for the default C:\VDM target on a normal Windows 11 machine. The installer writes nothing to Program Files, nothing to HKLM, and no system settings; the Start Menu shortcut goes to the per-user Programs folder. The only case that needs an elevated shell is choosing an -InstallRoot you do not have write access to.

Parameters

Install-VDM.ps1
ParameterEffect
-InstallRoot <path>Where to install. Default C:\VDM.
-SkipPrereqCheckRun the prerequisite checks for information only, and do not abort on a FAIL.
-NoShortcutSkip creating the Start Menu shortcut.
-WhatIfA real dry run. The prerequisite checks execute and report; every write is announced but not performed.
-Confirm, -VerboseStandard PowerShell behaviour.

Run it with -WhatIf first

On an unfamiliar laptop, -WhatIf gives you the full prerequisite report and the complete list of intended writes without touching the disk. It is the cheapest way to find out that the VC++ redist is missing or the volume is short on space.

What the installer does and does not do

Automatic: creates the install root; copies everything from app\ (executables, DLLs, numbers.txt, NorgeLogo.png, jumpers.csv); copies the config\ files into the same directory alongside the executables; creates empty CapturedVideos\, output_videos\ and cache\; writes VDM.bat; copies doc\ into the install root; and creates the Start Menu shortcut unless you passed -NoShortcut.

Left to you:

ItemWhat the installer doesWhat you must do
VC++ 2015–2022 x64 redistributable Detects it by reading HKLM:\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64. Reports FAIL and prints the remediation command if absent. Never installs anything. Run the winget command from step 1.
Antivirus / Defender exclusion Mentions it in the NEXT STEPS text. Does not add it. Step 2, and ideally before you got here.
NVIDIA driver Detects the GPU and driver version, reports WARN if below 570. Never installs. Update the driver yourself if warned.
%USERPROFILE%\.netrc Never creates it. Places netrc.template in the install root as a reference with placeholder values. Step 7, only if you are uploading clips.

The prerequisite checks are all read-only. Windows 10/11 x64, the VC++ redistributable, and at least 2 GB free on the target volume can each FAIL and abort the install with a nonzero exit code; the NVIDIA GPU and driver check is WARN-only and never blocks. -SkipPrereqCheck downgrades every FAIL to informational.

4. What the install directory looks like

app\ and config\ are staging only

They exist in the distribution package to keep it tidy. After installation everything lands flat in the install root — settings.txt sits directly beside VDM.exe. There is no app\ or config\ subdirectory in C:\VDM, and there must not be: the runtime data files have to be siblings of the executables.

C:\VDM\
    VDM.exe                  <- controller (main UI, the one you launch)
    capture.exe              <- USB HDMI capture (3 instances at runtime)
    motion.exe               <- motion detection (3 instances at runtime)
    videogen.exe             <- merge feeds + encode mp4s
    viewer.exe               <- live distance-measurement viewer (SDL3)
    fileviewer.exe           <- offline viewer for saved mp4s (SDL3)
    capfile.exe              <- continuous mp4-per-feed recording
    practice_player.exe      <- practice mode from saved videos
    launch_viewer.exe        <- viewer launcher helper
    captest.exe              <- standalone USB capture diagnostic
    shmem_diag.exe           <- shared-memory health diagnostic
    shmem_query.exe          <- shared-memory state query

    SDL3.dll                 <- REQUIRED for viewer / fileviewer
    avcodec-61.dll           <- REQUIRED for videogen / capfile
    avdevice-61.dll
    avfilter-10.dll
    avformat-61.dll
    avutil-59.dll
    swresample-5.dll
    swscale-8.dll
    libbz2-1.dll
    libiconv-2.dll
    libwinpthread-1.dll
    zlib1.dll

    numbers.txt              <- bitmap font for overlays (REQUIRED)
    NorgeLogo.png            <- logo bitmap
    jumpers.csv              <- tab-separated jumper roster (per event)
    settings.txt             <- venue configuration
    settings_sample.txt      <- commented template
    pixel_frames.txt         <- auto-setup output (regenerated per venue)
    netrc.template           <- reference for %USERPROFILE%\.netrc
    VDM.bat                  <- launcher written by the installer

    CapturedVideos\          <- capfile.exe output
    output_videos\           <- videogen output (name set by archive_dir)
    cache\
    doc\                     <- this documentation

The recommended path is C:\VDM\: short, no spaces, no special characters. A few launch-path edge cases inside the controller break on paths containing spaces, so avoid installing under C:\Program Files\ or a user folder with a space in the name.

5. Verifying the install

Run the bundled self-test from the package directory:

powershell -ExecutionPolicy Bypass -File .\Verify-Install.ps1
Verify-Install.ps1
ParameterEffect
-InstallRoot <path>Which installation to check. Default C:\VDM.
-NoDllLoadSkip the LoadLibraryEx dependency probe and only check that the DLLs exist.

It checks the 9 required executables (VDM, capture, motion, videogen, capfile, practice_player, viewer, fileviewer, launch_viewer), 5 optional executables, 12 runtime DLLs, a LoadLibraryEx dependency probe per DLL, the data files, that settings.txt parses as key=value with the expected prefix conventions, the three working directories, and VDM.bat. It prints a PASS/WARN/FAIL table with a TOTAL line and exits nonzero on any FAIL.

WARNs here are expected on a fresh install

The machine-specific items — the NVENC GPU name and the camera device paths — are reported as WARN because they cannot be correct until you have done step 6. They are things to confirm, not install defects. FAILs are real.

The LoadLibraryEx probe is the useful part: it catches a DLL that is present but cannot actually load because one of its dependencies is missing — a failure that otherwise only shows up as a mysterious crash the first time you start the viewer.

6. First run: cameras and GPU

Launch VDM.exe (or the Start Menu shortcut, or VDM.bat). The controller window opens with four tabs — Preview, Processes, Feeds, Settings.

6.1 Confirm Windows can see the capture devices

Plug all three capture boxes into USB 3.0 ports on different controllers, connect the HDMI sources, then from a command prompt in C:\VDM\:

captest.exe --list

You should see exactly three entries for the capture devices, plus any internal laptop webcam. If you see fewer, stop and fix that before going further — see Troubleshooting § cameras. Assigning a camera in VDM cannot succeed for a device Windows has not enumerated.

6.2 Assign the cameras

  1. In the controller, open ToolsSelect Cameras…
  2. The dialog has one row per feed, labelled Feed 0 (TOP), Feed 1 (MIDDLE) and Feed 2 (BOTTOM), each with a combo box listing the detected Media Foundation devices plus None.
  3. Assign each detected device to the feed matching its physical position on the hill. Feed 0 is the top of the landing hill, feed 1 the middle (the k-point area, and the camera whose motion fires the movie trigger), feed 2 the bottom outrun.
  4. If Windows' enumeration order does not match the physical order, use the [Swap 0↔1], [Swap 0↔2] and [Swap 1↔2] buttons rather than re-plugging cables.
  5. Click OK.

Assigning a device auto-starts capture and motion for that feed; selecting None stops both. The assignments persist to *camera_device_path[0..2] in settings.txt, so subsequent sessions resume automatically.

6.3 Select the NVENC GPU

The shipped configuration pins the encoder to a specific GPU by name. On a different laptop that name will not match. Use ToolsSelect GPU to re-select the GPU present on this machine, which rewrites *capfile_nvenc_gpu_name.

NVENC is disabled in the shipped configuration

The live configuration carries disable_nvenc_encoding=1. That is a deliberate workaround for the behaviour of one specific GPU, not a general recommendation. On new hardware, try disable_nvenc_encoding=0 and confirm the encode path works before you conclude anything; if it misbehaves, set it back. With NVENC disabled the pipeline falls back to software H.264 encoding, which works but costs a great deal more CPU — see Prerequisites § the NVENC constraint.

6.4 Fix the window geometry

big_window_width and big_window_height ship as 2880×1620, matching the display of the machine the configuration came from. On a different panel this is wrong — too big and the window extends off-screen, too small and you lose working area. Set them to suit the actual display. See Configuration § machine-specific settings.

6.5 Watch it come up

On the Processes tab, capture[0..2] and motion[0..2] should reach Running with stable PIDs within about three seconds. Then watch the title bar's Δ(N,N,N) indicator:

7. Upload credentials (if you are uploading)

After each encode, videogen.exe can spawn upload_video.bat, which FTPs the clip to the tournament server using curl.exe --netrc. The server settings come from settings.txt; the credentials never do.

Credentials live outside the package

%USERPROFILE%\.netrc is operator-provisioned and is never shipped, never packaged, and never written by the installer. Get the FTP login from the tournament organiser before the event. No credentials appear anywhere in this documentation or in the distribution.

  1. Open Notepad — a plain-text editor, not Word or WordPad.
  2. Enter one line, substituting the real values:
    machine thehansens.com login YOUR_USERNAME password YOUR_PASSWORD
    Replace thehansens.com with whatever *upload_host is set to if you are pointing at a different server.
  3. Save as %USERPROFILE%\.netrc. In the Save dialog set Save as type to All files so Notepad does not append .txt.
  4. Verify:
    curl.exe --netrc -v ftp://thehansens.com/
    A successful login reaches the FTP welcome banner. 530 Login incorrect means the file is wrong — check for a stray .txt extension first, it is the usual cause.

netrc.template in the install root has the same shape with placeholder values, if you would rather copy and edit it.

If you are not uploading — testing on a closed network, or a demo install — set upload_enabled=0 in settings.txt. The encode still happens; only the upload spawn is skipped.

8. Venue calibration

Do this once, when the cameras are first mounted, and again after any physical movement of a camera. It is the most operator-intensive part of a deployment.

  1. Motion regions. Controller → Preview tab. For each feed click Set Region N, then click the upper-left and lower-right corners of the area where motion should be detected — the landing zone, not the spectator stands. The rectangle draws in red on the preview. Click Save Regions to write the values back to settings.txt.
  2. Grid lines. The core of distance measurement, and the step to budget real time for — about 30 minutes on a first deployment. See User guide § grid-line calibration for the anchor-point workflow.
  3. Auto-setup (optional). Derives timing and pixel-to-meter interpolation from practice runs and writes pixel_frames.txt. Either from saved practice footage via VDM.exe --auto-setup, or live at the venue using warm-up jumpers via the Auto Setup button. See User guide § auto-setup.

Lock the cameras down afterwards

Every calibrated value is tied to exactly where the cameras are pointing. Once grid lines are calibrated, any camera movement invalidates them and the distance readout becomes quietly wrong — it will still produce plausible-looking numbers.

9. Verification checklist

Run all five checks the day before the event. Never on event morning.

CheckHowPass looks like
All three captures stable for 2 minutes Watch the Processes tab and the title bar. capture[0..2] and motion[0..2] Running with unchanged PIDs; Δ[0] stays under about 30.
Per-feed motion detection working Wave a hand or a flag through each camera's field of view. The m[f] indicator in the title bar increments for that feed when motion crosses the region.
Encode path working Click Force Video. Within about 5 seconds an mp4 appears in output_videos\. Open it in VLC and confirm it plays.
Practice mode end to end Controller → Launch Practice. Run at least one full practice movie that auto-commits, then Stop All. Four processes spawn (practice_player plus three motion). All spawned processes exit cleanly — check Task Manager for orphans.
Capfile round trip Capture Feeds, record 30 s, Pause Recording, wait 10 s, Resume Recording, record 30 s, then stop. Three mp4s land in the output directory, one per feed, all play in VLC, with no gap at the pause point.

Never stop a recording with Task Manager

Killing capfile.exe mid-recording leaves the mp4 without a moov atom and it will not play in anything. Always use the stop button, which finalises the file properly.

Where to go next