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

View File

@ -31,8 +31,7 @@ logger = logging.getLogger(__name__)
def get_frame_shape(source):
ffprobe_cmd = " ".join(
[
ffprobe_cmd = [
"ffprobe",
"-v",
"panic",
@ -40,13 +39,10 @@ def get_frame_shape(source):
"-show_streams",
"-of",
"json",
'"' + source + '"',
source,
]
)
p = sp.Popen(ffprobe_cmd, stdout=sp.PIPE, shell=True)
(output, err) = p.communicate()
p_status = p.wait()
info = json.loads(output)
p = sp.run(ffprobe_cmd, capture_output=True)
info = json.loads(p.stdout)
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:
continue
camera = "-".join(f.split("-")[:-1])
start_time = datetime.datetime.strptime(
f.split("-")[-1].split(".")[0], "%Y%m%d%H%M%S"
)
basename = os.path.splitext(f)[0]
camera, date = basename.rsplit("-", maxsplit=1)
start_time = datetime.datetime.strptime(date, "%Y%m%d%H%M%S")
ffprobe_cmd = " ".join(
[
ffprobe_cmd = [
"ffprobe",
"-v",
"error",
@ -80,14 +78,11 @@ class RecordingMaintainer(threading.Thread):
"format=duration",
"-of",
"default=noprint_wrappers=1:nokey=1",
f"{os.path.join(RECORD_DIR,f)}",
f"{os.path.join(RECORD_DIR, f)}",
]
)
p = sp.Popen(ffprobe_cmd, stdout=sp.PIPE, shell=True)
(output, err) = p.communicate()
p_status = p.wait()
if p_status == 0:
duration = float(output.decode("utf-8").strip())
p = sp.run(ffprobe_cmd, capture_output=True)
if p.returncode == 0:
duration = float(p.stdout.decode().strip())
else:
logger.info(f"bad file: {f}")
os.remove(os.path.join(RECORD_DIR, f))