Wishful Coding

Didn't you ever wish your
computer understood you?

All studl.es Lego Mindstorms building instructions added to this blog

The downside of having Spanish domain is that you get Spanish email about them. Somehow an email slipped through, which meant that studl.es suddenly got canceled.

I decided to merge studl.es into this blog, so that all the building instructions and videos I made will remain available. There are probably some broken links and images in there, sorry about that.

A complete list of all the articles is available here, and all the ones that have building instructions are available here.

Published on

Make all the Star Wars memes

Normal people watch movies or play games to relax. Me on the other hand, I write code about movies or games to relax.

I came across some memes that posed the question if every line from the Star Wars prequels is meme material, accompanied by a shot from said prequel with a character confirming said question. Easily nerd-sniped as I am, I thought, surely there are lines in the movie that are completely boring?

I figured it should be doable to extract the subtitles from the movie, and use those to generate every possible Star Wars meme. Well, at least all the ones adhering to the format described above.

Extracting the subtitles and timestamps

It turns out srt subtitles are a pretty easy format to grep, but in case the subtitles are embedded inside the video file, or in some other binary format, ffmpeg got you covered. Once you have the srt file, a simple grep command can be used to extract the timestamps.

Note the extra space and lack of decimal point. I’m lazy, and this seemed the easiest way to get a timestamp that refers to a frame when the subtitle is displayed. This sometimes fails, so a mean between the start and end time is obviously better.

ffmpeg -y -txt_format text -i sw.mkv out.srt;
timestamps=$(grep -oE " [0-9]{2}:[0-9]{2}:[0-9]{2}" out.srt);

Generating images for every subtitle line

Again, ffmpeg can do the job, but it requires a bit more than a straight copy-paste from the manual. Let’s go over the options after the full command, that I run inside a for loop.

ffmpeg -y -ss $ts -copyts -i sw.mkv -vf subtitles=sw.mkv -frames:v 1 frames/out$i.jpg;
  • -y answer yes to all prompts.
  • -ss timestamp seek to the specified timestamp. It is important this comes before the input file, otherwise it’ll render the whole movie up to that point. However, doing so changes the timestamps, which we need for the subtitles.
  • -copyts preserve the timestamp. This was a life-saver, thanks to the ffmpeg IRC channel.
  • -i the input file…
  • -vf subtitles=file specifies a filter that “burns” the subtitle into the movie.
  • -frames:v 1 save a single frame to the specified output file

Add the meme caption

With the hard part behind us, now we’re back to straight copy-pasting from the ImageMagick manual. The only interesting bit I added is the pointsize.

convert frames/out$i.jpg -background White -pointsize 32 label:'Insert funny caption' +swap  -gravity Center -append memes/meme$i.jpg;

Putting it all together

The whole script can be found here. I did not expect much, but it was already at frame 6 that I was pleasantly surprised.

Yes, of course

But then I thought

Surely you can do better

So I created a Twitter bot and a search page.

The Twitter bot is just an IFTTT applet that posts an image, served up by a mind-numbingly simple PHP script that I copied from somewhere.

For the search script, I wrote a little Python script that converts the srt file to a csv file that I can import into a MySQL database, which I then query using SELECT * FROM subtitles WHERE MATCH(sub) AGAINST ('words').

That’s all for now.

May the force be with you

Generate Cities: Skylines height maps

Over the Christmas holiday I played a bit of Cities: Skylines. I wondered if it would be possible to import a real-world location from Google Maps or Open Street Map or something. I quickly found terrain.party, and downloaded a couple of locations.

I found some videos of people building polders, so I thought it’d be fun to import a real Dutch polder to play on. But to my disappointment, the height map from terrain.party was quite bad around the coastlines and did not seem to deal well with land below the sea level.

However, the readme on the files explained the data sources and the file format used by Cities: Skylines. So it seemed pretty easy to write a simple script to generate my own tiles. Nothing is ever as easy as it seems, but a week later, I have a somewhat working script that generates playable maps that look nicer than terrain.party.

comparison

My script is based on exactly the same SRTM3 data als used by terrain.party (amongst other sources), but produces much nicer shorelines as well as smoothing the raw data to avoid that pixelated look. There are also a lot of other parameters to tweak.

After some searching, I found the Mapzen’s S3 bucket which offers easy access to the void-filled, 30m resolution SRTM3. But the real key to smooth shorelines is the SRTM Water Body Data, which I used to mask out the water with a negative altitude. As a finishing touch I applied a light Gaussian blur to the upscaled data to remove the hard edges.

Download the script here

Initially I developed the script under Linux, but switching to Windows for testing with the actual game was surprisingly painless, once I installed Anaconda. Anaconda takes care of compiling all the annoying C extensions, which is a huge relief. I highly recommend it.

For my personal use, some parameters and assumptions were just hardcoded, but I’ve since added a simple command-line interface so you can adjust the size of the map, how much blur is applied, height scale and offset, and disable shoreline fixes.

Published on