Go to Home
JavaScriptAPIsPuppeteerAWSFFmpeg

Automated TikTok Generator

Automatically generating reddit story TikToks that have become so popular. The app uses the reddit API to get popular posts, puppeteer to screenshot them, AWS Polly to create a TTS voiceover, YouTube API to find background footage, and YTDL-P to download the footage. All these components are edited together using FFmpeg


Who would watch these?

That's the question my mom asked me when I showed her the first video I generated. At the time of making this app, I was seeing a lot of the same type of video on my feed.

These videos are usually a screenshot of a reddit post, with a voiceover of the post being read out loud. The screenshot is overlayed on a muted background video that's unrelated to the main content. It's a formula that works, and I wanted to see if I could automate it.

Getting Screenshots

Reddit API

The first component of this project is getting screenshots of the reddit posts. Before you can start screenshotting though, you'll need to find relevant posts to use. I used the reddit API to get the top posts on a given time frame (day/week/month) from a target subreddit.

const response = await fetch(endpoint)
const data = await response.json()
const topPosts = data.data.children.map((post) => post.data)

const postPromises = topPosts.map(async (post) => {
    const commentsEndpoint = `https://www.reddit.com/r/${subreddit}/comments/${post.id}.json`
    const commentsResponse = await fetch(commentsEndpoint)
    const commentsData = await commentsResponse.json()
    const comments = commentsData[1].data.children.map((comment) => comment.data)
    return { post, comments }
})

const results = await Promise.all(postPromises)

This will give you an array of posts, each with an array of comments. Then, it's just a matter of picking a post. I chose to pick the first post every time, but you could easily randomize this.

const targetURL = `https://www.reddit.com${results[0].post.permalink}`
const targetComment1 = `https://www.reddit.com${results[0].comments[0].permalink}`
const targetComment2 = `https://www.reddit.com${results[0].comments[1].permalink}`
const targetComment3 = `https://www.reddit.com${results[0].comments[2].permalink}`

Puppeteer

To screenshot the posts, I used Puppeteer, a headless browser that can be controlled with JavaScript.
Reddit has a couple pop-ups (like asking to download the mobile app) that needed to be removed every time I used Puppeteer.

const ad = document.getElementsByTagName("shreddit-comments-page-ad")
if (ad.length) {
    console.log("Removing shreddit-comments-page-ad elements")
    for (const blocker of ad) {
        blocker.remove()
    }
}

You can find troublesome elements by running Puppeteer in non-headless mode. Once you have the tag for the element it's easy to find and remove. Once the ads are gone, Puppeteer searches for the comment/post element in the DOM and adjusts the screenshot to its dimensions.

before
after

Creating the Voiceover

AWS Polly

Now that we have the screenshot, we can create the voiceover from the text content of the Reddit post. This text is from the initial Reddit API call, not the screenshot. I used AWS Polly, Amazon's text-to-speech API to generate audio files for the text.

polly.synthesizeSpeech(params, (err, data) => {
    if (err) {
        console.error(err)
    } else {
        // write the TTS audio stream to a file
        fs.writeFileSync(`tts-${i}.mp3`, data.AudioStream, "binary")
        console.log(`TTS audio file written to tts-${i}.mp3`)
    }
})

Finding Background Footage

YouTube API

Now that we have the screenshot and the voiceover, we need to find some background footage. I found that shorter videos were usually better because they had less filler content. The YouTube API returned hyperlinks which I could use the ytdl-exec library to download content from.

youtubedl(`https://www.youtube.com/watch?v=${encodeURIComponent(videoId)}`, {
    noCheckCertificates: true,
    noWarnings: true,
    preferFreeFormats: true,
    addHeader: ["referer:youtube.com", "user-agent:googlebot"],
})

Bringing it all Together

FFmpeg

FFmpeg is a popular command line tool for editing videos. I used a FFmpeg wrapper called fluent-ffmpeg to edit my videos directly in JavaScript. I use it by defining a series of objects that are later converted to one large command. The entire buffer includes over 20 objects (commands), but this is what one looks like:

// mute the background footage
{
    filter: 'volume',
    options: {
        volume: 0
    },
    inputs: '0:a',
    outputs: 'muted'
}

And just like that, we have a video that can be posted on TikTok or any other short-form video platform!


Flycatcher - Waitlist Builder
TypeScriptNextJSTailwindCSSMongoDBUploadThingSupabaseStripeMailgun

Flycatcher - Waitlist Builder

Build your custom branded waitlist, collect insights about your subscribers, and send email campaign...

TOS Chat - Custom AI Chatbot
TypeScriptNextJSTailwindCSSPineconeLangChainMongoDB

TOS Chat - Custom AI Chatbot

Custom GPT chatbot that allows the user to 'chat' with terms of service and privacy policy agreement...

All Posts