在 Python 3.10 中使用 ffprobe 有困难
Difficulty with ffprobe in Python 3.10
我很新
所以这个 getLength 函数 运行 在 python 2.7 中可以正常工作,但我无法在 3.10 中使用它。想知道是否有人可以建议可能需要更改的内容,因为我不知所措。当我尝试打印 return 时,那里什么也没有。我 95% 确定问题出在 result = subprocess.Popen() 行,但为了完整起见,我包含了整个函数
#function...returns 视频文件的时长HH:MM:SS
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'
我很确定 python3 中的输出是字节流而不是字符串。
试试这个:
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))
输出:
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]
如果您同意以秒为单位的持续时间(不是 HH:MM:SS
表示法),我更喜欢使用 -of json
选项,这样我就可以使用 json
包来解析ffprobe 输出:
import subprocess as sp
import json
from pprint import pprint
out = sp.run(['ffprobe','-hide_banner','-of','json',
'-show_entries','format:stream', f'"{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
注意:您必须指定 -show_entries
选项,否则它将 return 为空 JSON
只是为了插入我的图书馆(pip install fmpegio-core
),你可以交替运行:
import ffmpegio
file_duration = ffmpegio.probe.format_basic(filename)['duration']
在Python中3个字符串在Unicode format中,stdout
输出是字节数组。
我们可以使用 x.decode("utf-8")
:
将字节数组转换为字符串
解析列表可能如下所示:
y = [x.decode("utf-8") for x in result.stdout.readlines() if "Duration: " in x.decode("utf-8")]
完整代码示例(使用 stderr
而不是 stdout
):
import subprocess
def get_length(filename):
# Uses FFprobe to get info about the video file
result = subprocess.Popen(["ffprobe", filename], stderr=subprocess.PIPE)
# Finds the info that has the word "Duration"
# Convert bytes array to strings using decode("utf-8")
y = [x.decode("utf-8") for x in result.stderr.readlines() if "Duration: " in x.decode("utf-8")]
# 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'
res = get_length('BBB.ogv')
print(res)
为了获取 OVG(或 MP4)文件的视频持续时间,我们可以 select JSON 格式:
import subprocess as sp
import json
# https://superuser.com/questions/650291/how-to-get-video-duration-in-seconds
data = sp.run(["ffprobe", '-v', 'error', '-select_streams', 'v', '-of', 'default=noprint_wrappers=1:nokey=1', '-show_entries', 'stream=duration', '-of', 'json', 'BBB.ogv'], stdout=sp.PIPE).stdout
dict = json.loads(data)
print(dict['streams'][0]['duration'])
我很新
所以这个 getLength 函数 运行 在 python 2.7 中可以正常工作,但我无法在 3.10 中使用它。想知道是否有人可以建议可能需要更改的内容,因为我不知所措。当我尝试打印 return 时,那里什么也没有。我 95% 确定问题出在 result = subprocess.Popen() 行,但为了完整起见,我包含了整个函数
#function...returns 视频文件的时长HH:MM:SS
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'
我很确定 python3 中的输出是字节流而不是字符串。
试试这个:
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))
输出:
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]
如果您同意以秒为单位的持续时间(不是 HH:MM:SS
表示法),我更喜欢使用 -of json
选项,这样我就可以使用 json
包来解析ffprobe 输出:
import subprocess as sp
import json
from pprint import pprint
out = sp.run(['ffprobe','-hide_banner','-of','json',
'-show_entries','format:stream', f'"{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
注意:您必须指定 -show_entries
选项,否则它将 return 为空 JSON
只是为了插入我的图书馆(pip install fmpegio-core
),你可以交替运行:
import ffmpegio
file_duration = ffmpegio.probe.format_basic(filename)['duration']
在Python中3个字符串在Unicode format中,stdout
输出是字节数组。
我们可以使用 x.decode("utf-8")
:
解析列表可能如下所示:
y = [x.decode("utf-8") for x in result.stdout.readlines() if "Duration: " in x.decode("utf-8")]
完整代码示例(使用 stderr
而不是 stdout
):
import subprocess
def get_length(filename):
# Uses FFprobe to get info about the video file
result = subprocess.Popen(["ffprobe", filename], stderr=subprocess.PIPE)
# Finds the info that has the word "Duration"
# Convert bytes array to strings using decode("utf-8")
y = [x.decode("utf-8") for x in result.stderr.readlines() if "Duration: " in x.decode("utf-8")]
# 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'
res = get_length('BBB.ogv')
print(res)
为了获取 OVG(或 MP4)文件的视频持续时间,我们可以 select JSON 格式:
import subprocess as sp
import json
# https://superuser.com/questions/650291/how-to-get-video-duration-in-seconds
data = sp.run(["ffprobe", '-v', 'error', '-select_streams', 'v', '-of', 'default=noprint_wrappers=1:nokey=1', '-show_entries', 'stream=duration', '-of', 'json', 'BBB.ogv'], stdout=sp.PIPE).stdout
dict = json.loads(data)
print(dict['streams'][0]['duration'])