Capturing and Posting Video Screenshots at Random Intervals
Tags: python, ffmpeg, twitter
Published: 2021-08-31 05:08:35

---
title: Capturing and Posting Video Screenshots at Random Intervals
published: true
description: 
tags: python, ffmpeg, twitter
cover_image: https://pbs.twimg.com/media/E8-jyzvWQAAq_59?format=jpg&name=900x900
---

I recently created a couple of bot Twitter accounts, [@ScreenshotsVice](twitter.com/screenshotsVice) which shares screencaps from episodes of "Miami Vice" and [@Pasolinibot](twitter.com/pasolinibot) which shares caps from the filmography of Pier Paolo Pasolini, both at regular intervals. 

The way these accounts are managed are that, when a cronjob is triggered, from a video library, a series of screencaptures are dumped (if they were set to refresh on the previous run), and then the listing in the directory is shuffled, and then the script selects one at random and posts it to Twitter. 

Because the intervals are managed by cronjobs, I'll focus on what happens when a job is triggered. 

The Python script that selects and posts the capture relies on the `tweepy` Twitter API client for Python, so you will need your [Twitter Developer API credentials](developers.twitter.com). The script that generates the captures, before running, requires that [`ffmpeg` be installed](https://github.com/jmarhee/screenshot-capture-twitter) and the directory where the video library is stored and the directory where you'll store screencaptures.

To generate the capture library, the following script is used:

```bash
#!/bin/bash

LNVC_DATA_PATH=${SOURCE_DIR}
LNVC_PREV_PATH=${SOURCE_DIR_OUT}-Screens
REFRESH_SCREENS=1
DUMP_INTERVAL=1
DUMP_RANDOM=1
RANDOMIZE_NAMES=1

if [ -z "${LNVC_DATA_PATH}" ]; then
    echo "No source path found. Set LNVC_DATA_PATH." ; exit 1
fi

if [ -z "${LNVC_PREV_PATH}" ]; then
    echo "No target path found. Set LNVC_PREV_PATH." ; exit 1
fi

if [ -n "${REFRESH_SCREENS}" ]; then
    rm -rf $LNVC_PREV_PATH/*
fi
```
This sets up options for things like randomizing filenames, whether or not to refresh the library, defining the video source and the capture outputs, the latter two are the only ones that are required.

After this, the video library is iterated, and the captures created:

```bash
for v in `ls $LNVC_DATA_PATH`; do \
    if [ -n "${DUMP_RANDOM}" ]; then
        LENGTH=$(ffmpeg -i $LNVC_DATA_PATH/$v 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//) ; \
        HOUR=$(echo $((0 + RANDOM % $(echo $LENGTH | cut -d ":" -f 2)))) ; \
        if (( $HOUR < 10 )); then HOUR=$(printf "%02d\n" $HOUR); fi ; \
        MINUTE=$(echo $((1 + RANDOM % $(echo $LENGTH | cut -d ":" -f 2)))) ; \
        if (( $MINUTE < 10 )); then MINUTE=$(printf "%02d\n" $MINUTE); fi ; \
        SECOND=$(echo $((1 + RANDOM % 59))) ; \
        if (( $SECOND < 10 )); then SECOND=$(printf "%02d\n" $SECOND); fi ; \
        ffmpeg -i $LNVC_DATA_PATH/$v -ss $HOUR:$MINUTE:$SECOND.000 -vframes 1 $LNVC_PREV_PATH/`head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo ''`.jpg
    fi

    if [ -n "${DUMP_INTERVAL}" ]; then
        ffmpeg -i $LNVC_DATA_PATH/$v -frames:v 1 -vf fps=1/$DUMP_INTERVAL $LNVC_PREV_PATH/`head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo ''`.jpg
        # The filenames will be prefixed by a random string, but per-video; if you'd like them randomized in totality, set `RANDOMIZE_NAMES`
        if [ -n "${RANDOMIZE_NAMES}" ]; then
            cd $LNVC_PREV_PATH ; \
            for f in `ls`; do mv $f `head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo ''`.jpg; done
        fi
    fi
done
```
If `DUMP_RANDOM` is enabled, random timecodes will be dumped from a video file, `DUMP_INTERVAL` will dump video files into captures at each interval (useful for films, rather than slices from an episode of a TV series). Filenames (which helps when selecting images randomly to post) can be selectively re-randomized. 

This script has dumped videos from `SOURCE_DIR` into `SOURCE_DIR_OUT`, which our poster script will read from.

First, we have to setup the Twitter authentication:

```python
import tweepy
import os, random


def main():

    twitter_auth_keys = {

        "consumer_key"        : os.environ['twitter_consumer_key'],

        "consumer_secret"     : os.environ['twitter_consumer_secret'],

        "access_token"        : os.environ['twitter_access_token'],

        "access_token_secret" : os.environ['twitter_access_token_secret']

    }



    auth = tweepy.OAuthHandler(

            twitter_auth_keys['consumer_key'],

            twitter_auth_keys['consumer_secret']

            )

    auth.set_access_token(

            twitter_auth_keys['access_token'],

            twitter_auth_keys['access_token_secret']

            )

    api = tweepy.API(auth)
```

Then lock in our selected image:

```python
    files = os.listdir(os.environ['SOURCE_DIR_OUT'])
    for i in range(1,10000):
        random.shuffle(files)
    path = os.environ['SOURCE_DIR_OUT'] + "/" + random.choice(files)
    media = api.media_upload(path)
```

you'll see above that it reads the captures into a list of filenames, then shuffles the list, before selecting one at random, then we post:

```python
    tweet = "#pasolini"

    post_result = api.update_status(status=tweet, media_ids=[media.media_id])



if __name__ == "__main__":

    main()
```

The package can be found on [Github](https://github.com/jmarhee/screenshot-capture-twitter) along with some additional examples (one using a Kubernetes CronJob resource, for example) for use.