After “Monty Python’s Flying Circus” ended, Graham Chapman worked with an up-and-coming young writer named Douglas Adams on a new sketch comedy show for the BBC. It was called “Out of
the Trees,” and it bombed. Only one episode was made, and that aired only once, on January 10, 1976.
Once the Beeb gave up on “Out of the Trees,” they did to it what they did to so many other programs of that era: they erased it.
…
Chapman had recorded the show on one of the very earliest home videotape formats… it took two years to build a compatible player.
It’s neither Chapman nor Adams best work, and you can see how it got canned after only a pilot episode. But it’s not terrible.
But the lesson here is one about the challenge of archiving non-print media. Anything that needs a device to “play” it, whether it’s as simple as a vinyl record or as complex as a
videogame, is at greater risk of being lost forever. And the faster the pace of technology moves, the more stuff gets left behind as technology moves on. Is a digital dark age looming?
Are we already in it, but that won’t be known until some future date?
This weekend, I threw a Virtual Free Fringe
party for some friends. The party was under-attended, but it’s fine because I got to experiment
with some tech that I’d been meaning to try.
The Abnibbers and I have experimented with watching things together, but apart, before, but this is the first time we’ve watched stand-up comedy this way.
If you ever want to run something like this yourself1, here’s how I did it.
My goals were:
A web page at which any attendee could “watch together” a streaming video2,
A “chat” overlay, powered by a WhatsApp group3 (the friend group I
was inviting were all using WhatsApp anyway, so this was an obvious choice), and
To do all the above cheaply or for free.
I’m a big fan of experiments. Contrary to this picture, though, they’re usually software experiments.
There were two parts to this project:
Setting up a streaming server that everybody can connect to, and
Decorating the stream with a WhatsApp channel
Setting up a streaming server
Linode offers a free trial of $100 of hosting credit over 60 days and has a ready-to-go recipe for installing Owncast, an open-source streaming server I’ve
used before, so I used their recipe, opting for a 4GB dedicated server in their London datacentre: at $36/mo, there’d be no risk of running out of my free trial credit even if I failed
to shut down and delete the virtual machine in good time. If you prefer the command-line, here’s the API call for
that:
The IP address got assigned before the machine finished booting, so I had time to copy that into my DNS configuration so the domain was already pointing to the machine before it was fully running. This enabled it to get its SSL certificate set up rightaway (if not, I’d have had to finish waiting for the DNS change to propogate and then reboot it).
Out of the box, Owncast is insecure-by-default, so I wanted to jump in and change some passwords. For some reason you’re initially only able to correct this over unencrypted
HTTP! I opted to take the risk on this server (which would only be alive for a few hours) and just configure it with this
limitation, logging in at http://mydomain:8080/admin with the default username and password (admin / abc123), changing the credentials to
something more-secure. I also tweaked the configuration in general: setting the service name, URL, disabling chat features,
and so on, and generating a new stream key to replace the default one.
Now I was ready to configure OBS Studio to stream video to my new Owncast server, which would distribute it to anybody who tuned-in.
Next up, we need to make WhatsApp appear on the stream with a little bit of CSS hackery.
Decorating the stream
I configured OBS Studio with a “Custom…” stream service with server rtmp://mydomain:1935/live and the stream key I chose when configuring Owncast and kicked off a test
stream to ensure that I could access it via https://mydomain. I added a VLC source4
to OBS and fed it a playlist of videos, and added some branding.
With that all working, I now needed a way to display the WhatsApp chat superimposed over the video.For this, I added a Window Capture source and pointed it at a Firefox window that was
showing a WhatsApp Web view of the relevant channel. I added a Crop/Pad filter to trim off the unnecessary chrome.
The same technique, of course, could be used to superimpose any web page or whatever other content you like onto a stream.
Next, I used the Firefox debugger “Style Editor” to inject some extra CSS into WhatsApp Web. The class names vary frequently, so
there’s no point we re-documenting all of them here, but the essence of the changes were:
Changing the chat background to a solid bright color (I used red) that can then be removed/made transparent using OBS’s Chroma Key filter. Because you have a good
solid color you can turn the Similarity and Smoothness way down.
Making all messages appear the same (rather than making my messages appear different from everybody else’s). To do this, I added:
.message-in, .message-out { align-items: flex-start !important; } to align them all to the left
[aria-label="You:"]::after { content: "Dan Q"; height: 15px !important; display: block; color: #00f !important; padding: 8px 0 0 8px; } to force my name to appear
even on my own messages
[aria-label^="Open chat details for "] { display: none; } to remove people’s avatars
[data-testid="msg-meta"] { display: none !important; } to remove message metadata
A hacky bit of CSS to make the backgrounds all white and to remove the speech bubble “tails”
Removing all the sending/received/read etc. icons with [data-icon] { display: none; }
I aimed where possible to exploit selectors that probably won’t change frequently, like [aria-label]s; this improves the chance that I can use the same code next time. I
also manually removed “old” messages from the channel that didn’t need to be displayed on the big screen. I wasn’t able to consistently remove “X new messages” notifications, but I’ll
probably try again another time, perhaps with the help of an injected userscript.
A little bit of a shame that more people didn’t get to see the results of this experiment, but I’m sure I’ll use the techniques I’ve learned on another ocassion.
Footnotes
1 Or, let’s be honest, if you’re Future Dan and you’re trying to remember how you did it
in last time.
3 This could probably be adapted for any other chat system that has a web interface, so if
you prefer Telegram or Slack or whatever ever, that’s fine.
4 OBS’s VLC source is just amazing: not only can you give it files, but you can give it
URLs, meaning that you can set up a playlist of YouTube videos, or RTSP security camera feeds, or pretty much anything else you feel like (and have the codecs for).
The problem of “needing to be able to hear from two Bluetooth sources at once” is so real for me that I came up with a solution that I genuinely use all the time. You’re not going to
like it, though.
Solution in video (no audio needed; no need to fix your headphones first!):
This post is also available as an article. So if you'd
rather read a conventional blog post of this content, you can!
This video accompanies a blog post of the same title. The content is mostly the same; the blog post contains a few extra elements (especially in
the footnotes!). Enjoy whichever one you choose.
I don’t even like sudoku. And if you’d told me in advance that I’d enjoy watching a man slowly solve a sudoku-based puzzle in real-time, I’d have called you crazy. But I watched it
again today, for what must’ve been the third time, and it’s still magical. The artistry of puzzle creator Mitchell Lee is staggering.
If you somehow missed it the first time around, now’s your chance. Put this 25-minute video on in the background and prepare to have your mind blown.
A video, in which I rant about the challenges of carrying two-childrensworth of school gear while dragging our dog, herding somebody else’s dog, and trying to stop the kids from
fighting. Some mornings it’s easy. Today… it was not. Also available on YouTube.
A friend said that this story sounded like it belonged in an illustrated children’s book and sketched this while on her first call of the morning.
Full transcript of the audio (except for the ocassional snorting sounds of our noisy Frenchie as she snuffles about in the background):
The morning school run is never effortless. But some days it’s easy.
Today was not one of those days.
It’s a Wednesday. So, for some strange reason, that’s the heaviest-laden day. And so, with the eldest child on her bike and the youngest on his scooter I set off, pulling the dog, and
carrying a PE kit, two book bags, two water bottles, and a guitar.
I should have realised early on that today wasn’t going to be a day that the universe smiled on me when the dog immediately ran off into a ditch to take a dump and I had to clamber down
into the ditch with a poop bag to fill it.
But while I’m coming out of the ditch I discover that the youngest child has zipped off up ahead in an effort to ram into his older sister and in doing so has inevitably flipped himself
over the handlebars of his scooter and is now lying, crying, in the middle of the road.
So I go over to him dragging the dog and carrying a PE kit and two book bags and two water bottles and a guitar and a bag full of poop and as best I can, carrying all those things,
console him and eventually, with some encouragement he’s able to get back up and carry on walking to school, but says he can no longer scoot, so I have to carry the scooter.
Now I’m dragging a dog and carrying a poop bag and a PE kit and two water bottles and two book bags and guitar… and a scooter… and that’s when the oldest child manages to throw the
chain off her bike.
Now she’s had little experience, in her defence, of the chain coming off her bike. And so she does the absolute worst thing possible which is tries to pedal as hard as possible to solve
the problem which makes it much worse. By the time I get there the chain is royally snarled between some of the sprockets and their housing, so I put down the guitar and the bag of poop
and I hand the lead to the younger child so that I can try to unpick the older child’s chain from her bike, getting myself covered in oil.
And that’s when I notice the commotion up ahead. There are some workmen who are rebuilding the wall outside Letterbox Cottage, and – up ahead of them – barking furiously, is a small
dog. This dog is Lovey, and she belongs to a friend of ours. And she’s probably the best example of whatever the opposite of nominative determinism is. Because Lovey is a truculent
little bitch. Lovey is a tiny small yappy dog who will start a fight with other dogs, try to see off workmen (which is what she’s doing at the time), and she’ll bark at passing cars.
And right now she’s running free, unattended, in the middle of the road. And one of the workmen says to me, “Oh, do you know who’s dog that is?” and I have to admit that yes, I do.
So, dragging our dog and carrying a PE kit and two book bags and two water bottles, a guitar, a scooter, and a bag of poop, I have to help round up this lost dog, who – if it gets too
close to our dog will start a fight – and get it back to the house where it lives.
So the younger child and I manage to succeed in our mission and return this lost dog and get back on our way to school and it’s there that we finally catch up with the older child who’s
gotten bored and cycled ahead. And when we catch up to the older child with me dragging the dog and carrying a PE kit and two book bags and two water bottles and a guitar and a scooter
and a bag of poop… she looks up at me and says, “Ugh! You took your time!”
Suffice to say, it’s a good job I Iove those children.
A year and a half ago I came up with a technique for intercepting the “shuffle” operation
on jigsaw website Jigidi, allowing players to force the pieces to appear in a consecutive “stack” for ludicrously easy solving. I did this
partially because I was annoyed that a collection of geocaches near me used Jigidi puzzles as a barrier to their coordinates1…
but also because I enjoy hacking my way around artificially-imposed constraints on the Web (see, for example, my efforts last week to circumvent region-blocking on radio.garden).
My solver didn’t work for long: code changes at Jigidi’s end first made it harder, then made it impossible, to use the approach I suggested. That’s fine by me – I’d already got what I
wanted – but the comments thread on that post suggests that there’s
a lot of people who wish it still worked!2
And so I ignored the pleas of people who wanted me to re-develop a “Jigidi solver”. Until recently, when I once again needed to solve a jigsaw puzzle in order to find a geocache’s
coordinates.
Making A Jigidi Helper
Rather than interfere with the code provided by Jigidi, I decided to take a more-abstract approach: swapping out the jigsaw’s image for one that would be easier.
This approach benefits from (a) having multiple mechanisms of application: query interception, DNS hijacking, etc., meaning that if one stops working then another one can be easily
rolled-out, and (b) not relying so-heavily on the structure of Jigidi’s code (and therefore not being likely to “break” as a result of future upgrades to Jigidi’s platform).
It’s not as powerful as my previous technique – more a “helper” than a “solver” – but it’s good enough to shave at least half the time off that I’d otherwise spend solving a Jigidi
jigsaw, which means I get to spend more time out in the rain looking for lost tupperware. (If only geocaching were even the weirdest of my hobbies…)
How To Use The Jigidi Helper
To do this yourself and simplify your efforts to solve those annoying “all one colour” or otherwise super-frustrating jigsaw puzzles, here’s what you do:
Visit a Jigidi jigsaw. Do not be logged-in to a Jigidi account.
Open your browser’s debug tools (usually F12). In the Console tab, paste it and press enter. You can close your debug tools again (F12) if you like.
Press Jigidi’s “restart” button, next to the timer. The jigsaw will restart, but the picture will be replaced with one that’s easier-to-solve than most, as described below.
Once you solve the jigsaw, the image will revert to normal (turn your screen around and show off your success to a friend!).
What makes it easier to solve?
The replacement image has the following characteristics that make it easier to solve than it might otherwise be:
Every piece has written on it the row and column it belongs in.
Every “column” is striped in a different colour.
Striped “bands” run along entire rows and columns.
To solve the jigsaw, start by grouping colours together, then start combining those that belong in the same column (based on the second digit on the piece). Join whole or partial
columns together as you go.
I’ve been using this technique or related ones for over six months now and no code changes on Jigidi’s side have impacted upon it at all, so it’s probably got better longevity than the
previous approach. I’m not entirely happy with it, and you might not be either, so feel free to fork my code and improve it: the legiblity of the numbers is sometimes suboptimal, and
the colour banding repeats on larger jigsaws which I’d rather avoid. There’s probably also potential to improve colour-recognition by making the colour bands span the gaps
between rows or columns of pieces, too, but more experiments are needed and, frankly, I’m not the right person for the job. For the second time, I’m going to abandon a tool
that streamlines Jigidi solving because I’ve already gotten what I needed out of it, and I’ll leave it up to you if you want to come up with an improvement and share it with the
community.
Footnotes
1 As I’ve mentioned before, and still nobody believes me: I’m not a fan of jigsaws! If you
enjoy them, that’s great: grab a bucket of popcorn and a jigsaw and go wild… but don’t feel compelled to share either with me.
2 The comments also include asuper-helpful person called Rich who’s been manually
solving people’s puzzles for them, and somebody called Perdita
who “could be my grandmother” (except: no) with whom I enjoyed a
conversation on- and off-line about the ethics of my technique. It’s one of the most-popular comment threads my blog has ever seen.
This was a delightful vlog. It really adds personality to what might otherwise have been a story only about technology and history.
I subscribed to Codex’s vlog like… four years ago? He went dark soon afterwards, but thanks to the magic of RSS, I got
notified as soon as he came back from his hiatus.
The week before last I had the opportunity to deliver a “flash talk” of up to 4 minutes duration at a work meetup
in Vienna, Austria. I opted to present a summary of what I’ve learned while adding support for Finger and Gopher protocols to the WordPress installation that powers DanQ.me (I also hinted at the fact that I already added Gemini and Spring ’83 support, and I’m looking at
other protocols). If you’d like to see how it went, you can watch my flash talk here or on
YouTube.
If you love the idea of working from wherever-you-are but ocassionally meeting your colleagues in person for fabulous in-person events with (now optional) flash talks like this, you
might like to look at Automattic’s recruitment pages…
The presentation is a shortened, Automattic-centric version of a talk I’ll be delivering tomorrow at Oxford Geek Nights #53; so if
you’d like to see it in-person and talk protocols with me over a beer, you should come along! There’ll probably be blog posts to follow with a more-detailed look at the how-and-why of
using WordPress as a CMS not only for the Web but for a variety of zany, clever, retro, and retro-inspired protocols down the
line, so perhaps consider the video above a “teaser”, I guess?
I bundled the dog into the car and drove out to Piddington, a couple of kilometres North of the hashpoint. Cherwell Council advertise a circular walk
that seems to circle from the village (which looked like a good place to park) up to Muswell Hill, the summit of which is near the hashpoint.
She and I walked through Piddington, past the church, and up onto the path. A soggy kilometre or so later we quickly discovered that this was going to be more-challenging than I’d
anticipated. We quickly got bogged down in a flooded field and needed to double-back. With my socks already soaking wet and the dog in a similar condition, we found a different route
that looped around the entire hill and through an alpaca farm (or were they llamas?), then we worked our way up the South face of the hill, over the summit, and down to the hashpoint.
We got there at 11:00 UTC, took a quick look around and pulled the closest thing a dog can manage to a silly grin, and then hacked our way back (by road) to Piddington for the drive
home and some dry clothes.
I hope to cycle/walk to the GZ about lunchtime? I’ve an opportunity to pass nearby the GZ between other errands this morning!
Expedition
I was excited to see this spot pop up on my radar, because it’s a lovely meadow that I’ve ocassionally walked my dog in, within comfortable cycling distance of my house. As it happened,
I had an even easier route here because a drive this morning to drop the kids off at a half-term activity took me “close enough” to be worth stopping and walking from there.
I parked at The Talbot Inn, just West of the Swinford Toll Bridge (a bizzare old bridge that, for weird historical reasons, continues to use human operators
to charge 5 pence per car to cross, which surely cannot be cost-effective!). From here, there’s a footpath along the back of the Seimens buildings in the nearby light industrial estate
which eventually comes out into the Wharf Stream Way circular walk. It was pretty damp out here today and I quickly regretted my choice of light trousers which would have been fine to
drive the kids to their camp and back but wasn’t really a good choice for stomping across the long grass of a damp meadow. Some way across I disturbed some grazing deer, but ultimatey
it was following a deer-trodden trail that eventually provided the best route to the GZ.
I reached the GZ at 09:19, took a selfie, and then turned around to go and get to work. I also shot a video covering the whole expedition which is presented, unedited, below.
Tracklog
My GPSr kept a tracklog; note that this was an “on the way” stopoff so the start and end point isn’t the same!
This post is also available as an article. So if you'd rather read a conventional
blog post of this content, you can!
This video accompanies a blog post of the same title. The content is basically the same – if you prefer videos, watch this video. If you prefer blog posts, go
read the blog post.
After talking about impulse control, our “puppy school” OABT
half-jokingly issued homework to photograph our dogs waiting patiently next to their initial, written in treats. #holdmybeer