Lately I’ve noticed a lot of similar YouTube channels popping up in my feed. I could go at length trying to describe this format to you or just give you an example. I think the latter would be easiest:

That video specifically has 19k views at the time of writing this. And there’s more like it, just type “Reddit” into the YouTube search bar:

Every single one of these videos, literally all of them, are of almost the exact same format. It looks something like this:

  • The video title is usually of the form: <channel name/series name>
  • The thumbnail includes the subreddit icon along with the name of the subreddit.
  • Sometimes the awards for the post are shown next to the subreddit name in the thumbnail.
  • In the thumbnail, the title of the thread takes up the entire vertical and about 2/3 of the horizontal space. The text usually has different highlighting methods to make certain words stand out. (The green text in the example video).
  • An image related to the name of the post is on the right-hand side of the thread title.
  • Each video has a TTS engine reads out the text of the tread title/comment.
  • While the text is being read, the text of the comment is incrementally revealed, usually one sentence at a time. Sort of like when you read with your finger except the video does it for you.
  • A transition is added between each comment. Usually some sort of TV static.
  • Intros/Outros are sometimes added.
  • Sometimes background music is added.

None of those steps exercise any use of creativity. That makes it the perfect process to automate.

I decided that Java/Spring would be a great combo for this project. So expect lots of Java from here on out.

Here was my original plan:

  1. Scrape Reddit for the top posts of the day.
  2. Use some library to take images of the text sentence by sentence.
  3. Generate TTS for those comments.
  4. Drop the images and TTS into some timeline-based rendering API
  5. Spit out a video
  6. Profit?

Scraping Reddit

This is straight forward. Reddit offers a public API.

All that has to be done is to call https://reddit.com/r/<subreddit>/top.json and you get all the top threads for a subreddit. My target for this project is /r/AskReddit.

Then once you have a threadId just call https://reddit.com/comments/<thread id>/top.json to get the top comments.

That’s it.

Generating Images

Scraping Reddit wasn’t so bad, no way images could be that hard… WRONG!!! I would estimate that around 50–70% of the time spent working on this project went towards image generation. I wouldn’t have thought it, but it appears to be uncommon to want to render HTML to pictures.

The first part of the generation is straightforward. The text of the comment has to be broken up into sentences and each sentence needs its own image. Then the images can be strung together to make something like this:

I had many ideas on how to go about this:

  • Draw the text/image using java.awt.Graphics.
  • Render locally generated HTML snippets.
  • Take a screenshot from Reddit.com and add the text in part-by-part.

As an exercise to the reader, try to guess which methods worked and which didn’t. I tried all of them and only one kind of worked.

Method 1: java.awt.Graphics

How patient are you? Chances are, you do not have the patience required to implement this. Drawing such a simple image is a burden in awt. Even just drawing text that doesn’t look horrible requires the follow blob of code:

// Load the font
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
Font font = Font.createFont(Font.TRUETYPE_FONT, fontFile);
ge.registerFont(font);

// Turn on text anti-aliasing
graphics.setRenderingHint(
        RenderingHints.KEY_TEXT_ANTIALIASING,
        RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
graphics.setRenderingHint(
        RenderingHints.KEY_FRACTIONALMETRICS,
        RenderingHints.VALUE_FRACTIONALMETRICS_ON);

// Set the font size
Font newFont = font.deriveFont(font.getStyle(), fontSize);
graphics.setFont(newFont);

// Draw the string at x,y
graphics.drawString(text, x, y +g.getFontMetrics().

getAscent());

And that was just to draw a single string. Yeah, AWT is tedious. I don’t have the patience to redo HTML in awt so on to the next idea.

Method 2: Rendering HTML locally

This was actually the first method I tried because it looks straight forward. You extract the styled HTML from Reddit, add in some placeholders, and render it.

Extracting the HTML is made straightforward by some amazing tools: