1

I'm trying to pass a glob pattern to ffmpeg via subprocess.check_output(). This appears to be having an issue as the output is what I would expect if the pattern was passed within quotes.

Example:

subprocess.check_output([ffmpeg_path, '-pattern_type', 'glob', '-i', '/tmp/*?(jpg|jpeg)'...])

This results in:

/tmp/*?(jpg|jpeg): No such file or directory.

Which is different than the "no matches" error I receive if run this command via the shell. What appears to be happening is that the command is being composed as

ffmpeg -pattern_type 'glob' -i '/tmp/*?(jpg|jpeg)'

and what I'd want is (note lack of quotations)

ffmpeg -pattern_type glob -i /tmp/*?(jpg|jpeg)

Something of note is that I am passing in the directory so directory + '/*?(jpg|jpeg)' is what is in the list being passed to check_output(). This may be part of the issue.

How would I prevent this, or how would I pass the raw arguments desired?

ffmpeg version when running on development machine:

ffmpeg version 4.4.1 Copyright (c) 2000-2021 the FFmpeg developers
  built with Apple clang version 13.0.0 (clang-1300.0.29.3)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/4.4.1_5 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-avresample --enable-videotoolbox

and using the ffmpeg amd64 static build when deployed.

0

2 Answers 2

2

Your wildcard pattern uses a bash extension, which ffmpeg probably doesn't support.

Instead, use multiple -i options, with standard wildcards.

subprocess.check_output([ffmpeg_path, '-pattern_type', 'glob', '-i', '/tmp/*.jpg', '-i', '/tmp/*.jpeg', ...])

There are no actual quotes being added. When you use shell=False, the list elements are passed as is directly to the program, without going through a shell, so no quoting is needed. The documentation doesn't explain it accurately -- what they mean is that this acts as if you were quoting all the arguments.

Sign up to request clarification or add additional context in comments.

1 Comment

Using multiple -i is not working, at least not with newer versions (I tested with FFmpeg version 4.3.1). The meaning of multiple -i is multiple input streams and not multiple input lists of images. When using subprocess.check_output([ffmpeg_path, '-y', '-pattern_type', 'glob', '-i', '*.jpg', '-pattern_type', 'glob', '-i', '*.jpeg', 'test.mp4']) there is no error, but the *.jpeg files are ignored (we may solve it using concat filter, but it complicates things).
1

The quotes is not the issue, the FFmpeg glob syntax is a little different than the one you are using.

Here is an example for a correct syntax:

subprocess.check_output([ffmpeg_path, '-vcodec', 'mjpeg', '-f', 'image2', '-pattern_type', 'glob', '-i', '/tmp/*?{jpg,jpeg}', 'test.mp4'])

  • Specify the video codec: '-vcodec', 'mjpeg'.
    I suppose FFmpeg fails to identify the codec automatically due to the pattern.
  • Specify the muxer format: '-f', 'image2'.
    I suppose FFmpeg fails to identify the format automatically due to the pattern.
  • Use the following syntax: '/tmp/*?{jpg,jpeg}' (instead of /tmp/*?(jpg|jpeg)).
    The pattern matches the rules of Bash Gglobing.

The command line includes the quotes, and it's working with the them.

ffmpeg -vcodec mjpeg -f image2 -pattern_type glob -i "/tmp/*?{jpg,jpeg}" -vcodec libx264 test.mp4

Testing:

I tested the Python code under Ubuntu 18.04 (using VirtualBox).

Using command line (console):

Changing directory to /tmp (in Ubuntu it supposed to be existed):
cd /tmp

Checking FFmpeg version:
ffmpeg -version

Output:
ffmpeg version 3.1.3-static http://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2016 the FFmpeg developers built with gcc 5.4.1 (Debian 5.4.1-1) 20160803
(I think it's the default version of Ubuntu 18.04).

Creating 10 (synthetic pattern) files with jpg extension and 7 files with jpeg extension:
ffmpeg -f lavfi -i testsrc=size=192x108:rate=1:duration=10 %d.jpg
ffmpeg -f lavfi -i testsrc=size=192x108:rate=1:duration=7 %d.jpeg

List jpg and jpeg files:
ls *?{jpg,jpeg}

Output:
10.jpg 1.jpeg 1.jpg 2.jpeg 2.jpg 3.jpeg 3.jpg 4.jpeg 4.jpg 5.jpeg 5.jpg 6.jpeg 6.jpg 7.jpeg 7.jpg 8.jpg 9.jpg

Encoding the files (in command line):
ffmpeg -y -vcodec mjpeg -f image2 -pattern_type glob -i "/tmp/*?{jpg,jpeg}" -vcodec libx264 test.mp4

Verifying there are 17 video frames using FFprobe:
ffprobe -v error -select_streams v:0 -count_frames -show_entries stream=nb_read_frames -print_format csv test.mp4

Output:
stream,17

delete test.mp4:
rm test.mp4


Python test (still in folder /tmp, and console):

Checking Python version:
python3 --version

Output:
Python 3.7.4

Copy test.py into /tmp folder.
Content of test.py (the file is in the same folder: /tmp):

import subprocess

ffmpeg_path = 'ffmpeg'

subprocess.check_output([ffmpeg_path, '-vcodec', 'mjpeg', '-f', 'image2', '-pattern_type', 'glob', '-i', '/tmp/*?{jpg,jpeg}', 'test.mp4'])

Executing the Python script form shell:
python3 test.py

Output:
ffmpeg version 3.1.3-static http://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2016 the FFmpeg developers
...
frame= 17

9 Comments

I'll give this a shot. Of note is that I reduced the example to the parts that I was able to figure out weren't working. I appreciate the -vcodec tip, but I do specify the other options in a way that works (with the Bash extension). I'll check with the new globbing pattern.
I am limiting the scope of my answer to the parts that are in your post, and I can't promise anything about the parts that you didn't post. Please test it as in my answer first.
I tried this pattern but I still get the same result. The output is the ffmpeg version and configuration options followed by /long/absolute/path/*?{jpeg,jpeg}: No such file or directory If I stop this script via a debugger I can verify the existence of the directory and files via ls, as I also do with os.path.isdir and os.listdir in the script. Of note may be that there is no file with the jpg extension.
Well... I tested it in Ubuntu 18.04 and FFmpeg version 4.3.1. Is it working with just *.jpg instead of *?{jpg,jpeg} ?
When testing, I didn't use the path \tmp, I used some other full path. The directory had jpeg and jpg files.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.