|
|
@@ -1,4 +1,4 @@
|
|
|
-import subprocess, logging
|
|
|
+import json, subprocess, logging
|
|
|
|
|
|
class Probe:
|
|
|
encoding = 'utf-8'
|
|
|
@@ -13,7 +13,7 @@ class Probe:
|
|
|
|
|
|
def probe(self, path):
|
|
|
self.logger.debug(f"Probing: {path}")
|
|
|
- streams = []
|
|
|
+ streams = {}
|
|
|
|
|
|
# Sanity
|
|
|
if not path.exists():
|
|
|
@@ -21,38 +21,30 @@ class Probe:
|
|
|
return streams
|
|
|
|
|
|
# ffprobe
|
|
|
- args = [ self.ffprobe_exec, '-hide_banner', '-show_streams', path ]
|
|
|
+ args = [ self.ffprobe_exec, '-hide_banner', '-show_streams', '-print_format', 'json', path ]
|
|
|
self.logger.debug(f"ffprobe command: {args}")
|
|
|
probe = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
self.logger.debug(f"ffprobe result: {probe}")
|
|
|
- data = probe.stdout.decode(self.encoding)
|
|
|
- if probe.returncode != 0:
|
|
|
- self.logger.error(f"ffprobe error ({probe.returncode}): {probe.stderr.decode(self.encoding)}")
|
|
|
- self.logger.debug(f"ffprobe stdout: {data}")
|
|
|
- return streams
|
|
|
+ try:
|
|
|
+ data = probe.stdout.decode(self.encoding)
|
|
|
+ streams = json.loads(data)['streams']
|
|
|
+ except:
|
|
|
+ pass
|
|
|
|
|
|
- # Parse streams
|
|
|
- prefix = None
|
|
|
- stream = None
|
|
|
- for line in data.splitlines():
|
|
|
- if line == "[STREAM]":
|
|
|
- stream = {}
|
|
|
- elif line == "[/STREAM]":
|
|
|
- streams.append(stream)
|
|
|
- steam = None
|
|
|
- elif line == "[SIDE_DATA]":
|
|
|
- prefix = 'SIDE_DATA'
|
|
|
- elif line == "[/SIDE_DATA]":
|
|
|
- prefix = None
|
|
|
- elif stream is not None:
|
|
|
- try:
|
|
|
- (key, val) = line.split('=', 1)
|
|
|
- if prefix is not None:
|
|
|
- key = f"{prefix}:{key}"
|
|
|
- except ValueError:
|
|
|
- self.logger.error(f"Skipping unexpected stream data ({path}): {line}")
|
|
|
- continue
|
|
|
- stream[key] = val
|
|
|
+ # Verify
|
|
|
+ err = None
|
|
|
+ if not probe or not hasattr(probe, 'returncode'):
|
|
|
+ err = 'Unknown'
|
|
|
+ elif probe.returncode != 0:
|
|
|
+ err = probe.returncode
|
|
|
+ elif not streams or len(streams) < 1:
|
|
|
+ err = f'Unable to parse stream data'
|
|
|
+ if err is not None:
|
|
|
+ eout = '<No output>'
|
|
|
+ if probe and hasattr(probe, 'stderr'):
|
|
|
+ eout = probe.stderr.decode('utf-8')
|
|
|
+ self.logger.error(f"ffprobe error ({path}): {err}\n{eout}")
|
|
|
+ return streams
|
|
|
|
|
|
# Return
|
|
|
return streams
|