You did everything the capture articles asked. You found a deck, you tapped the RF, you sat through a transfer in real time, and now there is a file on the disk — a big one, maybe several gigabytes per tape — with an extension like .lds or .flac that no media player will touch. Double-click it and nothing happens, or you get a wall of noise. What you have is the raw radio-frequency signal straight off the tape which is not meant to be watched directly — it is the input to the next part of the job that actually turns a capture into a picture. That next half is what this page is all about: how to use the next step (vhs-decode) to turn a stack of these RF files on disk into a watchable, keepable archive. If you have landed here without the earlier context, the mechanism is laid out in how vhs-decode actually works, and the transfer itself in the capture hardware guide.
Capturing is not decoding
Capture and decode are two separate jobs, and if you’re reading this, you’ve likely done the first. Capture simply takes the raw signal that comes off the spinning heads (the modulated radio frequency), before it has been converted, (traditionally by the player) into anything you would recognise as a picture. A normal VCR does this decoding in hardware, on the fly, with circuits from the 1970s/1980s, the new software based RF approach skips all of that and saves the untouched original signal so that software can do the work afterwards, far more accurately and this can be repeated over and over until the result is as good as you need. The file you are looking at is that untouched signal. Decoding is the software pass that reads it and reconstructs the image, line by line.
The decoder is more like a reconstruct capability than a restore capability. The decoder rebuilds the picture from what the tape actually had, it does not add anything that was never recorded and although there are some magic things that happen, it doesn’t really make a tired tape look new by modern standards. This confuses enough people that I have written a spin out piece on it — why AI upscaling doesn’t fix old tapes — but it is still worth doing this. Because you want a faithful reconstruction of whatever the source holds, not some AI interpretation of it. VHS-Decode will get you the best possible ORIGINAL data from your tape.
Step 1 — how to use vhs-decode
The first command takes the RF file and produces the picture data. The tool accepts a spread of input formats depending on how you captured: .lds (the 40 MSPS packed format a Domesday Duplicator writes by default), .ldf (the same thing FLAC-compressed), a plain .flac from a CX card capture, or raw samples such as .u8. One firm rule: the capture has to be lossless or raw. A capture saved to MP3 or Vorbis is ruined for this purpose — those codecs discard exactly the signal detail the decoder needs.
The command form is straightforward — an input file and an output name, with the output name being a base rather than a filename with an extension:
vhs-decode --pal --tape_format VHS --threads 4 input.lds my-first-decodeA handful of flags carry most of the weight. In plain terms: The system flag — --pal or --ntsc — is not optional: the decoder cannot guess whether it is looking at a 625-line PAL signal or a 525-line NTSC one, and getting it wrong gives you a broken picture with the wrong colour and the wrong framerate. --tape_format defaults to VHS, so you only set it for S-VHS, Video8, Betamax and the like only. --tape_speed (or --ts) tells it SP, LP or EP; the long and extended-play modes use different de-emphasis, so leaving it off on an EP recording gives you the wrong result. And --threads behaves in a way that might be what you think, three or four is the sweet spot and piling on more cores actually makes it slower. The work simply does not parallelise past that point – if you have a lot of tapes, you can parallelise the work using DdD Capture Toolkit which automates this and supports batching and a whole bunch of other features to make life easier.
Beyond those, there is a small set of options I would turn on as a matter of course — in fact they are the defaults I ship in DdD Capture Toolkit, because they earn their place on the great majority of tapes without you having to think about them. --no_resample skips a resampling step that is not needed when the capture is already at the rate the decoder works in, which saves a little time. --recheck_phase re-checks the colour phase on every frame rather than trusting the first lock, so colour holds together across scene changes and tape joins where it would otherwise slip. And --ire0_adjust pulls the black level to sit at IRE 0 where it belongs, so blacks come out properly black rather than lifted and grey. Folding those in, a dependable starting command looks more like this:
vhs-decode --pal --tape_format VHS --threads 4 --no_resample --recheck_phase --ire0_adjust input.lds my-first-decodeThose are of course not all the available options. vhs-decode carries a long list of other options — for black-and-white sources, for stubborn signals, for chasing down a particular artefact and the right ones depend entirely on what is on the tape and how it was captured. The three above are a sound default for an ordinary PAL colour VHS recording; the rest are worth reaching for case by case.
When it finishes you will have three files sharing your output name. The .tbc is the luma — the brightness picture, time-base-corrected, stored as raw greyscale. The _chroma.tbc is the colour, demodulated separately (more on why in a moment). And the .tbc.json is a metadata sidecar — it records the system, the position of every field in the original signal and the dropout coordinates. Don’t delete these intermediary files until after you have the finalised copy you’re happy with as the downstream tools genuinely need these. I treat that JSON as part of the master: even if you later delete the big intermediate files, keep the JSON and the log, because they hold the field timing the audio-sync step depends on.
Decoding runs well below real time. On a typical desktop you can expect somewhere around three to five frames per second, which means a two-hour tape can take anywhere from twelve to thirty-plus hours, depending on the machine and how noisy the capture is. Apple Silicon does noticeably better an older quad-core does noticeably worse. The bottleneck is memory bandwidth rather than raw clock speed, so a faster CPU helps less than you would initially think. The one piece of advice I would treat as non-negotiable is to decode to and from an SSD or nvme, spinning disk is just too slow. And if hand-running each of the stages below is not your idea of a good time, there is DdD Capture Toolkit available to automate this.
Step 2 — check it before you commit the hours

