Video 从ffmpeg获取视频尺寸/分辨率/宽度x高度
如何从Video 从ffmpeg获取视频尺寸/分辨率/宽度x高度,video,ffmpeg,ffprobe,Video,Ffmpeg,Ffprobe,如何从ffmpeg的信息输出中获得视频的高度和宽度。例如,使用以下输出: $ ffmpeg -i video.mp4 ... Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video.mp4': Metadata: major_brand : isom minor_version : 1 compatible_brands: isomavc1 creation_time : 2010-01-24 00:55:
ffmpeg
的信息输出中获得视频的高度和宽度。例如,使用以下输出:
$ ffmpeg -i video.mp4
...
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video.mp4':
Metadata:
major_brand : isom
minor_version : 1
compatible_brands: isomavc1
creation_time : 2010-01-24 00:55:16
Duration: 00:00:35.08, start: 0.000000, bitrate: 354 kb/s
Stream #0.0(und): Video: h264 (High), yuv420p, 640x360 [PAR 1:1 DAR 16:9], 597 kb/s, 25 fps, 25 tbr, 25k tbn, 50 tbc
Metadata:
creation_time : 2010-01-24 00:55:16
Stream #0.1(und): Audio: aac, 44100 Hz, stereo, s16, 109 kb/s
Metadata:
creation_time : 2010-01-24 00:55:17
At least one output file must be specified
我如何获得高度=640,宽度=360?看看大多数格式的句柄
如果您正在寻找解析ffmpeg输出的方法,请使用regexp\d+x\d+
使用perl的示例:
$ ./ffmpeg -i test020.3gp 2>&1 | perl -lane 'print $1 if /(\d+x\d+)/'
176x120
使用python的示例(不完美):
[][][][][][][]176x120][]
Python一行程序没有perl一行程序那么吸引人:-)根据上面Fredrik的提示,下面是我如何使用MediaInfo()实现的: 在python中有一个粗略的解决方案:
import subprocess, re
pattern = re.compile(r'Stream.*Video.*([0-9]{3,})x([0-9]{3,})')
def get_size(pathtovideo):
p = subprocess.Popen(['ffmpeg', '-i', pathtovideo],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
match = pattern.search(stderr)
if match:
x, y = map(int, match.groups()[0:2])
else:
x = y = 0
return x, y
但是,假设它是3位x 3位(即854x480),则需要循环遍历可能的尺寸长度,例如(1280x720):
并检查match在每个步骤中是否返回None:
for pattern in possible_patterns:
match = pattern.search(stderr)
if match!=None:
x, y = map(int, match.groups()[0:2])
break
if match == None:
print "COULD NOT GET VIDEO DIMENSIONS"
x = y = 0
return '%sx%s' % (x, y)
可能会更漂亮,但效果不错 坏(\d+x\d+)
好([0-9]{2,}x[0-9]+)
无re模块
out = error_message.split() # make a list from resulting error string
out.reverse()
for index, item in enumerate(out): # extract the item before item= "[PAR"
if item == "[PAR": #
dimension_string = out[i+1] #
video_width, video_height = dimension_string.split("x")
编辑:不是一个好答案,因为并非所有视频都有“PAR”信息:(回答此问题的最佳方式是ffmpeg开发人员准确解释ffmpeg输出的格式,以及我们是否可以一致地假设大小位于其中的指定上下文中。在此之前,我们只能通过示例猜测格式通常是什么 这是我的尝试。与这些“一行程序”相比,这是冗长的,但那是因为我想知道为什么它最终失败了
import subprocess
def get_video_size(video_filename):
"""Returns width, height of video using ffprobe"""
# Video duration and hence start time
proc = subprocess.Popen(['ffprobe', video_filename],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
res = proc.communicate()[0]
# Check if ffprobe failed, probably on a bad file
if 'Invalid data found when processing input' in res:
raise ValueError("Invalid data found by ffprobe in %s" % video_filename)
# Find the video stream
width_height_l = []
for line in res.split("\n"):
# Skip lines that aren't stream info
if not line.strip().startswith("Stream #"):
continue
# Check that this is a video stream
comma_split = line.split(',')
if " Video: " not in comma_split[0]:
continue
# The third group should contain the size and aspect ratio
if len(comma_split) < 3:
raise ValueError("malform video stream string:", line)
# The third group should contain the size and aspect, separated
# by spaces
size_and_aspect = comma_split[2].split()
if len(size_and_aspect) == 0:
raise ValueError("malformed size/aspect:", comma_split[2])
size_string = size_and_aspect[0]
# The size should be two numbers separated by x
width_height = size_string.split('x')
if len(width_height) != 2:
raise ValueError("malformed size string:", size_string)
# Cast to int
width_height_l.append(map(int, width_height))
if len(width_height_l) > 1:
print "warning: multiple video streams found, returning first"
return width_height_l[0]
导入子流程
def get_video_大小(视频文件名):
“”“使用ffprobe返回视频的宽度、高度”“”
#视频持续时间和开始时间
proc=subprocess.Popen(['ffprobe',video_filename],
stdout=subprocess.PIPE,stderr=subprocess.stdout)
res=proc.communicate()[0]
#检查ffprobe是否失败,可能是在错误的文件上
如果res中的“处理输入时发现无效数据”:
raise VALUERROR(“ffprobe在%s”%video\u filename中找到无效数据)
#查找视频流
宽度\高度\ l=[]
对于res.split(“\n”)中的行:
#跳过不是流信息的行
如果不是line.strip().startswith(“Stream#”):
持续
#检查这是一个视频流
逗号_split=line.split(',')
如果“视频:”不以逗号分隔[0]:
持续
#第三组应包含大小和纵横比
如果len(逗号分割)<3:
raise VALUERROR(“格式错误的视频流字符串:”,第行)
#第三组应该包含大小和纵横比,分开
#按空格
大小和纵横比=逗号分割[2]。分割()
如果len(大小和纵横比)==0:
raise VALUERROR(“格式错误的大小/方面:”,逗号分割[2])
大小\字符串=大小\和\方面[0]
#大小应该是由x分隔的两个数字
宽度\高度=大小\字符串。拆分('x')
如果len(宽度和高度)!=2:
raise VALUERROR(“格式错误的大小字符串:”,大小字符串)
#转换为整数
宽度\高度\ l.附加(映射(整数,宽度\高度))
如果长度(宽度和高度)大于1:
打印“警告:找到多个视频流,先返回”
返回宽度\u高度\u l[0]
使用ffprobe
示例1:使用键/变量名
示例2:仅宽度x高度
示例3:JSON
示例4:JSON压缩
示例5:XML
ffprobe-v error-select_streams v-show_entries stream=width,height-of xml input.mkv
选项的作用:
进行安静输出,但允许显示错误。不包括通常的通用FFmpeg输出信息,包括版本、配置和输入详细信息-v error
只需显示-show_entries stream=width,height
和width
流信息height
选项选择输出格式(默认格式、压缩格式、csv格式、平面格式、ini格式、json格式、xml格式)。有关每种格式的说明,请参阅,并查看其他格式选项-of
如果您的输入包含多个视频流,则可以添加此选项。-选择\u streams v:0
将仅选择第一个视频流。否则,您将获得与视频流一样多的v:0
和width
输出。height
可用于显示所有视频流的信息铰孔并避免JSON和XML输出中的空音频-选择\u streams v
信息流
- 有关更多信息,请参阅和
ffprobe
提供了一种检索视频文件数据的方法。我发现以下命令非常有用ffprobe-v quiet-print\u format json-show\u streams input video.xxx
,可以查看您可以签出的数据类型
然后我编写了一个函数,运行上述命令并返回视频文件的高度和宽度:
import subprocess
import shlex
import json
# function to find the resolution of the input video file
def findVideoResolution(pathToInputVideo):
cmd = "ffprobe -v quiet -print_format json -show_streams"
args = shlex.split(cmd)
args.append(pathToInputVideo)
# run the ffprobe process, decode stdout into utf-8 & convert to JSON
ffprobeOutput = subprocess.check_output(args).decode('utf-8')
ffprobeOutput = json.loads(ffprobeOutput)
# find height and width
height = ffprobeOutput['streams'][0]['height']
width = ffprobeOutput['streams'][0]['width']
return height, width
这是有帮助的,但我认为OP希望捕获python中的值。@Geoff这将提供所需的值,并且比这里显示的其他方法更可靠。它如何与python一起使用取决于用户。事实上,这对我帮助很大。谢谢。使用
子流程
包对ca进行搜索
非常容易解析p请检查输出。很抱歉听起来是否定的。-of json
以json格式返回数据,这在Python中更容易访问(避免使用正则表达式)。@SimonSteinberger编辑为提及json以及所有其他可用格式。当我测试时,此格式失败,因为流信息是stream#0:0:Video:mjpeg(MJPG/0x47504A4D),yuvj420p(pc,bt470bg/unknown/unknown),733x446[SAR 1:1 DAR 733:446],7516 kb/s,60 fps,60 tbr,60 tbn,60 tbc
,因此结果是[[[[]['0x47504',733x446'][][/code>这很好,但对m4v不起作用
$ echo 'Stream #0:0(eng): Video: mjpeg (jpeg / 0x6765706A), yuvj420p, 1280x720, 19939 kb/s, 30 fps, 30 tbr, 30 tbn, 30 tbc' | perl -lane 'print $1 if /(\d+x\d+)/'
> 0x6765706
$ echo 'Stream #0:0(eng): Video: mjpeg (jpeg / 0x6765706A), yuvj420p, 1280x720, 19939 kb/s, 30 fps, 30 tbr, 30 tbn, 30 tbc' | perl -lane 'print $1 if /([0-9]{2,}x[0-9]+)/'
> 1280x720
out = error_message.split() # make a list from resulting error string
out.reverse()
for index, item in enumerate(out): # extract the item before item= "[PAR"
if item == "[PAR": #
dimension_string = out[i+1] #
video_width, video_height = dimension_string.split("x")
import subprocess
def get_video_size(video_filename):
"""Returns width, height of video using ffprobe"""
# Video duration and hence start time
proc = subprocess.Popen(['ffprobe', video_filename],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
res = proc.communicate()[0]
# Check if ffprobe failed, probably on a bad file
if 'Invalid data found when processing input' in res:
raise ValueError("Invalid data found by ffprobe in %s" % video_filename)
# Find the video stream
width_height_l = []
for line in res.split("\n"):
# Skip lines that aren't stream info
if not line.strip().startswith("Stream #"):
continue
# Check that this is a video stream
comma_split = line.split(',')
if " Video: " not in comma_split[0]:
continue
# The third group should contain the size and aspect ratio
if len(comma_split) < 3:
raise ValueError("malform video stream string:", line)
# The third group should contain the size and aspect, separated
# by spaces
size_and_aspect = comma_split[2].split()
if len(size_and_aspect) == 0:
raise ValueError("malformed size/aspect:", comma_split[2])
size_string = size_and_aspect[0]
# The size should be two numbers separated by x
width_height = size_string.split('x')
if len(width_height) != 2:
raise ValueError("malformed size string:", size_string)
# Cast to int
width_height_l.append(map(int, width_height))
if len(width_height_l) > 1:
print "warning: multiple video streams found, returning first"
return width_height_l[0]
ffprobe -v error -show_entries stream=width,height -of default=noprint_wrappers=1 input.mp4
width=1280
height=720
ffprobe -v error -select_streams v -show_entries stream=width,height -of csv=p=0:s=x input.m4v
1280x720
ffprobe -v error -select_streams v -show_entries stream=width,height -of json input.mkv
{
"programs": [
],
"streams": [
{
"width": 1280,
"height": 720
}
]
}
ffprobe -v error -select_streams v -show_entries stream=width,height -of json=compact=1 input.mkv
{
"programs": [
],
"streams": [
{ "width": 1280, "height": 720 }
]
}
ffprobe -v error -select_streams v -show_entries stream=width,height -of xml input.mkv
<?xml version="1.0" encoding="UTF-8"?>
<ffprobe>
<programs>
</programs>
<streams>
<stream width="1280" height="720"/>
</streams>
</ffprobe>
import subprocess
import shlex
import json
# function to find the resolution of the input video file
def findVideoResolution(pathToInputVideo):
cmd = "ffprobe -v quiet -print_format json -show_streams"
args = shlex.split(cmd)
args.append(pathToInputVideo)
# run the ffprobe process, decode stdout into utf-8 & convert to JSON
ffprobeOutput = subprocess.check_output(args).decode('utf-8')
ffprobeOutput = json.loads(ffprobeOutput)
# find height and width
height = ffprobeOutput['streams'][0]['height']
width = ffprobeOutput['streams'][0]['width']
return height, width