2012-03-27 12 views
7

He estado tratando de resolver esto por siempre (soy nuevo en la programación) y no puedo resolverlo.Obteniendo información de FFProbe con Python

Estoy intentando construir una secuencia de comandos que probará el archivo, y me dará un resultado del cual puedo obtener información como "Formato de audio" que luego puedo poner en el nombre del archivo. Sin embargo, ni siquiera puedo obtener el script para devolver cualquier información de archivo. Me he topado con una pared al insertar un archivo de entrada ...

Así que en este punto solo necesito ayuda para escupir información en función de los argvs que he arrojado. Con suerte podré figurar cómo analizar la información de audio de eso.

Mi intento que parece estar cerca:

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

Respuesta

8

pocos problemas en su código de lista

  1. args a Popen tiene último argumento como -i filename que es un error utilizar la sintaxis '-i '+filename lugar
  2. shell=True generalmente no es necesario y es una carga innecesaria.

Aparte de eso, parece que está funcionando, ¿no está viendo la salida después de arreglar # 1?

Editar: Parece que usted está teniendo problemas con comandos ffprobe, así que lo instaló y cambios que se requieren son

  1. Mi ffprobe (ffprobe 0.7.3-4: 0.7.3-0ubuntu0.11.10.1) no parece aceptar el indicador -i, el archivo de entrada acaba de pasar como último argumento.
  2. que necesita para pasar -logelevel y la opción de logleve quiet como argumentos separados, es decir, [..., '-loglevel', 'quiet',..]

Así que después de estos cambios aquí es un script de ejemplo

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

Y veo la salida correcta:

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

Me estoy poniendo '... '/ opt// bin/ffprobe locales: falta un argumento para la opción 'i foo' \ n ")' –

+0

@RobinHood, lo que significa que no está pasando los parámetros correctos a ffprobe, primero intente ver cómo usar ffprobe correctamente desde la línea de comandos y luego traduzca eso a python –

+0

El comando '/opt/local/bin/ffprobe -pretty -i 'foo.avi'' devuelve información; el comando '/ opt/local/bin/ffprobe -pretty -i 'foo.avi' \ n' doesnt; pero no puedo entender qué diablos está agregando el '\ n' –

1

Esta es una técnica que creo que es simple de usar y fácil de analizar (probado con ff 3.x MPEG):

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)) 

Los datos disponibles proviene de una representación de cadena que tiene este aspecto:

<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

Su análisis XML no funciona para mí (Debian 9, Python 3.5.3, ffprobe 3.2.8-1 ~ deb9u1). Pero gracias por la sugerencia: Transformé tu código para usar JSON y está funcionando. –

+0

Gracias por los comentarios. ¿Podría decirnos por qué no funciona para usted? ¿Es un problema de Python o el XML generado no cumple? –

+0

Cuando llamo a su función, la declaración de devolución me da un 'AttributeError: module 'xml.etree' no tiene atributo 'ElementTree'' –

Cuestiones relacionadas