Given how long a full decode takes, the most valuable habit I can pass on is to look at the result before you commit to the whole tape. The tool for that is ld-analyse, which opens the .tbc and its chroma companion and lets you inspect them. A few things are worth your attention. The picture itself, obviously — but turn on the dropout overlay, which marks missing signal in red and blue, and you get an immediate read on how clean the transfer is. The graph I check first is Black SNR: you want a roughly flat line, and as a rough guide anything around 30 dB and up is usable, while 44 to 50 dB is excellent. Dips and spikes in that line point to dropouts, interference or a weak signal. The third view I lean on is the field split, which shows the two fields of a frame side by side — one bad field next to one clean field is the tell-tale signature of a dirty head or a head clog.
The faults have fairly legible signatures once you have seen them. A picture that is skewed or will not lock, usually with a grainy texture, most often means a sample-rate or system mismatch or RF that was down-sampled too far on capture. No colour, or weak washed-out colour, shows up as a vectorscope that collapses toward the centre meaning the colour reference has likely been lost. Hard white lines and a heavy “snowing” look point to tracking loss and weak RF. None of these need a full two-day decode to diagnose. A ten-second test export tells you almost everything before you start the long run, and it costs you a few minutes rather than an day of decode you’ll have to redo.
Step 3 — colour is a separate pass
VHS does not record colour the way broadcast composite does, instead it shifts the colour down to a lower frequency and lays it underneath the brightness — the so-called colour-under system. The decoder demodulates the two separately and keeps them in separate files for a good reason, when colour and brightness share one signal, the leftover colour subcarrier shows up in the picture as dot crawl, like a crawling checkerboard along sharp colour edges. Keeping luma and chroma apart means neither contaminates the other, and the dot crawl never gets baked in.
The colour reconstruction is done by ld-chroma-decoder, and you can choose a decoder for it depending on what your needs are. For VHS colour-under, the 2D comb decoders are the standard go to decoders — pal2d for PAL, ntsc2d for NTSC. The clever-sounding options — the Transform decoders and the 3D comb — are built for clean LaserDisc and composite sources, and they actively misbehave on VHS, because the per-line phase rotation in the colour-under signal breaks the assumptions those filters rely on. So the rule of thumb is plain: 2D for VHS, and leave the 3D and Transform modes for cleaner sources.
In practice, though, most people never call ld-chroma-decoder by hand. The export tool in Step 5, tbc-video-export runs it for you — it is essentially dropout correction, the chroma decode and ffmpeg bundled into one command — three or four programs combined more or less. It is useful to understand what is happening under that one command, but you do not normally drive the colour pass yourself.
Step 4 — the audio path
Depending on the hardware you’ve got, audio can be it’s own small project or inconsequential. VHS holds sound in two main ways. There is the linear edge track, a thin audio-cassette-style stripe along the edge of the tape, usually mono which is captured as ordinary ‘baseband’ audio off the deck’s RCA outputs. And there is Hi-Fi FM, the sort of near-CD-quality stereo carried under the video, which you can either take as baseband via the RCA jacks or, for the cleanest result, capture as raw RF from a Hi-Fi tap and decode with hifi-decode into a 24-bit, 48 kHz FLAC.
The catch is sync. The decoded video comes out at a perfect, normalised framerate — exactly 25 or 29.97 frames per second. The tape, though, never played at a perfectly steady speed, and if the audio was captured on a separate device, that device can and will have a clock that drifts independently to the video. This means the audio creeps out of sync over a long recording even if it started aligned. There are three main things to get this fixed: 1 – Ensure your audio and video hardware has a syncronised clock (the ClockGen / Clockgen Lite or MISRC approach) to remove the drift between devices, 2 – An initial offset read from the .tbc.json lines up the start and 3 – The drift compensation tool — VhsDecodeAutoAudioAlign, also called vhs-decode-aaa — uses the per-field timing in that JSON to stretch the audio to match the video’s real field-by-field timing across the whole tape. Anything longer than a short clip really wants that last step. I have gone into the capture-side of this in more depth in the capture hardware and audio-sync guide, which is the place to look if sync is your sticking point. Again, this is all automated in the DdD Capture Toolkit.
Step 5 — export the archival master
The .tbc files still are not something you can hand to a relative; they are raw greyscale data. The last step turns everything into a finished file, and it is a single command:
tbc-video-export --ffmpeg-profile ffv1 my-first-decode.tbc my-first-decode.mkvThat gives you FFV1 video (a lossless codec, the rough equivalent of FLAC for pictures) inside a Matroska .mkv container, exported as 10-bit 4:2:2 with the audio muxed in. The choice of format is not arbitrary, and this is one area where the reasoning rests on something firmer than community habit. FFV1 is a published standard, set out in IETF RFC 9043, and Matroska likewise in RFC 9559, both produced by the IETF’s CELLAR working group. The United States Library of Congress lists FFV1-in-Matroska as a “Preferred” format for video preservation in its Recommended Formats Statement — a status it reached in 2023 with input from the Federal Agencies Digital Guidelines Initiative (FADGI), which funded the work needed to close the remaining gaps. The EU’s PREFORMA project, in the same vein, funded the open-source MediaConch tool that checks files for conformance to those standards. In other words, the format you are exporting to is the one that national archiving institutions have settled on for keeping moving images — which is a reassuring place for a family archive to land.
One distinction is worth making explicit: the FFV1/MKV file is your export master, not your viewing copy. It is large and lossless, and its job is to be the authoritative version you keep and never touch again (unless you want to re-export from the true master RF files). From this you derive a small access copy — an H.264 or H.265 which is the one you actually watch, share and put on a phone. Keep the master, distribute the derivative.
When you’re starting out, the storage is really easy to underestimate. An FFV1 master from the export step is roughly 40 to 50 GB per hour of VHS. A six-hour tape, then, is somewhere around 250 to 300 GB on its own. Noisier tapes compress less and sit at the top of that range. A serious project (i.e. multiiple captures) of a hundred-plus hours is squarely into multi-terabyte territory, and this is in addition to the tbc files and rf captures that you’ve already created above. It’s worth knowing because you need to plan how your fast SSD’s and slower HDD’s will be used throughout the process.
An alternative path through the same chain
Everything above is a chain of commands you can absolutely run by hand, and I would argue it is worth understanding them at least once — when something goes wrong, knowing what each stage does is the difference between a quick fix and a baffled evening. But once you are working through a stack of tapes, remembering the exact flags for every stage, every time, one at a time, gets old fast, and that is where mistakes creep in. So I will mention DdD Capture Toolkit here, because it exists for exactly this. DdD-capture-toolkit, an open-source Python project that runs the whole pipeline for you — capture, decode, compress, export, validate and archive — with hardware-aware scheduling so several decodes can run at once, a realy nice capability when you have a large multi-tape archiving project. And the fiddly audio sync is handled for you.
A valuable addition is what DdD Capture Toolkit does at the end: it does per-project SHA-256 hashing for archival and a three-tier compression-integrity check, so you can confidently delete the huge intermediate Time Base Corrector (TBC) files and the non compressed RF file once the master and compression is complete. It is aimed at bulk, serious archiving — the kind of work where large projects need repeatable transfers. Linux is the first-class platform; macOS and Windows have the groundwork laid but still want testers, so if you are on either, reports are genuinely welcome. None of this replaces the manual method if that’s what you prefer and it is the right way to learn — it just spares you re-typing the flags on tape number forty and gives you a health batch speed up with an archival oriented focus.
Things to know
The first and hardest limit is the old rule: garbage in, garbage out. The first and hardest is the old rule: garbage in, garbage out. The decode reconstructs the RF you captured, and it cannot invent picture that a bad capture, a worn tape or an EP-speed recording never preserved in the first place. A weak signal stays weak, a recording made at extended play, with its narrower tracks, has a lower quality baked in that no software pass can improve. This is the same trap AI upscaling falls into — synthesising plausible detail is not the same as recovering real detail which I have set out exactly why in why AI upscaling doesn’t fix old tapes.
Dropout correction deserves a comment, because it is easy to over-trust. It is concealment, not reconstruction. Dropout correction copies picture from the matching field alongside to cover over a loss. That works invisibly on still or slow material, but it smears on fast motion, because the borrowed content no longer matches. And where the signal was never captured at all, a clogged head, a tape that is shedding, a physical break — there is nothing adjacent to borrow from, so the loss simply stands. Hi-Fi audio currently has no dropout correction at all, so a loss in the captured audio is still an audible loss.
There is a practical cost. The decode is slow and CPU-bound, there is no GPU acceleration to fall back on and the files are large at every stage. And it is genuinely command-line and multi-step, with format-specific flags at each turn, which means there is a real learning curve and plenty of room to get a setting wrong. It is a powerful workflow that produces a better master than any other option I’ve tried (and I’ve tried basically all of them), so it’s worth it if you have something you care about.
What’s next
Once you have a master you trust you need to think about how best to keep the file, it’s checksums, copies, a storage plan that outlives you or the drive it is on and a storage structure someone else could understand if you’re no longer around. I have written that side up in designing a family archive that survives you — the preservation part, which is the natural next read from here.
Thanks for reading and I hope you enjoyed it!
Marshalleq.








