1

I am trying to run an autocrop ffmpeg command in python. The command works in Ruby so I am not sure why it isn't working in Python. I am just trying to run an autocrop on the videos just in case they have black bars on the top/bottom/sides.

I found this bit of code from this thread a while ago and it has worked for me in Ruby, which makes me think this might be a Python syntax issue because I am running the same version of FFMPEG on my computer.

Would appreciate any help on this

Here is the command from that thread in my Python file:

Code

import subprocess

in_file = /path/input.mp4
out_file = /path/output.mp4

cmd = [
    'ffmpeg', 
    '-y',
    '-i', in_file,
    '-vf', 'cropdetect -f null - 2>&1 | awk \'/crop/ { print \$NF }\' | tail -1',
    out_file
]
subprocess.Popen(cmd, stdout = subprocess.PIPE, bufsize=10**8)

Error

ffmpeg version 3.3.4 Copyright (c) 2000-2017 the FFmpeg developers
  built with Apple LLVM version 7.0.2 (clang-700.1.81)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/3.3.4 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-libass --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-opencl --enable-videotoolbox --disable-lzma --enable-nonfree --enable-vda
  libavutil      55. 58.100 / 55. 58.100
 [...]
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))
Press [q] to stop, [?] for help
[AVFilterGraph @ 0x7f8c23d1dc60] No such filter: 'cropdetect -f null - 2>&1 | awk /crop/ { print $NF } | tail -1'
Error reinitializing filters!
Failed to inject frame into filter network: Invalid argument
Error while processing the decoded data for stream #0:0
[aac @ 0x7f8c2400a400] Qavg: 45917.641
[aac @ 0x7f8c2400a400] 2 frames left in the queue on closing
Conversion failed!

After more searching, I discovered another approach and have been working on running this but still with no luck:

Code

import subprocess

in_file = /path/input.mp4
out_file = /path/output.mp4

cmd = [
    'ffmpeg', 
    '-y',
    '-i', in_file,
    '-vf', 'cropdetect=24:16:0 -y -crf 51 ultrafast -f null /dev/null 2>&1 | grep -o crop=.* | sort -bh | uniq -c | sort -bh | tail -n1 | grep -o crop=.*', 
    out_file
]
subprocess.Popen(cmd, stdout = subprocess.PIPE, bufsize=10**8)

Error

ffmpeg version 3.3.4 Copyright (c) 2000-2017 the FFmpeg developers
  built with Apple LLVM version 7.0.2 (clang-700.1.81)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/3.3.4 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-libass --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-opencl --enable-videotoolbox --disable-lzma --enable-nonfree --enable-vda
  libavutil      55. 58.100 / 55. 58.100
[ ... ]
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))
Press [q] to stop, [?] for help
[01/Oct/2017 16:44:25] "GET /home/ HTTP/1.1" 200 13844
[cropdetect @ 0x7f85aca02d00] [Eval @ 0x7fff5cfc1820] Undefined constant or missing '(' in 'y-crf51ultrafast-fnull/dev/null2>&1|grep-ocrop=.*|sort-bh|uniq-c|sort-bh|tail-n1|grep-ocrop=.*'
[cropdetect @ 0x7f85aca02d00] Unable to parse option value "0 -y -crf 51 ultrafast -f null /dev/null 2>&1 | grep -o crop=.* | sort -bh | uniq -c | sort -bh | tail -n1 | grep -o crop=.*"
[cropdetect @ 0x7f85aca02d00] [Eval @ 0x7fff5cfc18a0] Undefined constant or missing '(' in 'y-crf51ultrafast-fnull/dev/null2>&1|grep-ocrop=.*|sort-bh|uniq-c|sort-bh|tail-n1|grep-ocrop=.*'
[cropdetect @ 0x7f85aca02d00] Unable to parse option value "0 -y -crf 51 ultrafast -f null /dev/null 2>&1 | grep -o crop=.* | sort -bh | uniq -c | sort -bh | tail -n1 | grep -o crop=.*"
[cropdetect @ 0x7f85aca02d00] Error setting option reset to value 0 -y -crf 51 ultrafast -f null /dev/null 2>&1 | grep -o crop=.* | sort -bh | uniq -c | sort -bh | tail -n1 | grep -o crop=.*.
[Parsed_cropdetect_0 @ 0x7f85aca02c40] Error applying options to the filter.
[AVFilterGraph @ 0x7f85ac904e20] Error initializing filter 'cropdetect' with args '24:16:0 -y -crf 51 ultrafast -f null /dev/null 2>&1 | grep -o crop=.* | sort -bh | uniq -c | sort -bh | tail -n1 | grep -o crop=.*'
Error reinitializing filters!
Failed to inject frame into filter network: Invalid argument
Error while processing the decoded data for stream #0:0
[aac @ 0x7f85ad805000] Qavg: 45917.641
[aac @ 0x7f85ad805000] 2 frames left in the queue on closing
Conversion failed!
Grady Woodruff
  • 143
  • 2
  • 11

2 Answers2

3

Check the line [AVFilterGraph @ 0x7f85ac904e20] Error initializing filter ..

What you think are piped shell commands is passed as a single argument to ffmpeg, which confuses it.

Add a print(cmd) before you run the command and you will see that the '-vf' flag just gets a very large argument.

  • do you have any idea why it would work when i am running `'-vf', 'crop=500:500, pad=width=550:height=550:x=25:y=25:color=white',` in the `-vf` line – Grady Woodruff Oct 01 '17 at 17:53
  • 1
    Because that is a valid argument for -vf. All commandline tools fundamentally accept an array of strings, and each string can contain whitespaces - a frequent stumbling block. So `-vf`, `filter_arg1:filter arg two with spaces` is fundamentally different from `-vf`, `filter_arg1:filter`, `arg`, `two`, `with`, `spaces` – finite graygreen Oct 01 '17 at 18:00
0

In case it helps anyone in the future, here is one solution to the problem I was facing. I run the cropdetect in a seperate ffmpeg command and store its output as a variable.

I'm not so familiar with python so this solution might not be the most elegant, if anyone with more python experience has a better way of formatting the subprocess layout, it would be awesome to see a better layout

I tested this and it works:

import subprocess

in_file = '/path/input.mp4'
out_file = '/path/output.mp4'

crop_dimensions = subprocess.Popen(['ffmpeg -i ' + in_file + ' -vf cropdetect -f null - 2>&1 | awk \'/crop/ { print $NF }\' | tail -1'], shell=True, stdout=subprocess.PIPE).stdout.read().strip()

cmd = [
    'ffmpeg', 
    '-y',
    '-i', in_file,
    '-vf', crop_dimensions,
    out_file
]
subprocess.Popen(cmd, stdout = subprocess.PIPE, bufsize=10**8)
Grady Woodruff
  • 143
  • 2
  • 11