16

I tried to upload a video file (mp4) to Twitter but the site complained it couldn't be uploaded. It seems Twitter has some conditions in order to allow a video upload:

File Type: MP4 or MOV
Max Time: 2 minutes and 20 seconds
Minimum Resolution: 32 x 32
Maximum Resolution: 1920 x 1200
Aspect Ratios: 1:2.39 - 2.39:1 range (inclusive)
Maximum Frame rate: 40 fps
Maximum Video Bitrate: 25 Mbps

And here you are the general infos about the video I was trying to upload but Twitter kept saying there was a problem while processing it (the infos I got through mediainfo):

General
Complete name                            : tmp03.mp4
Format                                   : MPEG-4
Format profile                           : Base Media
Codec ID                                 : isom (isom/iso2/mp41)
File size                                : 6.71 MiB
Duration                                 : 2mn 15s
Overall bit rate mode                    : Constant
Overall bit rate                         : 417 Kbps
Encoded date                             : UTC 1904-01-01 00:00:00
Tagged date                              : UTC 1904-01-01 00:00:00
Writing application                      : Lavf58.29.100

Video
ID                                       : 1
Format                                   : MPEG-4 Visual
Format profile                           : Simple@L1
Format settings, BVOP                    : No
Format settings, QPel                    : No
Format settings, GMC                     : No warppoints
Format settings, Matrix                  : Default (H.263)
Codec ID                                 : 20
Duration                                 : 2mn 15s
Bit rate mode                            : Constant
Bit rate                                 : 281 Kbps
Width                                    : 720 pixels
Height                                   : 405 pixels
Display aspect ratio                     : 16:9
Frame rate mode                          : Constant
Frame rate                               : 29.970 (30000/1001) fps
Color space                              : YUV
Chroma subsampling                       : 4:2:0
Bit depth                                : 8 bits
Scan type                                : Progressive
Compression mode                         : Lossy
Bits/(Pixel*Frame)                       : 0.032
Stream size                              : 4.52 MiB (67%)
Writing library                          : Lavc58.54.100
Encoded date                             : UTC 1904-01-01 00:00:00
Tagged date                              : UTC 1904-01-01 00:00:00

Audio
ID                                       : 2
Format                                   : AAC
Format/Info                              : Advanced Audio Codec
Format profile                           : LC
Codec ID                                 : 40
Duration                                 : 2mn 15s
Duration_LastFrame                       : -19ms
Bit rate mode                            : Constant
Bit rate                                 : 129 Kbps
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Sampling rate                            : 48.0 KHz
Frame rate                               : 46.875 fps (1024 spf)
Compression mode                         : Lossy
Stream size                              : 2.07 MiB (31%)
Default                                  : Yes
Alternate group                          : 1
Encoded date                             : UTC 1904-01-01 00:00:00
Tagged date                              : UTC 1904-01-01 00:00:00

Can you tell me what's wrong with the video file??

Best regards!

8 Answers 8

29

Twitter does not accept MPEG-4 Part 2 video. This is an old video format. Re-encode to H.264:

ffmpeg -i input.mp4 -c:v libx264 -crf 20 -preset slow -vf format=yuv420p -c:a aac -movflags +faststart output.mp4
  • If you get not divisible by 2 error see this answer.
  • If your input contains AAC audio you can stream copy instead of re-encoding by changing -c:a aac to -c:a copy to preserve the audio quality.
option explanation
-c:v libx264 Chooses video encoder libx264
-crf 20 x264 quality level
-preset slow x264 encoding speed vs compression efficiency preset
-vf format=yuv420p Ensures YUV 4:2:0 chroma subsampling for compatibility
-c:a aac Chooses audio encoder aac
-movflags +faststart Enables fast start: may allow Twitter to begin processing faster
1
  • Thank you for your answer! Even though it didn't solve my problem, it led me to a solution. I installed ffmpeg from source and I didn't compile it using all the flags ffmpeg needs to properly convert/manipulate media files. I followed the official ffmpeg installation guide (trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu) and now the problem is solved! Thank you for your kindness in helping me! Commented Nov 27, 2019 at 19:03
7

I tried all the commands from the other answers and non of them worked for me. So, I decided to do my own version:

ffmpeg -i input.mov \
 -vcodec libx264 -pix_fmt yuv420p -strict experimental \
 -r 30 -t 2:20 \
 -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" -vb 1024k \
 -acodec aac -ar 44100 -ac 2\
 -minrate 1024k -maxrate 1024k -bufsize 1024k \
 -movflags +faststart \
 output.mp4
  • If your input contains AAC audio you can stream copy instead of re-encoding by changing -acodec aac -ar 44100 -ac 2 to -acodec copy to preserve the audio quality.
