Skip to main content
  1. Blog/

How to generate a video for Threads with ffmpeg

·2 mins

Today I wanted to generate a small teaser of an AI generated song I produced for a D&D campaign in order to share it on Threads. Sounds like an easy task but I had to overcome some limitation:
while from its mobile app you can send voice notes, Threads doesn’t allow for standard audio files like an mp3, so I had to generate a video.

I quickly hacked together this command that given the audio file an image, it uses them to produce a video with the image in loop.

Warning! The next command is not the correct one, if you are in a hurry jump straight to the end of the article.
ffmpeg -loop 1 -i sollevamento_nanico.webp -i sollevamento_nanico-teaser.mp3 -shortest sollevamento_nanico-teaser.mp4

The generated file had this spec:

Output #0, mp4, to 'sollevamento_nanico-teaser.mp4':
  Metadata:
    encoder         : Lavf60.16.100
  Stream #0:0: Video: mpeg4 (mp4v / 0x7634706D), yuv420p(tv, bt470bg/unknown/unknown, progressive), 1024x1024, q=2-31, 200 kb/s, 25 fps, 12800 tbn
    Metadata:
      encoder         : Lavc60.31.102 mpeg4
    Side data:
      cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: N/A
  Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s

Unlucky for me Threads can’t reproduce it, so I digged a bit into the API documentation and I gathered more information:

Video Specifications
    Container: MOV or MP4 (MPEG-4 Part 14), no edit lists, moov atom at the front of the file.
    Audio Codec: AAC, 48khz sample rate maximum, 1 or 2 channels (mono or stereo).
    Video Codec: HEVC or H264, progressive scan, closed GOP, 4:2:0 chroma subsampling.
    Frame Rate: 23-60 FPS
    Picture Size:
        Maximum Columns (horizontal pixels): 1920
        Required aspect ratio is between 0.01:1 and 10:1 but we recommend 9:16 to avoid cropping or blank space.
    Video Bitrate: VBR, 25 Mbps maximum.
    Audio Bitrate: 128 kbps.
    Duration: 300 seconds (5 minutes) maximum, minimum longer than 0 seconds.
    File Size: 1 GB maximum.

Bingo! My file had two issues:

  • wrong video codec
  • moov atom not at the beginning of the file

Fixing it is a straightforward task in ffmpeg:

ffmpeg -loop 1 -i sollevamento_nanico.webp -i sollevamento_nanico-teaser.mp3 -shortest -c:v libopenh264 -movflags faststart sollevamento_nanico-teaser.mp4

Notice that I used libopenh264 instead of libx264 since the latter is not available on Fedora due to patent issues; nothing prevents you from installing it, but for a 10 second video it doesn’t make any difference.

This was a very quick and dirty solution, I hope it will be useful to someone.

Comments are open if you need some help or want to discuss.

HyperTesto
Author
HyperTesto
Hey, i’m the same guy from the homepage. Incredible, isn’t it?