0

Im working on an application that is splitting videos from youtube into images. I work on a macbook pro for development, but our app servers run on an ubuntu 12.04 server. The current code on our servers running right now is the following

ffmpeg -i {video_file} -vf fps={fps}

which we run via a subprocess Popen function call in python. This has very slow performance because it is essentially playing back the whole video file to get the frames. I found another SO post that said you could use -accurate_seek -ss to grab single frames at a specific time, but I am facing some issues with that. When i run the command via command line when SSH into our dev server, it works fine, but when i run it via a subprocess Popen call in python, i get the following error:

(standard_in) 1: syntax error
ffmpeg version 3.2.4-static http://johnvansickle.com/ffmpeg/  Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 5.4.1 (Debian 5.4.1-5) 20170205
  configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc-5 --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gray --enable-libass --enable-libfreetype --enable-libfribidi --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libzimg
  libavutil      55. 34.101 / 55. 34.101
  libavcodec     57. 64.101 / 57. 64.101
  libavformat    57. 56.101 / 57. 56.101
  libavdevice    57.  1.100 / 57.  1.100
  libavfilter     6. 65.100 /  6. 65.100
  libswscale      4.  2.100 /  4.  2.100
  libswresample   2.  3.100 /  2.  3.100
  libpostproc    54.  1.100 / 54.  1.100
Option accurate_seek (enable/disable accurate seeking with -ss) cannot be applied to output url test.mkv -- you are trying to apply an input option to an output file or vice versa. Move this option before the file it belongs to.
Error parsing options for output file test.mkv.
Error opening output files: Invalid argument

python code:

import subprocess
command = "for i in {0..3} ; do ffmpeg -accurate_seek -ss `echo $i*60.0 | bc` -i test.mkv -frames:v 1 images/test_img_$i.jpg ; done"
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr = subprocess.STDOUT, shell=True)
output = process.communicate()
print output[0].replace('\\n' , '\n')

The thing is, when i run this on my OSX terminal, it works fine, but there is some issue with doing it in ubuntu. Does anyone have experience with this issue?

Output when i run the same exact code in osx:

ffmpeg version 3.0.2 Copyright (c) 2000-2016 the FFmpeg developers
  built with Apple LLVM version 7.3.0 (clang-703.0.31)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/3.0.2 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-opencl --enable-libx264 --enable-libmp3lame --enable-libxvid --enable-libvpx --enable-vda
  libavutil      55. 17.103 / 55. 17.103
  libavcodec     57. 24.102 / 57. 24.102
  libavformat    57. 25.100 / 57. 25.100
  libavdevice    57.  0.101 / 57.  0.101
  libavfilter     6. 31.100 /  6. 31.100
  libavresample   3.  0.  0 /  3.  0.  0
  libswscale      4.  0.100 /  4.  0.100
  libswresample   2.  0.101 /  2.  0.101
  libpostproc    54.  0.100 / 54.  0.100
  Input #0, matroska,webm, from 'test.mkv':
  Metadata:
    COMPATIBLE_BRANDS: iso6avc1mp41
    MAJOR_BRAND     : dash
    MINOR_VERSION   : 0
    ENCODER         : Lavf57.25.100
  Duration: 00:02:10.20, start: 0.007000, bitrate: 2729 kb/s
    Stream #0:0: Video: h264 (High), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default)
    Metadata:
      HANDLER_NAME    : VideoHandler
      DURATION        : 00:02:10.172000000
    Stream #0:1(eng): Audio: opus, 48000 Hz, stereo, fltp (default)
    Metadata:
      DURATION        : 00:02:10.201000000
      [swscaler @ 0x7f9b4b008000] deprecated pixel format used, make sure you did set range correctly
Output #0, image2, to 'images/test_img_0.jpg':
  Metadata:
    COMPATIBLE_BRANDS: iso6avc1mp41
    MAJOR_BRAND     : dash
    MINOR_VERSION   : 0
    encoder         : Lavf57.25.100
    Stream #0:0: Video: mjpeg, yuvj420p(pc), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 23.98 fps, 23.98 tbn, 23.98 tbc (default)
    Metadata:
      HANDLER_NAME    : VideoHandler
      DURATION        : 00:02:10.172000000
      encoder         : Lavc57.24.102 mjpeg
    Side data:
      unknown side data type 10 (24 bytes)
      Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> mjpeg (native))
  Press [q] to stop, [?] for help
frame=    1 fps=0.0 q=7.2 Lsize=N/A time=00:00:00.04 bitrate=N/A speed=   1x    
video:73kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
....

One thing i forgot to mention is that on my mac i used homebrew to install ffmpeg, where as on Ubuntu i used a static build

other stack overflow reference: Fastest way to extract frames using ffmpeg?

Community
  • 1
  • 1
Wonger
  • 285
  • 6
  • 18

1 Answers1

0

The problem is the range notation {0..3}, which works in bash but not in other shells. While the normal login shell on my Ubuntu system is bash, subprocess.Popen() with shell=True calls /bin/sh, which in my case is not bash but dash, which does not support brace expansion.

Since the range is not expanded, the loop runs only once, with the variable $i containing the string {0..3}. That is passed to bc, causing the first error (standard_in) 1: syntax error. As a result the accurate_seek argument -ss to ffmpeg does not get any value.

On my Ubuntu system with dash shell, a loop with seq works:

$ sh
$ for i in $(seq 0 3); do echo $i; done    
0
1
2
3

as opposed to:

$ sh
$ for i in {0..3}; do echo $i; done
{0..3}

But as seq is not POSIX and may not be present on all systems, it may be best not to rely too much on the shell anyway (see also the warning in the documentation).

gdwarf
  • 76
  • 1
  • 3