我正在尝试制作一个简单的功能来包裹FFProbe ,并且大多数数据都可以正确检索。
问题是,使用Windows命令提示符和Windows的Git Bash实际将字符串实际打印到命令行时,输出出现乱和订单。
一些歌曲(特别是文件Imagine Dragons - Hit Parade_ Best of the Dance Music Charts80 - Beazz - Lime (Extended Mix).flac
(缺少元数据。我不知道为什么,但是词典以下功能返回的函数为空。
ffprobe将其结果输出到stderr
,可以将其输送到subprocess.PIPE
,解码和解析。我选择了解析位的正则罚款。
这是下面我代码的纤细版本,因为输出查看GitHub Gist。
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import os
from glob import glob
from re import findall, MULTILINE
from subprocess import Popen, PIPE
def glob_from(path, ext):
"""Return glob from a directory."""
working_dir = os.getcwd()
os.chdir(path)
file_paths = glob("**/*." + ext)
os.chdir(working_dir)
return file_paths
def media_metadata(file_path):
"""Use FFPROBE to get information about a media file."""
stderr = Popen(("ffprobe", file_path), shell=True, stderr=PIPE).communicate()[1].decode()
metadata = {}
for match in findall(r"(w+)s+:s(.+)$", stderr, MULTILINE):
metadata[match[0].lower()] = match[1]
return metadata
if __name__ == "__main__":
base = "C:/Users/spike/Music/Deezloader"
for file in glob_from(base, "flac"):
meta = media_metadata(os.path.join(base, file))
title_length = meta.get("title", file) + " - " + meta.get("length", "000")
print(title_length)
输出要点输出RAW
我不明白为什么只有在使用Python的print
函数打印到控制台时,输出(有效地从正则表达式检索到弦乐(才会出现混乱。我如何构建字符串以打印,串联,逗号限制的参数,无论如何都无关紧要。
我最终以歌曲的长度和歌曲名称第二,但两者之间没有空间。由于某种原因,仪表板悬而未决。基于以前的代码中的打印语句,格式应为Title - 000
({title} - {length}
(,但输出看起来更像000Title -
。为什么?
我通过我相关问题中接受的答案解决了这一点。
我忘记了每条线末端的返回马车。提供的解决方案如下:
- 在子过程呼叫中使用
universal_newlines=True
。-
stderr = Popen(("ffprobe", file_path), shell=True, stderr=PIPE, universal_newlines=True).communicate()[1]
-
-
从
stderr
剥离围绕线的空格。-
*.communicate()[1].decode().rstrip()
最终剥离所有空格。 -
*.communicate()[1].decode().strip()
剥离所有Wightspace。 -
*.communicate()[1].decode()[:-2]
删除最后两个字符。
-
-
吞咽
r
在正则模式中。-
findall(r"(w+)s+:s(.+)r$", stderr, MULTILINE)
-
这都非常有用,但是我没有使用这些建议。
我不知道FFProbe为Stdout提供JSON输出,但确实如此。代码下面的代码。
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
from json import loads
from subprocess import check_output, DEVNULL, PIPE
def arg_builder(args, kwargs, defaults={}):
"""Build arguments from `args` and `kwargs` in a shell-lexical manner."""
for key, val in defaults.items():
kwargs[key] = kwargs.get(key, val)
args = list(args)
for arg, val in kwargs.items():
if isinstance(val, bool):
if val:
args.append("-" + arg)
else:
args.extend(("-" + arg, val))
return args
def run_ffprobe(file_path, *args, **kwargs):
"""Use FFPROBE to get information about a media file."""
return loads(check_output(("ffprobe", arg_builder(args, kwargs, defaults={"show_format": True}),
"-of", "json", file_path), shell=True, stderr=DEVNULL))
您可能还可以从arg_builder()
中获得一些用途。它不是完美的,但对于简单的外壳命令来说已经足够了。这不是白痴的证据,它是用几个孔编写的,假设程序员不会破坏任何东西。