Home > database >  Difficulty with ffprobe in Python 3.10
Difficulty with ffprobe in Python 3.10

Time:02-17

I'm very new

So this getLength function will run fine in python 2.7 but I can't get it to work in 3.10. Was wondering if anyone could suggest what may need to be changed because I am at a loss. When I try to print the return there is nothing there. I am 95% sure the issue is with the result = subprocess.Popen() line but I include the entire function for completeness

#function... returns the duration HH:MM:SS of a video file

def getLength(filename):

   #uses ffprobe to get info about the video file

   result = subprocess.Popen(["ffprobe", filename],

   stdout = subprocess.PIPE, stderr = subprocess.STDOUT)


   #finds the info that has the word "Duration"

   y = [x for x in result.stdout.readlines() if "Duration: " in x]

   #get the location of the "Duration: " phrase

   loc = y[0].find("Duration: ")

   #assuming we find the location of that phrase..

   if loc != -1:

   #cut out everything before and everything more than 10 characters later

   print ( y[0][loc 10:loc 18] )

   return y[0][loc 10:loc 18]

   else:

   #if we don't find anything then set it to be 2 seconds of nothing...

   print ( y[0][loc 10:loc 18] )

   return '00:00:02' 

CodePudding user response:

I'm pretty sure that the output in python3 is a byte stream rather than a str.
Try this:

import subprocess
media = "/home/rolf/BBB.ogv"
try:
    comm = subprocess.Popen(['ffprobe', '-hide_banner', '-show_entries', 'format=size, duration',\
                       '-i', media], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
except Exception as e:
    pass
try:
    with comm.stdout:
        for i in iter(comm.stdout.readline, b''):
            if i != '':
                print(i)
            else:
                break
except Exception as e:
    print("Error: ", str(e))

Output:

python probe.py
Input #0, ogg, from '/home/rolf/BBB.ogv':

  Duration: 00:01:00.14, start: 0.000000, bitrate: 264 kb/s

  Stream #0:0(eng): Video: theora, yuv420p, 640x360 [SAR 1:1 DAR 16:9], 24 fps, 24.04 tbr, 24.04 tbn

    Metadata:

      creation_time   : 2011-03-16 10:41:52

      handler_name    : Apple Video Media Handler

      encoder         : Lavc56.60.100 libtheora

      major_brand     : mp42

      minor_version   : 1

      compatible_brands: mp42avc1

  Stream #0:1(eng): Audio: vorbis, 44100 Hz, mono, fltp, 80 kb/s

    Metadata:

      creation_time   : 2011-03-16 10:41:53

      handler_name    : Apple Sound Media Handler

      encoder         : Lavc56.60.100 libvorbis

      major_brand     : mp42

      minor_version   : 1

      compatible_brands: mp42avc1

[FORMAT]

duration=60.139683

size=1992112

[/FORMAT]
    

CodePudding user response:

If you are OK with the duration in seconds (not in the HH:MM:SS notation), I prefer to use the -of json option so I can use json package to parse the ffprobe output:

import subprocess as sp
import json
from pprint import pprint

out = sp.run(f'ffprobe -hide_banner -of json -show_entries format:stream "{filename}"', 
             stdout=sp.PIPE, universal_newlines=True)
results = json.loads(out.stdout)

pprint(results) # to see the full details

format_duration = float(results['formats']['duration']) # in seconds
stream_durations = [float(st['duration']) for st in results['streams']] # in seconds

Note: You must specify -show_entries option or it'll return an empty JSON

Just to plug my library (pip install fmpegio-core), you can alternately run:

import ffmpegio

file_duration = ffmpegio.probe.format_basic(filename)['duration']
  • Related