Skip to content

Instantly share code, notes, and snippets.

@brianloveswords
Last active December 1, 2023 14:58
Show Gist options
  • Save brianloveswords/7534169715b5750a892cddcf54c2aa0e to your computer and use it in GitHub Desktop.
Save brianloveswords/7534169715b5750a892cddcf54c2aa0e to your computer and use it in GitHub Desktop.

gif-from-tweet

There are so many great GIFs out there and I want to have copies of them. Twitter makes that harder than it should be by converting them to MP4 and not providing access to the source material. To make it easier, I made a bash pipeline that takes a tweet URL and a filename, extracts the MP4 from that tweet and uses ffmpeg to convert back to GIF.

Dependencies

  • ffmpeg
    • macOS: brew install ffmpeg
    • Ubuntu/Debian: apt install ffmpeg

Install

Stick this in your ~/.profile:

video-url-from-tweet() {
    if [ "$1" ]; then
        url=$1
    else
        echo "Must provide a url"
        return 1
    fi

    curl --silent $url |\
        # should find the <meta> tag with content="<thumbnail url>"
        (grep -m1 "tweet_video_thumb" ||\
          echo "Could not find video" && return 1) |\

        # from: <meta property="og:image" content="https://pbs.twimg.com/tweet_video_thumb/xxxxxxxxxx.jpg">
        # to: https://pbs.twimg.com/tweet_video_thumb/xxxxxxxxxx.jpg
        cut -d '"' -f 4 |\

        # from: https://pbs.twimg.com/tweet_video_thumb/xxxxxxxxxx.jpg
        # to: https://video.twimg.com/tweet_video/xxxxxxxxxx.mp4
        sed 's/.jpg/.mp4/g' |\
        sed 's/pbs.twimg.com\/tweet_video_thumb/video.twimg.com\/tweet_video/g'
}
video-from-tweet() {
    if [ "$1" ]; then
        url=$1
    else
        echo "Must provide a url"
        return 1
    fi
    curl $(video-url-from-tweet $url)
}
video-to-gif() {
    # derived from https://engineering.giphy.com/how-to-make-gifs-with-ffmpeg/
    if [ "$2" ]; then
        input=$1
        output=$2
    else
        echo "Must provide an input file and output file"
        return 1
    fi

    ffmpeg -i $input \
           -filter_complex "[0:v] split [a][b];[a] palettegen [p];[b][p] paletteuse" \
           -f gif \
           $output
}
gif-from-tweet() {
    if [ "$2" ]; then
        url=$1
        output=$2
    else
        echo "Must provide a url and an output filename"
        return 1
    fi
    video-from-tweet $url | video-to-gif - $output
}

Usage

  • video-url-from-tweet <url>: takes a tweet URL and returns the MP4 embedded in that tweet, or fails if no video is found.
  • video-from-tweet <url>: returns the raw data of the video that is embedded in the tweet
  • video-to-gif <input> <output>: converts a video to a GIF
  • gif-from-tweet <url> <output>: takes a tweet URL and an output filename and saves the MP4 embedded in that tweet as a GIF.

Example

$ video-url-from-tweet https://twitter.com/tsunamino/status/1003318804619804672
https://video.twimg.com/tweet_video/DeyBINOUwAAbuif.mp4

# creates `wink.mp4'
$ video-from-tweet https://twitter.com/tsunamino/status/1003318804619804672 > wink.mp4

# creates `wink.gif' from `wink.mp4'
$ video-to-gif wink.mp4 wink.gif
<...a bunch of ffmpeg output...>

# or use this, which pipelines the above and doesn't create intermediate MP4
$ gif-from-tweet https://twitter.com/tsunamino/status/1003318804619804672 wink.gif
@PacoH
Copy link

PacoH commented Jan 8, 2022

@eugene1g:

Thank you for pointing this out.

@PacoH
Copy link

PacoH commented Jan 8, 2022

@gaving:

Thanks for the excellent script! It works perfectly.

@PacoH
Copy link

PacoH commented Jan 8, 2022

As pointed out by meyerweb, though it was not mentioned why, this must be added to ~/.bash_profile in OS X. That said, it does not work at all.

video-url-from-tweet https://twitter.com/tsunamino/status/1003318804619804672
Could not find video

All other commands fail similarly.

Thank gawd for comments. As eugene1g pointed out, youtube-dl can download the video of the animated GIF.

And as gaving pointed out, you can directly download the video and convert it to animated GIF with his brilliant script added to your profile file:

tweet-to-gif() {
  youtube-dl -o - $1 | ffmpeg -i pipe: \
	-filter_complex "[0:v] split [a][b];[a] palettegen [p];[b][p] paletteuse" \
	-hide_banner -loglevel panic \
	-f gif ${1##*/}.gif
}

Note that both the twitter thread URL and the URL you get from right-clicking the GIF and clicking Copy Gif Address both work.

e.g.,
Thread URL: https://twitter.com/Astropartigirl/status/1479837621337657345
GIF URL: https://twitter.com/i/status/1479837621337657345

I deleted the original script in my ~/.bash_profile and added this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment