0
votes

This is my first SO question. Help me help you help me: does this question need any clarification?

Goal: A script that makes Instagram-ready videos with audio, and a logo overlay. The script takes in an audio and video source and combines them. Important: the logo should have a consistent position and size for each video. This probably means that all output videos should have the same width x height.

Any alternate approaches are welcome!

The ffmpeg command I'm calling from python is below. I try to scale the video to 720:-2 (so auto-height), then crop a 500x500 square from the center. The choices of 720 and 500 are arbitrary; better approaches are welcome.

ffmpeg -i video.mp4 -i logo.png -i audio.mp3 -filter_complex "[0:v]scale=720:-2,crop=500:500[bg];[bg][1:v] overlay=(W-w)/2:(H-h)/2" -pix_fmt yuv420p -map 0:v -map 2:a -shortest + output.mp4

This script errors on some videos.

[Parsed_crop_1 @ 0x7fcf96401f00] Invalid too big or non positive size for width '500' or height '500'
[Parsed_crop_1 @ 0x7fcf96401f00] Failed to configure input pad on Parsed_crop_1

I'm new to ffmpeg so please guide me to correct usage of filter_complex. Thank you!

2

2 Answers

0
votes

Use

ffmpeg -i video.mp4 -i logo.png -i audio.mp3 -filter_complex "[0:v]scale=720:-2,crop=min(500\,min(iw\,ih)):min(500\,min(iw\,ih))[bg];[bg][1:v] overlay=(W-w)/2:(H-h)/2" -pix_fmt yuv420p -map 2:a -shortest output.mp4

The new crop args will make sure crop does not try to pick a size larger than the frame.

The choice of scale and crop values depend upon the use case, and have to be decided by you.

0
votes

It looks like not all videos are the same height and width. Im not positive because it's been a while but when using scaling to width or height if all the videos you use aren't uniform height and width things can go funky, like your telling ffmpeg to place something where it cant. Some videos will work when the math is right and when its wrong you'll get errors.

I would use ffprobe to get the dimensions of the video.

import os
import json
import subprocess

def getVidInfo(videoPath):
    '''This function gets json data from ffprobe'''
    # print vPath
    if os.path.exists(videoPath):
        command = ['ffprobe', '-loglevel', 'quiet', '-print_format', 'json', '-show_format', '-show_streams', videoPath]
        pipe = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        out, err = pipe.communicate()
        if not err is None:
            print 'err = '+str(err)
        return json.loads(out)

## This was taken from an old python2.7 project so you might need to 
## get proper keys if these dont work.

vidJson = getVidInfo('pathToYourVideo')
vWidth = vidJson['streams'][0]['width']
vHeight = vidJson['streams'][0]['height']

Then do your math from the acquired video dimensions for ffmpeg call. Any way that is where I would start.