Improve ffprobe executions

When running ffprobe, use `subprocess.run` rather than
`subprocess.Popen`.  This simplifies the handling that is needed to run
and process the outputs.  Here, filename parsing is also simplified by
explicitly removing the file extension with `os.path.splitext` and
forcing a single split into the camera name and the formatted date.
This commit is contained in:
Sean Vig 2021-05-21 23:35:25 -04:00 committed by Blake Blackshear
parent ebb6d348a3
commit a4e6d9ed9a
3 changed files with 48 additions and 62 deletions

View File

@ -72,13 +72,11 @@ class EventProcessor(threading.Thread):
if f in files_in_use or f in self.cached_clips: if f in files_in_use or f in self.cached_clips:
continue continue
camera = "-".join(f.split("-")[:-1]) basename = os.path.splitext(f)[0]
start_time = datetime.datetime.strptime( camera, date = basename.rsplit("-", maxsplit=1)
f.split("-")[-1].split(".")[0], "%Y%m%d%H%M%S" start_time = datetime.datetime.strptime(date, "%Y%m%d%H%M%S")
)
ffprobe_cmd = " ".join( ffprobe_cmd = [
[
"ffprobe", "ffprobe",
"-v", "-v",
"error", "error",
@ -86,14 +84,11 @@ class EventProcessor(threading.Thread):
"format=duration", "format=duration",
"-of", "-of",
"default=noprint_wrappers=1:nokey=1", "default=noprint_wrappers=1:nokey=1",
f"{os.path.join(CACHE_DIR,f)}", f"{os.path.join(CACHE_DIR, f)}",
] ]
) p = sp.run(ffprobe_cmd, capture_output=True)
p = sp.Popen(ffprobe_cmd, stdout=sp.PIPE, shell=True) if p.returncode == 0:
(output, err) = p.communicate() duration = float(p.stdout.decode().strip())
p_status = p.wait()
if p_status == 0:
duration = float(output.decode("utf-8").strip())
else: else:
logger.info(f"bad file: {f}") logger.info(f"bad file: {f}")
os.remove(os.path.join(CACHE_DIR, f)) os.remove(os.path.join(CACHE_DIR, f))
@ -113,10 +108,10 @@ class EventProcessor(threading.Thread):
else: else:
earliest_event = datetime.datetime.now().timestamp() earliest_event = datetime.datetime.now().timestamp()
# if the earliest event exceeds the max seconds, cap it # if the earliest event is more tha max seconds ago, cap it
max_seconds = self.config.clips.max_seconds earliest_event = max(
if datetime.datetime.now().timestamp() - earliest_event > max_seconds: earliest_event, datetime.datetime.now().timestamp() - max_seconds
earliest_event = datetime.datetime.now().timestamp() - max_seconds )
for f, data in list(self.cached_clips.items()): for f, data in list(self.cached_clips.items()):
if earliest_event - 90 > data["start_time"] + data["duration"]: if earliest_event - 90 > data["start_time"] + data["duration"]:

View File

@ -31,8 +31,7 @@ logger = logging.getLogger(__name__)
def get_frame_shape(source): def get_frame_shape(source):
ffprobe_cmd = " ".join( ffprobe_cmd = [
[
"ffprobe", "ffprobe",
"-v", "-v",
"panic", "panic",
@ -40,13 +39,10 @@ def get_frame_shape(source):
"-show_streams", "-show_streams",
"-of", "-of",
"json", "json",
'"' + source + '"', source,
] ]
) p = sp.run(ffprobe_cmd, capture_output=True)
p = sp.Popen(ffprobe_cmd, stdout=sp.PIPE, shell=True) info = json.loads(p.stdout)
(output, err) = p.communicate()
p_status = p.wait()
info = json.loads(output)
video_info = [s for s in info["streams"] if s["codec_type"] == "video"][0] video_info = [s for s in info["streams"] if s["codec_type"] == "video"][0]

View File

@ -66,13 +66,11 @@ class RecordingMaintainer(threading.Thread):
if f in files_in_use: if f in files_in_use:
continue continue
camera = "-".join(f.split("-")[:-1]) basename = os.path.splitext(f)[0]
start_time = datetime.datetime.strptime( camera, date = basename.rsplit("-", maxsplit=1)
f.split("-")[-1].split(".")[0], "%Y%m%d%H%M%S" start_time = datetime.datetime.strptime(date, "%Y%m%d%H%M%S")
)
ffprobe_cmd = " ".join( ffprobe_cmd = [
[
"ffprobe", "ffprobe",
"-v", "-v",
"error", "error",
@ -80,14 +78,11 @@ class RecordingMaintainer(threading.Thread):
"format=duration", "format=duration",
"-of", "-of",
"default=noprint_wrappers=1:nokey=1", "default=noprint_wrappers=1:nokey=1",
f"{os.path.join(RECORD_DIR,f)}", f"{os.path.join(RECORD_DIR, f)}",
] ]
) p = sp.run(ffprobe_cmd, capture_output=True)
p = sp.Popen(ffprobe_cmd, stdout=sp.PIPE, shell=True) if p.returncode == 0:
(output, err) = p.communicate() duration = float(p.stdout.decode().strip())
p_status = p.wait()
if p_status == 0:
duration = float(output.decode("utf-8").strip())
else: else:
logger.info(f"bad file: {f}") logger.info(f"bad file: {f}")
os.remove(os.path.join(RECORD_DIR, f)) os.remove(os.path.join(RECORD_DIR, f))