mtp/vidchk: write ffprobe metadata to file

This commit is contained in:
ed 2022-07-09 04:33:19 +02:00
parent ac49b0ca93
commit 204bfac3fa

View file

@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import json import json
import re
import sys import sys
import subprocess as sp import subprocess as sp
@ -14,6 +15,7 @@ except:
_ = r""" _ = r"""
inspects video files for errors and such inspects video files for errors and such
plus stores a bunch of metadata to filename.ff.json
usage: usage:
-mtp vidchk=t600,ay,p,bin/mtag/vidchk.py -mtp vidchk=t600,ay,p,bin/mtag/vidchk.py
@ -33,6 +35,29 @@ FAST = True # parse entire file at container level
# FAST = False # fully decode audio and video streams # FAST = False # fully decode audio and video streams
# warnings to ignore
harmless = re.compile("^Unsupported codec with id ")
def wfilter(lines):
return [x for x in lines if not harmless.search(x)]
def errchk(so, se, rc):
if rc:
err = (so + se).decode("utf-8", "replace").split("\n", 1)
err = wfilter(err) or err
return f"ERROR {rc}: {err[0]}"
if se:
err = se.decode("utf-8", "replace").split("\n", 1)
err = wfilter(err)
if err:
return f"Warning: {err[0]}"
return None
def main(): def main():
fp = sys.argv[1] fp = sys.argv[1]
zb = sys.stdin.buffer.read() zb = sys.stdin.buffer.read()
@ -46,6 +71,26 @@ def main():
except: except:
return "could not determine resolution" return "could not determine resolution"
# grab streams/format metadata + the final keyframe (and the next 2 seconds of frames after it)
zs = "ffprobe -hide_banner -v warning -of json -show_streams -show_format -show_packets -show_data_hash crc32 -read_intervals 999999%+2"
cmd = zs.encode("ascii").split(b" ") + [fsenc(fp)]
p = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE)
so, se = p.communicate()
# spaces to tabs, drops filesize from 69k to 48k
so = b"\n".join(
[
b"\t" * int((len(x) - len(x.lstrip())) / 4) + x.lstrip()
for x in (so or b"").split(b"\n")
]
)
with open(fsenc(f"{fp}.ff.json"), "wb") as f:
f.write(so)
err = errchk(so, se, p.returncode)
if err:
return err
if min(w, h) < 1080: if min(w, h) < 1080:
return "resolution too small" return "resolution too small"
@ -66,16 +111,7 @@ def main():
p = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE) p = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE)
so, se = p.communicate() so, se = p.communicate()
rc = p.returncode return errchk(so, se, p.returncode)
if rc:
err = (so + se).decode("utf-8", "replace").split("\n", 1)[0]
return f"ERROR {rc}: {err}"
if se:
err = se.decode("utf-8", "replace").split("\n", 1)[0]
return f"Warning: {err}"
return None
if __name__ == "__main__": if __name__ == "__main__":