Search code examples
pythonopencvffmpegpython-imaging-librarymoviepy

How do I resize my video? in proportion (python)


*I am sorry for my poor English. It's a translator.

I used Python moviepy to resize it, but the pixels are broken. I want to make the video 9:16 ratio while maintaining the original image quality. (So that there are black frames on both sides)

from moviepy.editor import *
c = VideoFileClip('test.mp4')
f = c.resize(newsize=(1080,1920))
f.write_videofile('aa.mp4')

This code causes pixels to collapse.

Let me show you an example picture.

Original Video Example

The video I want

Pictures that come out using movie resize (other example pictures, pixels collapse and proportions collapse) Pictures that I don't want

It doesn't have to be moviepy, so I'd appreciate it if you could tell me how to use Python. (PIL? opencv?)

Thank you so much. Have a nice day 🙏


Solution

  • In FFmpeg, you need to scale then pad your frames. You can achieve this by running your frames through scale then pad filters. You can find the filter documentation here.

    Assuming your input is taller than 16:9. The command you need is:

    ffmpeg -i test.mp4 -vf 
        scale=-1:1080,pad=w=1920:x=(ow-iw)/2 aa.mp4
    

    Assuming you have ffmpeg binary on the system path, you can run this command from Python by

    import subprocess as sp
    
    cmd = ['ffmpeg','-i','test.mp4','-vf','scale=-1:1080,pad=w=1920:x=(ow-iw)/2','aa.mp4']
    sp.run(cmd)
    

    If you want something simpler, you can try my ffmpegio package which you can install by

    pip ffmpegio-core
    

    then in Python

    import ffmpegio
    
    ffmpegio.transcode('test.mp4','aa.mp4',vf='scale=-1:1080,pad=w=1920:x=(ow-iw)/2')
    

    If you need higher quality mp4, you can add crf=xx argument. (The wiki says crf ~18 yields no loss of perceptual quality.)

    You can add any ffmpeg output/global options as an argument. If you need to add an input argument, modify the input name by appending _in. For example, say to get a clip from at 10 s to 20 s, you can add ss_in=10, to_in=20.