TL;DR: https://gitlab.com/markotka/zx-spectrum-tape-archiver
For years, I’ve been slowly digitising my vintage computer collection — taking photographs, cataloguing machines, and preserving software. But one category always intimidated me more than the others: cassette tapes for the ZX Spectrum.
Unlike floppy disks (which you can usually image in a few minutes), cassettes are slow, noisy, mechanical, and—above all—time-consuming. A single 30-minute game tape loads at roughly the speed of geological processes. When you have dozens or even hundreds of tapes to archive, the task becomes overwhelming.
This blog post tells the story of how I built a small, automated pipeline to turn a chaotic box of Spectrum tapes into clean, organised TZX files with almost no manual work. The tools are simple, the setup is reliable, and—most importantly—once everything is prepared, the process feels almost effortless.
The Problem: Too Many Tapes, Not Enough Time
The project began when I received a few dozen old ZX Spectrum cassettes. Some were commercial releases, some home-recorded compilations, and others simply unlabelled. I wanted to preserve everything:
- Even “junk” tapes sometimes contain rare or personal software.
- Many home-recorded compilations have programs you won’t find elsewhere.
- Cassettes degrade with age. Time was not on my side.
My original approach was naïve: record a WAV manually → name it → convert to TZX → check it → repeat.
It quickly became clear that I’d never finish the batch that way. I needed a pipeline that allowed me to work like this:
- press Play on a cassette,
- press Enter on the PC,
- come back 30–45 minutes later.
Everything else—naming, detection, conversion—should happen automatically.
Part 1: Designing a Pipeline That Works With Human Nature
There are two ways to speed up archiving:
- Record faster (not possible; tape is tape)
- Reduce the number of things the human has to do
I chose the latter.
Goal: one command for recording, one for conversion
If each tape requires even 30 seconds of manual activity, you’ll burn hours before real progress happens. So I designed the pipeline with a philosophy:
Every point of friction is multiplied by the number of tapes.
This is how the foundation of the project was born.
Part 2: Recording the Tapes — Hands Off as Much as Possible
The heart of the recording stage is a simple batch file (record_tape.bat) powered by FFmpeg. FFmpeg can record from a sound device directly to WAV with no GUI, no clicks, no dialogs.
But discovering the correct audio device name in Windows is surprisingly annoying. You get one of those DirectShow monsters:
@device_cm_{33D9A762-...}\wave_{97F01462-...}
Once you put that into the script, everything becomes easy.
The Recording Script Does Three Important Things
Smart filename generation If
Tape003_A.wavalready exists, it will automatically pickTape003_B.wav, and after both sides are done, it jumps toTape004_A.wav.Auto-stop after 45 minutes Long enough for a full C90 side, but short enough to guarantee you don’t accidentally record silence forever.
A dry-run preview So you always know what filename the script intends to use before it starts recording.
The effect is magical. I put in a tape, press Play, hit Enter, and walk away. The PC handles the rest. If your cassette deck has the auto stop functionality, you can go out for a drink without worries.
Part 3: Converting WAV to TZX — The Easy Part
Once you have a folder full of WAV files, the next logical step is to convert them into TZX format. For this, I rely on tzxtools: https://github.com/shred/tzxtools?tab=readme-ov-file.
The conversion script (convert_to_tzx.bat) does exactly what I needed:
- looks in
tape_rips/ - processes every WAV it finds
- outputs corresponding TZX files into
tape_tzx/ - stores logs in
temp/
No prompts. No dialogs. Just clean, predictable output.
Part 4: The Surprise Twist — Many TZX Files Contain More Than One Program
One pleasant “problem” with old home-recorded cassettes is that people frequently packed multiple programs on a single side:
PSSST
→
JETPAC
→
MANIC MINER
→
A homemade BASIC program
Recording such a tape produces a single 30–40 minute WAV file, which converts into a single giant TZX file.
Inside it may be 3–10 independent programs.
To solve this, I added a Python script (extract_blocks.py) which uses tzxsplit.exe. It:
- scans each TZX file,
- detects individual program blocks,
- splits them cleanly into separate TZX files,
- saves them under
tape_tzx_split/.
It’s a second layer of automation: even if you throw a 45-minute recording at it, it will dissect the programs quietly in the background.
Part 5: The Final Structure (Everything Has Its Place)
After a few iterations, the project settled into a structure that feels intuitive:
tape_rips/ => Raw WAV recordings
tape_tzx/ => Converted TZX files
tape_tzx_split/ => Split TZX files (one per program)
temp/ => Logs, trash, working files
tools/ => ffmpeg and tzxtools binaries
src/ => Batch files and python scripts
You can drop the project on any machine and start archiving immediately. No installers. No dependencies scattered across your system.
It’s self-contained, like a portable preservation kit.
Part 6: Hardware Setup — Keeping It Simple
My setup looks like this:
- a reliable cassette deck (any well-calibrated unit works),
- a small USB audio interface (e.g. Roland Go:Mixer Pro X),
- FFmpeg configured to use the correct audio input device,
- Audacity used only for initial level calibration.
Once the levels are set, I no longer need Audacity at all.
The actual archiving process becomes:
- Insert tape
- Press Play
- Hit Enter
- Come back later
It’s astonishing how few moving parts are needed once the automation is in place.
Part 7: The Experience of Archiving at Scale
With the full pipeline in place, I archived 10+ tapes in a single weekend while doing completely unrelated tasks. The computer quietly generated WAVs, TZXs, and split-program TZXs. All I had to do was change tapes every now and then.
The beauty of the system is not in how “clever” it is, but in how little attention it demands from me.
The pipeline doesn’t fight me. It lets me preserve history without burnout.
Part 8: Why I Built This (And Why It Matters)
Digital preservation is often less romantic than it sounds. It’s not about uncovering lost masterpieces—though sometimes that happens. Most of the time, it’s repetitive, slow, and physically tedious.
But once preserved:
- a cassette no longer depends on rubber belts and magnetic oxide,
- its data becomes shareable, analyzable, and immortal,
- the software becomes accessible for research or nostalgia.
This pipeline isn’t just a convenience—it’s a small contribution to keeping old software alive.
Part 9: If You Want to Try It Yourself
I’ve uploaded the tools, scripts, and instructions here:
GitLab project https://gitlab.com/markotka/zx-spectrum-tape-archiver
The only external components you need are:
- FFmpeg: https://www.ffmpeg.org/
- tzxtools (
tzxwav,tzxsplit): https://github.com/shred/tzxtools?tab=readme-ov-file - a cassette deck + audio interface
Everything else is bundled.
If you have a pile of dusty ZX Spectrum tapes somewhere, this pipeline might save you days—maybe weeks—of manual work.