4

尝试使用 Hachoir 从视频文件中检索元数据。工作得相当好,除非使用 'get' 或类似方法返回宽度和高度值。

我以为会是:

metadata.get('width') 

但这会引发错误(对象没有“宽度”属性)。

当我运行以下命令时:

for data in sorted(metadata):
    if len(data.values ) > 0:
        print data.key, data.values[0].value

返回的只是来自“公共”组的信息。

当我使用:

metadata.exportPlaintext 

...返回“普通”、“视频流”和“音频流”的信息。我可以简单地解析生成的“文本”项并去掉高度和宽度值,但我宁愿尝试使用 metadata.get('width') 或类似方法正确地完成它。

查看源代码,我想我可以使用以下内容:

for key, metadata in metadata.__groups.iteritems():

遍历元数据中的 ._ 组,但随后会抛出“'AsfMetadata'对象没有属性' _groups' - 我确信不应该是这种情况,因为我认为 'AsfMetadata' 是 MultipleMetadata 的子类() 其中确实有这样一个变量。

可能遗漏了一些非常明显的东西。

4

2 回答 2

4

要从width x height在媒体文件中具有大小信息的第一个顶级元数据组获取,而不访问私有属性并且不解析文本输出,您可以使用file_metadata.iterGroups()

#!/usr/bin/env python
import sys
from itertools import chain

# $ pip install hachoir-{core,parser,metadata}
from hachoir_core.cmd_line import unicodeFilename
from hachoir_metadata import extractMetadata
from hachoir_parser import createParser

file_metadata = extractMetadata(createParser(unicodeFilename(sys.argv[1])))
it = chain([file_metadata], file_metadata.iterGroups())
print("%sx%s" % next((metadata.get('width'), metadata.get('height'))
                     for metadata in it
                     if metadata.has('width') and metadata.get('height')))

转换metadata成字典(非递归,即,如果需要,手动迭代组):

def metadata_as_dict(metadata):
    return {item.key: (len(item.values) > 1 and 
                       [v.value for v in item.values] or
                       item.values[0].value)
            for item in metadata if item.values}
于 2014-10-13T22:51:27.270 回答
4

对于 WMV 文件,这似乎不那么简单。我已将此类视频的元数据转换为defaultdict,现在获取图像宽度更直接:

from collections import defaultdict
from pprint import pprint

from hachoir_metadata import metadata
from hachoir_core.cmd_line import unicodeFilename
from hachoir_parser import createParser

# using this example http://archive.org/details/WorkToFishtestwmv
filename = './test_wmv.wmv' 
filename, realname = unicodeFilename(filename), filename
parser = createParser(filename)

# See what keys you can extract
for k,v in metadata.extractMetadata(parser)._Metadata__data.iteritems():
    if v.values:
        print v.key, v.values[0].value

# Turn the tags into a defaultdict
metalist = metadata.extractMetadata(parser).exportPlaintext()
meta = defaultdict(defaultdict)
for item in metalist:
    if item.endswith(':'):
        k = item[:-1]
    else:
        tag, value = item.split(': ')
        tag = tag[2:]
        meta[k][tag] = value

print meta['Video stream #1']['Image width'] # 320 pixels
于 2013-01-27T13:00:14.707 回答