option explanation
-vcodec libx264 Chooses video encoder libx264
-pix_fmt yuv420p Ensures YUV 4:2:0 chroma subsampling for compatibility
-strict experimental allows non standardized experimental things, experimental (unfinished/work in progress/not well tested) decoders and encoders
-r 30 sets the frame rate of the output file to 30 fps
-t 2:20 sets the duration to 2:20 mins. after that it will stop writing the output
-vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" If you get not divisible by 2 error see
-acodec aac Chooses audio encoder aac
-minrate 1024k set min bitrate tolerance to 1024k (in bits/s). It is of little use elsewise
-maxrate 1024k set max bitrate tolerance to 1024k (in bits/s). Requires bufsize to be set
-bufsize 1024k set rate-control buffer size to 1024k (in bits)
-movflags +faststart enables fast start for streaming
1
3

Biggest problem is likely the odd number height. They will convert it to H264 and it needs to be even.

That file is not the preferred format, H264 High Profile, which may be another issue.

2

I was struggling with posting to Twitter video found on Facebook. For me this one worked:

ffmpeg -i video.mov -r 30 -c:v libx264 -b:v 1M -vf scale=640:-1 video.mp4

Found here.

2

None of the given answers worked for my video, which had a very wide aspect ratio, which it seems twitter doesn't like.

So I combined @Teocci's answer with some advanced video filter that will rescale the video to 1280x720 while keeping the aspect ratio, and then pad it symmetrically to reach exactly 1280x720px. This video worked, here's the full command:

ffmpeg -i input.mp4 \
-vcodec libx264 -pix_fmt yuv420p -strict experimental \
-r 30 -t 2:20 \
-vf "scale=w=1280:h=720:force_original_aspect_ratio=1,pad=1280:720:(ow-iw)/2:(oh-ih)/2" -vb 1024k \
-acodec aac -ar 44100 -ac 2 \
-minrate 1024k -maxrate 1024k -bufsize 1024k \
-movflags +faststart \
output.mp4
1

pix_fmt yuv420p is the only missing required option for mp4 as of FFmpeg 6.0

This was mentioned at https://stackoverflow.com/a/69438596/895245 but I wanted to provide a minimal precise synthetic example.

Uploading the following 0-2 counter works as of January 2024:

ffmpeg -y -lavfi "
color=white:480x480:d=3,
format=rgb24,
drawtext=
  fontcolor=black:
  fontsize=600:
  text='%{eif\:t\:d}':
  x=(w-text_w)/2:
  y=(h-text_h)/2[v];
" -map '[v]' \
-pix_fmt yuv420p \
out.mp4

and if we remove -pix_fmt yuv420p it upload fails because the default format is yuv444p which is not accepted by Twitter.

This is the diff of ffprobe between the two versions:

-  Stream #0:0[0x1](und): Video: h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuv444p(progressive), 480x480 [SAR 1:1 DAR 1:1], 32 kb/s, 25 fps, 25 tbr, 12800 tbn (default)
+  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 480x480 [SAR 1:1 DAR 1:1], 31 kb/s, 25 fps, 25 tbr, 12800 tbn (default)

Tested on FFmpeg 6.0, Ubuntu 23.10.

Official Twitter API documentation

This useful post: https://gehrcke.de/2021/10/twitters-h-264-video-requirements/ pointed me to the official API docs: https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/uploading-media/media-best-practices (archive) which actually document the yuv422 restriction and a few others (highlight mine):

  • Frame rate must be 60 FPS or less
  • Dimensions must be between 32x32 and 1280x1024
  • File size must not exceed 512 mb
  • Duration must be between 0.5 seconds and 140 seconds
  • Aspect ratio must be between 1:3 and 3:1
  • Must have 1:1 pixel aspect ratio
  • Only YUV 4:2:0 pixel format is supported
  • Audio must be AAC with Low Complexity profile. High-Efficiency AAC is not supported
  • Audio must be mono or stereo, not 5.1 or greater
  • Must not have open GOP
  • Must use progressive scan
0

I had this uploading problem but the cause was different. In my case it was because the CTTS was invalid even though the file played fine locally. You can check for errors in the file with ffprobe media_file.mp4

0

In my case, I was missing this option: -pix_fmt yuv420p.

There are more ideas at https://twittercommunity.com/t/ffmpeg-mp4-upload-to-twitter-unsupported-error/68602 and I think you might be able to see a more specific error if you inspect the JSON response.

Not the answer you're looking for? Browse other questions tagged or ask your own question.