Getting FFProbe Information Using Python

I'm trying to figure this out forever (I'm new to programming) and I can't figure it out.

I am trying to create a script that will check a file and give me an output from which I can get information like "Audio Format", which I can then enter in the file name. However, I cannot even get a script to return file information. I hit the wall when pasting the input file ...

So, at this point, I just need help to get him to spit out the information based on the argvs I put in. I hope I can figure out how to parse the audio information.

My attempt seems close:

#!/usr/bin/python import os, sys, subprocess, shlex, re from subprocess import call def probe_file(filename): p = subprocess.Popen(['/opt/local/bin/ffprobe', '-show_format', '-pretty', '-loglevel quiet', -i filename], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) print filename print p.communicate() [probe_file (f) for f in os.listdir('.') if not f.startswith('.')] 
+7
source share
3 answers

There are several problems in your code:

  1. the argument list for Popen has the last argument of the form -i filename , which is a syntax error, use '-i '+filename instead
  2. shell=True usually not needed and is an unnecessary burden.

Also, it looks like it works, you don’t see the output after fixing # 1?

Edit: it looks like you have problems with the ffprobe command line, so I installed it and make the following changes:

  1. My ffprobe (ffprobe 0.7.3-4: 0.7.3-0ubuntu0.11.10.1) doesn't seem to accept the -i flag, the input file is just passed as the last argument.
  2. you need to pass -loglevel and the loglevel quiet option as separate arguments, i.e. [..., '-loglevel', 'quiet',..]

So, after these changes, here is an example script:

 #!/usr/bin/python import os, sys, subprocess, shlex, re from subprocess import call def probe_file(filename): cmnd = ['ffprobe', '-show_format', '-pretty', '-loglevel', 'quiet', filename] p = subprocess.Popen(cmnd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) print filename out, err = p.communicate() print "==========output==========" print out if err: print "========= error ========" print err probe_file('drop.avi') 

And I see the correct conclusion:

 ==========output========== [FORMAT] filename=drop.avi nb_streams=1 format_name=avi format_long_name=AVI format start_time=0:00:00.000000 duration=0:00:06.066667 size=660.000 Kibyte bit_rate=891.217 Kbit/s [/FORMAT] ========= error ======== ffprobe version 0.7.3-4:0.7.3-0ubuntu0.11.10.1, Copyright (c) 2007-2011 the Libav developers built on Jan 4 2012 16:08:51 with gcc 4.6.1 configuration: --extra-version='4:0.7.3-0ubuntu0.11.10.1' --arch=amd64 --prefix=/usr --enable-vdpau --enable-bzlib --enable-libgsm --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libvorbis --enable-pthreads --enable-zlib --enable-libvpx --enable-runtime-cpudetect --enable-vaapi --enable-gpl --enable-postproc --enable-swscale --enable-x11grab --enable-libdc1394 --enable-shared --disable-static libavutil 51. 7. 0 / 51. 7. 0 libavcodec 53. 6. 0 / 53. 6. 0 libavformat 53. 3. 0 / 53. 3. 0 libavdevice 53. 0. 0 / 53. 0. 0 libavfilter 2. 4. 0 / 2. 4. 0 libswscale 2. 0. 0 / 2. 0. 0 libpostproc 52. 0. 0 / 52. 0. 0 Unsupported codec with id 114 for input stream 0 
+9
source

Here is a technique, I think it is simple and easy to analyze (tested with ffmpeg 3.x):

 import subprocess import xml.etree def ffprobe(executable, filename): '''Runs ``ffprobe`` executable over ``filename``, returns parsed XML Parameters: executable (str): Full path leading to ``ffprobe`` filename (str): Full path leading to the file to be probed Returns: xml.etree.ElementTree: containing all parsed elements ''' cmd = [ executable, '-v', 'quiet', '-print_format', 'xml', #here is the trick '-show_format', '-show_streams', filename, ] return xml.etree.ElementTree.fromstring(subprocess.check_output(cmd)) 

Available data comes from a string representation that looks like this:

  <ffprobe> <streams> <stream index="0" codec_name="h264" codec_long_name="H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10" profile="Constrained Baseline" codec_type="video" codec_time_base="1/60" codec_tag_string="avc1" codec_tag="0x31637661" width="560" height="320" coded_width="560" coded_height="320" has_b_frames="0" sample_aspect_ratio="0:1" display_aspect_ratio="0:1" pix_fmt="yuv420p" level="30" color_range="tv" color_space="bt709" color_transfer="bt709" color_primaries="bt709" chroma_location="left" refs="1" is_avc="true" nal_length_size="4" r_frame_rate="30/1" avg_frame_rate="30/1" time_base="1/90000" start_pts="0" start_time="0.000000" duration_ts="498000" duration="5.533333" bit_rate="465641" bits_per_raw_sample="8" nb_frames="166"> <disposition default="1" dub="0" original="0" comment="0" lyrics="0" karaoke="0" forced="0" hearing_impaired="0" visual_impaired="0" clean_effects="0" attached_pic="0" timed_thumbnails="0"/> <tag key="creation_time" value="2010-03-20T21:29:11.000000Z"/> <tag key="language" value="und"/> <tag key="encoder" value="JVT/AVC Coding"/> </stream> <stream>...</stream> </streams> <format filename="/Users/andre/Projects/qnap/librarian/librarian/data/movie.mp4" nb_streams="2" nb_programs="0" format_name="mov,mp4,m4a,3gp,3g2,mj2" format_long_name="QuickTime / MOV" start_time="0.000000" duration="5.568000" size="383631" bit_rate="551193" probe_score="100"> <tag key="major_brand" value="mp42"/> <tag key="minor_version" value="0"/> <tag key="compatible_brands" value="mp42isomavc1"/> <tag key="creation_time" value="2010-03-20T21:29:11.000000Z"/> <tag key="encoder" value="HandBrake 0.9.4 2009112300"/> </format> </ffprobe> 
+2
source

There is an FFProbe shell for Python ( https://pypi.org/project/ffprobe/ ).

You can easily install it: (sudo) pip install ffprobe

Typical Usage:

 from ffprobe import FFProbe metadata = FFProbe("example.mp4") 

An alternative to FFProbe is the pymediainfo library ( https://pymediainfo.readthedocs.io/en/stable/ ). You can find use in the site documentation.

+1
source

All Articles