[{"data":1,"prerenderedAt":245},["ShallowReactive",2],{"blog-\u002Fblog\u002Fwatching-the-watchers":3},{"id":4,"title":5,"author":6,"body":7,"coverImage":229,"description":230,"draft":231,"extension":232,"meta":233,"navigation":234,"path":235,"publishedAt":236,"readingTime":237,"seo":238,"stem":239,"tags":240,"__hash__":244},"blog\u002Fblog\u002Fwatching-the-watchers.md","Watching the watchers","Evan Ritter",{"type":8,"value":9,"toc":219},"minimark",[10,15,19,22,25,33,37,40,47,53,59,65,68,72,75,94,97,107,125,128,131,135,142,145,148,151,155,158,164,167,173,179,186,190,193,196,203,206,210,213,216],[11,12,14],"h2",{"id":13},"a-pi-a-dvb-t-hat-and-the-surprising-difficulty-of-knowing-whats-on-television","A Pi, a DVB-T HAT, and the surprising difficulty of knowing what's on television",[16,17,18],"p",{},"A mast on a hill, a few hundred metres of cable, an aerial on the roof, and you have access to most of what the country is putting out tonight. It's an unglamorous bit of infrastructure that has been quietly working in the background of my life for years.",[16,20,21],{},"A few months ago I got curious. What is the local transmitter actually sending right now? Not what the EPG says. Not what the listings magazines say. What's actually coming down the air, mux by mux, channel by channel, second by second?",[16,23,24],{},"The EPG is a guide. It's a promise. It's not a record of fact. If you want to know what was actually broadcast at 19:42 last Tuesday on your regional BBC One, the EPG isn't going to tell you. Neither, really, is anything else easily accessible. So I built a thing.",[16,26,27,28,32],{},"This is the story of that thing. It's a Raspberry Pi that watches television. Not streams it. Not records it for later. ",[29,30,31],"em",{},"Watches"," it — in the sense that it tries to understand what's on screen and write down what it sees.",[11,34,36],{"id":35},"the-shopping-list","The shopping list",[16,38,39],{},"The hardware was the easy part. The whole stack is off-the-shelf and reasonably cheap.",[16,41,42,46],{},[43,44,45],"strong",{},"Raspberry Pi 4B."," I started with the 2GB model and upgraded to the 4GB once I knew the project was going somewhere. I didn't go with a Pi 5 deliberately — it draws more power, runs hotter, and for a device that's going to sit on a shelf running 24 hours a day, the Pi 4 is more than capable. The Pi 5 is a better machine in absolute terms, but \"better\" isn't the same as \"right.\" For unattended always-on work, lower power and lower heat win. The 4GB Pi 4B is around £65–£85 in the UK depending on supplier.",[16,48,49,52],{},[43,50,51],{},"Sony CXD2880 DVB-T\u002FT2 HAT."," I went with a HAT rather than a USB tuner for a few reasons. The Pi's USB bus isn't fantastic — it shares bandwidth with the ethernet port on some models, and for sustained high-throughput work like streaming a transport stream to disk, you don't want anything competing. A HAT sits on the GPIO header, has its own clean power, and gets out of the way. The CXD2880 itself is genuinely good silicon — it's the chip inside a lot of consumer set-top boxes, and it does its job without drama. The official Raspberry Pi TV HAT is around £20 where you can still find it, though it's now being discontinued by some distributors, so worth grabbing one while they're around.",[16,54,55,58],{},[43,56,57],{},"SSD over HDD."," I went back and forth on this. An HDD is cheaper per gigabyte and for a project that's going to accumulate hours of recordings it's tempting. But spinning rust on a Pi is a bad idea for the long haul. SSDs draw less power, don't care about orientation or vibration, and don't have a mean-time-to-failure measured in spin-up cycles. I had a couple of suitable drives sitting in a drawer, which decided the matter — and that's just as well, because storage pricing in 2026 is having a moment. NAND flash is in global shortage thanks to AI data centre demand, SSD contract prices have doubled or worse since late 2024, and meaningful relief isn't expected before the end of the year at the earliest. If you're starting fresh, the advice is \"look around carefully and check the price the day you publish, because whatever I quote here will be wrong by the time you read it.\" Anything from 240GB upwards is plenty for the project.",[16,60,61,64],{},[43,62,63],{},"An aerial that already worked."," This is the bit nobody mentions in Pi project posts. Reception matters enormously, and the closer you are to a strong transmitter the easier everything is. I have a decent rooftop aerial that's been there longer than I have, with a strong, clean signal. If you tried to do this with a marginal indoor aerial in a fringe area, your problems would multiply considerably. Strong signal in, strong stream out — that's the whole game.",[16,66,67],{},"That's the hardware. The Pi and the HAT together are well under a hundred quid; the SSD is whatever today's market is doing to you. The interesting parts come next.",[11,69,71],{"id":70},"recording-the-stream","Recording the stream",[16,73,74],{},"If you Google \"record DVB-T on Raspberry Pi\" you'll mostly land on tutorials involving ffmpeg or VLC. Both work. Neither is what you want for unattended 24\u002F7 capture.",[16,76,77,78,82,83,85,86,89,90,93],{},"The tool I ended up using is ",[79,80,81],"code",{},"tzap",". It's old, it's lower-level, and the documentation isn't great, which is probably why it doesn't appear in the first ten Google results. What ",[79,84,81],{}," does is tune the demodulator on the DVB hardware to a specific multiplex and lock onto a transport stream. Once it's locked, the raw demultiplexed stream becomes available at ",[79,87,88],{},"\u002Fdev\u002Fdvb\u002Fadapter0\u002Fdvr0",". You can read from that file with plain ",[79,91,92],{},"cat"," and redirect to disk, and what you get is a clean MPEG-TS recording of exactly what came down the air.",[16,95,96],{},"That's it. That's the recording stack. No transcoding. No format conversion. No software trying to be helpful. The Pi tunes the tuner, opens a pipe, and shuffles bytes from the antenna to the SSD. It's about as close as you can get to \"plug the aerial into the file.\"",[98,99,104],"pre",{"className":100,"code":102,"language":103},[101],"language-text","tzap -c ~\u002Fchannels_final.conf -r \"BBC ONE S West\" &\ntimeout 3600 cat \u002Fdev\u002Fdvb\u002Fadapter0\u002Fdvr0 > recording.ts\n","text",[79,105,102],{"__ignoreMap":106},"",[16,108,109,110,113,114,117,118,120,121,124],{},"The one piece that's genuinely fiddly is the ",[79,111,112],{},"channels.conf"," file. It's a colon-separated list of tuning parameters: frequency, modulation type, transmission mode, guard interval, FEC, hierarchy, and so on. If you've ever looked at a ",[79,115,116],{},"wpa_supplicant.conf"," and thought \"I wonder how much worse this could get,\" ",[79,119,112],{}," is the answer. The good news is you only have to assemble it once, and there are tools (",[79,122,123],{},"w_scan"," is one) that will do most of the work for you by sweeping the band and noting what's there.",[16,126,127],{},"Once you've got it, recording is the easy part. The file lands on disk, MPEG-2, 704×576, 25 frames per second. SD by modern standards — good enough for a 2002 television and that's exactly what it is.",[16,129,130],{},"Now you have a file. The file is just bytes. The hard bit comes next.",[11,132,134],{"id":133},"the-thing-nobody-tells-you-about-uk-dtt","The thing nobody tells you about UK DTT",[16,136,137,138,141],{},"I had assumed, when I started, that the EPG data was just ",[29,139,140],{},"in there",". DVB transport streams can carry EPG information in something called the EIT — the Event Information Table. It's part of the spec. Set-top boxes use it. Your TV uses it. Why wouldn't I be able to parse it and just know what's on?",[16,143,144],{},"I spent longer than I'd like to admit trying to work this out. The short version: on UK DTT, particularly on the older MPEG-2 SD multiplexes, the EIT data carried in the stream is patchy at best. Some channels carry a present\u002Fnext entry that tells you what's on now and what's on next, sometimes with start times that lag reality. Some carry essentially nothing useful. The full schedule data that your TV uses to populate its EPG is, in many cases, being pulled from elsewhere or filled in from cached data the receiver has built up over time. Pointing a DVB tuner at a multiplex and saying \"tell me what's on\" doesn't get you the answer you'd expect.",[16,146,147],{},"This was, in a way, the moment the project became interesting. If the EPG had been embedded and reliable, the problem would have been a parsing exercise. Read the EIT, write the answer to a database, go home. The fact that it wasn't meant the only way to know what was actually on the screen was to look at the actual screen.",[16,149,150],{},"Constraint is the engine of interesting engineering. The simple solution wasn't available, so a harder solution became necessary.",[11,152,154],{"id":153},"looking-at-the-picture","Looking at the picture",[16,156,157],{},"This is where the project stops being about broadcast infrastructure and starts being about computer vision. And it's also the part where I'm going to be a bit careful, because some of what I've worked out is genuinely useful and I'd rather not have it copy-pasted into someone else's weekend project. But the general principles are worth talking about.",[16,159,160,163],{},[43,161,162],{},"Downscale first."," The native stream is 704×576. That's about 400,000 pixels per frame. For the kind of analysis I'm doing — recognising the general visual character of what's on screen — that's massively more detail than I need. I downscale aggressively, to 320×180, before doing anything else. The features that matter for this kind of work (broad scene structure, logo presence, on-screen text, overall colour distribution) survive the downscale fine. The features that don't matter (face detail, fabric texture, individual leaves on a tree) disappear into the noise where they belong.",[16,165,166],{},"The principle generalises: throw away pixels until the pixels you have left are the ones doing real work. People reach for more resolution by default because more is more. For analysis on a constrained device, more is usually just slower.",[16,168,169,172],{},[43,170,171],{},"Don't process every frame."," 25 frames per second is 25 chances to look at essentially the same picture. The interesting events on a TV screen — a programme starting, an advert break, a station ident, a scene change — happen on second-or-longer timescales. I sample at three-second intervals. Anything that changes faster than that is either an advert or noise, and you can deal with both separately. The Pi spends most of its time doing nothing, which is exactly what you want for an always-on device that should run cool and last.",[16,174,175,178],{},[43,176,177],{},"OpenCV is enough."," I'm not using TensorFlow. I'm not using a GPU. There is no model to train. Vanilla OpenCV running on the Pi 4 is more than capable of the analysis I'm doing, and the principle behind that is one I'd encourage anyone working in this space to internalise: a lot of problems that get framed as \"AI problems\" are actually classical computer vision problems with sensible preprocessing. Reaching for the heavy ML stack too quickly is a way of paying a lot of complexity tax for something that didn't need it.",[16,180,181,182,185],{},"What the Pi is actually ",[29,183,184],{},"looking at"," — the features it's extracting, how it's deciding what kind of programme is on, how it handles transitions and edge cases — is the part I'm not going to go into. Partly because it's still evolving and I don't want to write down something I'll regret in three months, and partly because that's where the genuinely hard work has been done. The hardware is the easy bit. The pipeline is the easy bit. Working out what the pictures actually mean is where the time has gone.",[11,187,189],{"id":188},"what-it-can-and-cant-do","What it can and can't do",[16,191,192],{},"I want to be honest about this, because I think this is the most useful part of the post for anyone considering a similar project.",[16,194,195],{},"It works well enough to be interesting. It can tell you, broadly, what kind of programme is on at any given moment. It can spot an advert break. It can notice when one programme ends and another begins, most of the time. As a personal curiosity project running on a Pi on a shelf in Cornwall, telling me what came down the air from Redruth this afternoon, it is doing exactly what I wanted it to do.",[16,197,198,199,202],{},"Making it ",[29,200,201],{},"reliable",", in the sense that you could trust it to produce a clean, accurate, complete log of what was broadcast across all the awkward cases, is a much harder problem. Continuity announcers talking over the start of the next programme. Mid-programme idents and \"next\" promos. Ad breaks that don't quite line up with where you'd expect. Regional opt-outs where Cornwall sees something different from London. Late schedule changes. Live programmes that overrun. The cases where the picture is genuinely ambiguous because the broadcaster has chosen to make it ambiguous — fades through black between an end-credits roll and a station ident, for example — are real and they're hard, and any honest treatment of this problem has to acknowledge them.",[16,204,205],{},"I haven't solved those. I've solved enough of them to find the project rewarding. The gap between \"interesting weekend project\" and \"reliable production system\" in this space is enormous, and I've been able to see the shape of that gap more clearly the further into the project I've gone.",[11,207,209],{"id":208},"why-bother","Why bother?",[16,211,212],{},"A reasonable question. The honest answer is: because I wanted to. The project lets me poke at a piece of infrastructure that's been part of my daily life for years, and the engineering is genuinely fun. Computer vision on a Pi watching MPEG-2 SD off an aerial is the kind of project that hits a sweet spot between \"old enough to be approachable\" and \"constrained enough to be interesting.\"",[16,214,215],{},"I've learned more about DVB-T, DTT muxing, MPEG transport streams, and classical computer vision in the last few months than in the previous ten years. The country broadcasts; the Pi watches; the disk fills up with a record of what actually happened.",[16,217,218],{},"It turns out there's quite a lot worth knowing in there. If any of this sounds interesting, the parts are cheap (well — most of them), the documentation is patchy, and the rabbit hole is deeper than it looks. Mind your step.",{"title":106,"searchDepth":220,"depth":220,"links":221},2,[222,223,224,225,226,227,228],{"id":13,"depth":220,"text":14},{"id":35,"depth":220,"text":36},{"id":70,"depth":220,"text":71},{"id":133,"depth":220,"text":134},{"id":153,"depth":220,"text":154},{"id":188,"depth":220,"text":189},{"id":208,"depth":220,"text":209},"\u002Fblog\u002Fwatching-the-watchers\u002Fcover.png","A Pi, a DVB-T HAT, and the surprising difficulty of knowing what's on television.",false,"md",{},true,"\u002Fblog\u002Fwatching-the-watchers","2026-05-23",11,{"title":5,"description":230},"blog\u002Fwatching-the-watchers",[241,242,243],"raspberry-pi","broadcasting","computer-vision","IDJ7zGnbzJA-GTRLIzE3V51AU3mBYnSqclDqYDcS364",1779548066040]