2012-03-27 23 views
7

Próbowałem to rozgryźć na zawsze teraz (jestem nowy w programowaniu) i nie mogę tego rozgryźć.Uzyskiwanie informacji o FFProbe z Pythonem

Próbuję zbudować skrypt, który przetestuje plik i da mi dane wyjściowe, z których mogę uzyskać informacje takie jak "Format audio", który mogę następnie umieścić w nazwie pliku. Jednak nie mogę nawet uzyskać skryptu do zwrócenia żadnych informacji o pliku. Uderzyłem w ścianę przy wstawianiu pliku wejściowego ...

W tym momencie potrzebuję pomocy w wypluciu informacji na podstawie argumentów, które włączyłem. Mam nadzieję, że będę w stanie wymyślić jak przetworzyć informacje audio z tego.

Moja próba, która wydaje się być blisko:

#!/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('.')] 

Odpowiedz

8

Kilka problemów w kodzie listy

  1. args do POPEN ma ostatni argument jako -i filename który jest zastosowaniem błąd składni '-i '+filename zamiast
  2. shell=True zwykle nie jest potrzebny i stanowi niepotrzebne obciążenie.

Poza tym wydaje się, że działa, czy nie widzisz danych wyjściowych po ustaleniu pierwszego numeru?

Edit: Wygląda na to, że mają problem z ffprobe poleceń, więc zainstalowałem go i zmiany wymagające są

  1. Moja ffprobe (ffprobe 0.7.3-4: 0.7.3-0ubuntu0.11.10.1) nie przyjmuje flagi -i, plik wejściowy jest właśnie przekazywany jako ostatni argument.
  2. trzeba przejść -logelevel oraz możliwość logleve quiet jako osobne argumenty tj [..., '-loglevel', 'quiet',..]

Więc po tych zmianach Oto przykładowy skrypt

#!/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') 

I widzę poprawny wynik:

==========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 
+0

Dostaję '... '/ opt/local/bin/ffprobe: brakujący argument dla opcji 'i foo' \ n ")' –

+0

@RobinHood oznacza, że ​​nie przekazujesz poprawnych parametrów do ffprobe, najpierw spróbuj zobaczyć, jak poprawnie użyć ffprobe z linii poleceń, a następnie przetłumaczyć to na python –

+0

Polecenie '/opt/local/bin/ffprobe -pretty -i 'foo.avi'' zwraca informację; polecenie '/ opt/local/bin/ffprobe -pretty -i 'foo.avi' \ n' doesnt; ale nie mogę zrozumieć, co do cholery dodaje '\ n' –

1

Oto technika, którą myślę, że jest zarówno łatwa w użyciu, jak i łatwa w analizie (przetestowana za pomocą ff mpeg 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)) 

Dostępne dane pochodzą z ciąg znaków, który wygląda tak:

<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> 
+0

Twoje parsowanie XML nie działa dla mnie (Debian 9, Python 3.5.3, ffprobe 3.2.8-1 ~ deb9u1). Ale dzięki za podpowiedź jednak: Przekształciłem twój kod, by używać JSON i działało. –

+0

Dzięki za opinię. Czy możesz powiedzieć, dlaczego to nie działa? Czy jest to problem w języku Python, czy wygenerowany kod XML nie jest zgodny? –

+0

Kiedy wywołuję twoją funkcję, instrukcja return daje mi moduł 'AttributeError: module 'xml.etree' nie ma atrybutu 'ElementTree'' –

Powiązane problemy