Allow deleting failed in progress exports

This commit is contained in:
Nicolas Mowen 2024-06-04 06:31:51 -06:00
parent ea0292b911
commit 6fd5b2c8b7
2 changed files with 61 additions and 40 deletions

View File

@ -4,6 +4,7 @@ import logging
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Optional
import psutil
from flask import ( from flask import (
Blueprint, Blueprint,
current_app, current_app,
@ -14,6 +15,7 @@ from flask import (
from peewee import DoesNotExist from peewee import DoesNotExist
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from frigate.const import EXPORT_DIR
from frigate.models import Export, Recordings from frigate.models import Export, Recordings
from frigate.record.export import PlaybackFactorEnum, RecordingExporter from frigate.record.export import PlaybackFactorEnum, RecordingExporter
@ -140,6 +142,28 @@ def export_delete(id: str):
404, 404,
) )
files_in_use = []
for process in psutil.process_iter():
try:
if process.name() != "ffmpeg":
continue
flist = process.open_files()
if flist:
for nt in flist:
if nt.path.startswith(EXPORT_DIR):
files_in_use.append(nt.path.split("/")[-1])
except psutil.Error:
continue
logger.error(f"comparing {export.video_path.split('/')[-1]} to {files_in_use}")
if export.video_path.split("/")[-1] in files_in_use:
return make_response(
jsonify(
{"success": False, "message": "Can not delete in progress export."}
),
400,
)
Path(export.video_path).unlink(missing_ok=True) Path(export.video_path).unlink(missing_ok=True)
if export.thumb_path: if export.thumb_path:

View File

@ -109,43 +109,38 @@ export default function ExportCard({
"relative flex aspect-video items-center justify-center rounded-lg bg-black md:rounded-2xl", "relative flex aspect-video items-center justify-center rounded-lg bg-black md:rounded-2xl",
className, className,
)} )}
onMouseEnter={ onMouseEnter={isDesktop ? () => setHovered(true) : undefined}
isDesktop && !exportedRecording.in_progress onMouseLeave={isDesktop ? () => setHovered(false) : undefined}
? () => setHovered(true) onClick={isDesktop ? undefined : () => setHovered(!hovered)}
: undefined
}
onMouseLeave={
isDesktop && !exportedRecording.in_progress
? () => setHovered(false)
: undefined
}
onClick={
isDesktop || exportedRecording.in_progress
? undefined
: () => setHovered(!hovered)
}
> >
{hovered && ( {hovered && (
<> <>
<div className="absolute inset-0 z-10 rounded-lg bg-black bg-opacity-60 md:rounded-2xl" /> <div className="absolute inset-0 z-10 rounded-lg bg-black bg-opacity-60 md:rounded-2xl" />
<div className="absolute right-1 top-1 flex items-center gap-2"> <div className="absolute right-1 top-1 flex items-center gap-2">
<a {!exportedRecording.in_progress && (
className="z-20" <a
download className="z-20"
href={`${baseUrl}${exportedRecording.video_path.replace("/media/frigate/", "")}`} download
> href={`${baseUrl}${exportedRecording.video_path.replace("/media/frigate/", "")}`}
<Chip className="cursor-pointer rounded-md bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500"> >
<FaDownload className="size-4 text-white" /> <Chip className="cursor-pointer rounded-md bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500">
<FaDownload className="size-4 text-white" />
</Chip>
</a>
)}
{!exportedRecording.in_progress && (
<Chip
className="cursor-pointer rounded-md bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500"
onClick={() =>
setEditName({
original: exportedRecording.name,
update: "",
})
}
>
<MdEditSquare className="size-4 text-white" />
</Chip> </Chip>
</a> )}
<Chip
className="cursor-pointer rounded-md bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500"
onClick={() =>
setEditName({ original: exportedRecording.name, update: "" })
}
>
<MdEditSquare className="size-4 text-white" />
</Chip>
<Chip <Chip
className="cursor-pointer rounded-md bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500" className="cursor-pointer rounded-md bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500"
onClick={() => onClick={() =>
@ -159,15 +154,17 @@ export default function ExportCard({
</Chip> </Chip>
</div> </div>
<Button {!exportedRecording.in_progress && (
className="absolute left-1/2 top-1/2 z-20 h-20 w-20 -translate-x-1/2 -translate-y-1/2 cursor-pointer text-white hover:bg-transparent hover:text-white" <Button
variant="ghost" className="absolute left-1/2 top-1/2 z-20 h-20 w-20 -translate-x-1/2 -translate-y-1/2 cursor-pointer text-white hover:bg-transparent hover:text-white"
onClick={() => { variant="ghost"
onSelect(exportedRecording); onClick={() => {
}} onSelect(exportedRecording);
> }}
<FaPlay /> >
</Button> <FaPlay />
</Button>
)}
</> </>
)} )}
{exportedRecording.in_progress ? ( {exportedRecording.in_progress ? (