#!/usr/bin/env python3 import os, sys, subprocess, pathlib, logging, pprint # Static config DEBUG = False lang_undef = 'und' ffprobe_exec = 'ffprobe' # Env config if 'DEBUG' in os.environ: DEBUG = bool(os.environ['DEBUG']) if 'EXEC' in os.environ: ffprobe_exec = pathlib.Path(os.environ['EXEC']) # CLI config if len(sys.argv) < 2: print(f"Usage: {sys.argv[0]} input_file", file=sys.stderr) sys.exit(-1) # Logging if DEBUG: logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) else: logging.basicConfig(stream=sys.stderr, level=logging.WARN) logger = logging.getLogger(__name__) # Parse to array of dicts of stream data def ffprobe(path): streams = {} # ffprobe args = [ ffprobe_exec, '-hide_banner', '-show_streams', path ] logger.debug(f"ffprobe command: {args}") probe = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) logger.debug(f"ffprobe result: {probe}") data = probe.stdout.decode('utf-8') if probe.returncode != 0: logger.error(f"ffprobe error ({probe.returncode}): {probe.stderr.decode('utf-8')}") logger.debug(f"ffprobe stdout: {data}") sys.exit(probe.returncode) # Process streams stream = None for line in data.splitlines(): if line == "[STREAM]": logger.debug('Stream start') stream = {} elif line == "[/STREAM]": logger.debug('Stream end') i = len(streams) try: i = int(stream['index']) except ValueError: pass if i in streams: logger.error(f"Inconsistent stream index: {i}") logger.debug(f"Streams: {steams}\nNext stream: {stream}") continue streams[i] = stream steam = None elif stream is not None: logger.debug(f"\tStream data: {line}") try: (key, val) = line.split('=', 1) except ValueError: logger.error(f"Skipping unexpected stream data: {line}") continue stream[key] = val # Return the set of all parsed streams return streams # Execute streams = ffprobe(sys.argv[1]) if len(sys.argv) == 2: pprint.pp(streams) else: for (i, stream) in streams.items(): for key in sys.argv[2:]: if key in stream: print(f"{i}: {key}={stream[key]}") else: print(f"{i}: {key}=")