Kataklycm
Kataklycm

Reputation: 21

FFmpeg cropping: 'Invalid too big or non positive size for width '2304' or height '4096'

I'm trying to crop video to format 1080:1920, it works with most videos but sometimes it fails with an error like:

Invalid too big or non positive size for width '2304' or height '4096'

Here is the code I am using:

import ffmpy

ffmpy.FFmpeg(inputs={"input.mp4": None}, outputs={"output.mp4": ["-y", "-vf", "crop=ih*(9/16):ih,scale=1080:1920", "-preset", "ultrafast"]})`

Upvotes: 2

Views: 3497

Answers (1)

Rotem
Rotem

Reputation: 32144

The reason for the error is that ih*(9/16) > frame_width.

We can't crop a rectangle that exceeds the boundaries of the frame.

For example:
Assume the resolution of input.mp4 is 100x200 (100 is the width).
ih = 200
ih*(9/16) = 112.5
We can't crop 112x200 pixels because the frame width is only 100 pixels...


For reproducing the issue, we may create synthetic video using FFmpeg (command line tool):

ffmpeg -y -f lavfi -i testsrc=size=100x200:rate=1:duration=5 input.mp4

(The synthetic video is used only for demonstration).


When executing ffmpy.FFmpeg(inputs={"input.mp4": None}, outputs={"output.mp4": ["-y", "-vf", "crop=ih*(9/16):ih,scale=1080:1920", "-preset", "ultrafast"]}), we are getting an error message:

Invalid too big or non positive size for width '112' or height '200'


For fixing the issue, we may check if height*9/16 <= width.
We may get the video resolution (width and height) using OpenCV (or any other package we find).
Now we can check if height*9/16 <= width, and use other cropping parameters if the condition is false.


Code sample:

import ffmpy
import cv2

# Get video resolution using OpenCV
cap = cv2.VideoCapture('input.mp4')
width  = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
cap.release()

crop_w = height*9/16

if crop_w <= width:
    # We can do the cropping only when the cropped area is inside frame boundaries.
    ff = ffmpy.FFmpeg(inputs={"input.mp4": None}, outputs={"output.mp4": ["-y", "-vf", "crop=ih*(9/16):ih,scale=1080:1920", "-preset", "ultrafast"]})
else:
    ff = ffmpy.FFmpeg(inputs={"input.mp4": None}, outputs={"output.mp4": ["-y", "-vf", "crop=iw:iw*(16/9),scale=1080:1920", "-preset", "ultrafast"]})

ff.run()

Note: We don't really have to duplicate the part of the code (I used the duplication for demonstration).

Upvotes: 3

Related Questions