Created
March 26, 2021 13:37
-
-
Save hhsprings/3672d2ca575dd49d65cb3cf5d6b7f1ed to your computer and use it in GitHub Desktop.
nearly equals to "for i in * ; do ffpprobe -hide_banner $i ; done" with a few extra values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
from __future__ import unicode_literals | |
import sys | |
import subprocess | |
if hasattr("", "decode"): | |
_encode = lambda s: s.encode(sys.getfilesystemencoding()) | |
else: | |
_encode = lambda s: s | |
def _str(s): | |
return s.encode(sys.getfilesystemencoding(), errors="xmlcharrefreplace").decode( | |
sys.getfilesystemencoding()) | |
def _filter_args(*cmd): | |
""" | |
do filtering None, and do encoding items to bytes | |
(in Python 2). | |
""" | |
return list(map(_encode, filter(None, *cmd))) | |
def check_call(*popenargs, **kwargs): | |
""" | |
Basically do simply forward args to subprocess#check_call, but this | |
does two things: | |
* It does encoding these to bytes in Python 2. | |
* It does omitting `None` in *cmd. | |
""" | |
cmd = kwargs.get("args") | |
if cmd is None: | |
cmd = popenargs[0] | |
subprocess.check_call( | |
_filter_args(cmd), **kwargs) | |
def check_stderroutput(*popenargs, **kwargs): | |
""" | |
Unfortunately, ffmpeg and ffprobe throw out the information | |
we want into the standard error output, and subprocess.check_output | |
discards the standard error output. This function is obtained by | |
rewriting subprocess.check_output for standard error output. | |
And this does two things: | |
* It does encoding these to bytes in Python 2. | |
* It does omitting `None` in *cmd. | |
""" | |
if 'stderr' in kwargs: | |
raise ValueError( | |
'stderr argument not allowed, it will be overridden.') | |
cmd = kwargs.get("args") | |
if cmd is None: | |
cmd = popenargs[0] | |
# | |
process = subprocess.Popen( | |
_filter_args(cmd), | |
stderr=subprocess.PIPE, | |
**kwargs) | |
stdout_output, stderr_output = process.communicate() | |
retcode = process.poll() | |
if retcode: | |
raise subprocess.CalledProcessError( | |
retcode, list(cmd), output=stderr_output) | |
return stderr_output | |
def _main(): | |
import re | |
import argparse | |
ap = argparse.ArgumentParser( | |
description="""ex.) | |
globffprobe.py '*.*' --search=' hevc ' --extract 'Duration *: *[\d:.]+'""") | |
ap.add_argument("pattern", nargs="+") | |
ap.add_argument("--search") | |
ap.add_argument("--negate", action="store_true") | |
ap.add_argument("--extract") | |
args = ap.parse_args() | |
from glob import glob | |
_test = lambda s: not args.negate | |
_extract = lambda s: s | |
if args.search: | |
if not args.negate: | |
_test = lambda s: re.search(args.search, s) | |
else: | |
_test = lambda s: not re.search(args.search, s) | |
if args.extract: | |
def _extract(s): | |
m = re.search(args.extract, s) | |
if m: | |
return m.group(0) | |
return "" | |
for pat in args.pattern: | |
for ifn in glob(pat): | |
cmdl = ["ffprobe", "-hide_banner", ifn] | |
eout = check_stderroutput(cmdl).decode("utf-8") | |
if _test(eout): | |
print("$ " + _str(ifn) + " | " + _str(_extract(eout))) | |
if __name__ == '__main__': | |
_main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ffprobeを、特に Windows の MSYS から unicode だらけファイル名群相手に使おうとすると鬱陶しい、てことに対する一つの処方箋。ArgumentParser に与えている description 内に使用例を入れといたが、それだけでわかる? かと思うんだけど…どうだろか。