Search code examples
ffmpeggopro

ffmpeg output file smaller than input file


I am using ffmpeg to rotate videos 90 or 180 degrees in a Python script. It works great. But, I am curious as to why the output file would be a smaller amount of bytes than the input file.

Here are the commands I use:

180 degrees:

ffmpeg -i ./input.mp4 -preset veryslow -vf "transpose=2,transpose=2,format=yuv420p" -metadata:s:v rotate=0 -codec:v libx264 -codec:a copy ./output.mp4

90 degrees:

ffmpeg -i ./input.mp4 -vf "transpose=2" ./output.mp4

For example, a GoPro Hero 3 MP4 file was originally 2.0 GB. The resulting output file was 480.9 MB. Another GoPro file was 2.0 and its resulting file was 671.5 MB. Is this maybe because the GoPro files were 2.0 but contains empty space, sort of like how some NTFS filesystems make a minimal 4k file, even when there is less bytes in it?

If this isn't the GoPro Hero 3, how do I rotate the files 90 or 180 degrees but ensure the output file size is the same? Or, is data loss expected? Does the data loss have to do with the format?

Note that the quality of the video doesn't appear to be damaged, which is good. So, I am interested in learning more about why this is happening, then I can read the section of ffmpeg documentation that is relevant to this.

Thank you!


Solution

  • Bitrate is ignored from the start

    ffmpeg fully decodes the input into uncompressed raw video and audio (except when stream copying – more about that below). The input format or bitrate does not matter: it does this for all formats. The encoder then works from these raw, decoded frames. See diagram.

    H.264 vs H.264

    Your input and output are both H.264. A format, such as H.264, is created by an encoder. Anyone can make an encoder. However, not all encoders are equal. Given the same input, the output from one H.264 encoder may have the same quality as an output from another H.264 encoder, but the bitrate may be several times smaller.

    The GoPro H.264 encoder was made to work on a platform with limited hardware. That means bitrate (file size) is sacrificed for speed and quality. x264 is the ultimate H.264 encoder: nothing can beat its quality-to-bitrate ratio.

    Rotate without re-encoding

    You can stream copy (re-mux) and rotate at the same time. The rotation is handled by the metadata/sidedata:

    ffmpeg -i input.mp4 -metadata:s:v rotate=90 -c copy output.mp4
    

    Downside is your player/device may ignore the rotation, so you may have to physically rotate with filters which requires re-encoding, and therefore stream copy can't be used.