diff --git a/backend/config_parser.py b/backend/config_parser.py index 79cfad5..f62cd72 100644 --- a/backend/config_parser.py +++ b/backend/config_parser.py @@ -9,6 +9,11 @@ from nvr_core import NVR from nvr_types import File import platform import aiofiles +import hashlib + +def uuid_from_string(string:str): + hex_string = hashlib.md5(string.encode("utf8")).hexdigest() + return uuid.UUID(hex=hex_string) def app_dir(): return os.path.dirname(os.path.abspath(__file__)) @@ -46,7 +51,7 @@ class Recorder: class TranscodeStatus: def __init__(self, b64) -> None: self.b64 = b64 - self.uuid = str(uuid.uuid4()) + self.uuid = str(uuid_from_string(b64)) self.h264 = 0 self.downloaded_h264_bytes = 0 self.total_h264_bytes = 0 @@ -164,7 +169,7 @@ class TranscodeTools: raise Exception("AVI not be created") async def avitomp4(self, source_file, delete_source_file = False): - exec_string = ["-y", "-i", source_file, f"{source_file}.mp4"] + exec_string = ["-y", "-i", source_file, "-movflags", "faststart", f"{source_file}.mp4"] print("execute", exec_string) proc = await asyncio.create_subprocess_exec("ffmpeg", *exec_string) await proc.communicate() @@ -179,25 +184,38 @@ class TranscodeTools: def deleteFile(self, source_file): os.remove(source_file) - async def processing(self, status: TranscodeStatus, file:File, nvr: NVR): + async def processing(self, status: TranscodeStatus, file:File, nvr: NVR, reCreate:bool = False): raw_file = os.path.join(self.transcode_directory, status.uuid + ".h264") - print("save raw file to", raw_file) - async with aiofiles.open(raw_file, "wb") as raw: - self.statuses[status.b64].total_h264_bytes = file.size - async for chunk in nvr.stream_file(file): - self.statuses[status.b64].downloaded_h264_bytes += len(chunk) - self.statuses[status.b64].h264 = round(100 * self.statuses[status.b64].downloaded_h264_bytes / self.statuses[status.b64].total_h264_bytes) - await raw.write(chunk) - print("raw file is downloaded") + + if not os.path.exists(raw_file) or os.path.getsize(raw_file) != file.size: + print("save raw file to", raw_file) + async with aiofiles.open(raw_file, "wb") as raw: + self.statuses[status.b64].total_h264_bytes = file.size + async for chunk in nvr.stream_file(file): + self.statuses[status.b64].downloaded_h264_bytes += len(chunk) + self.statuses[status.b64].h264 = round(100 * self.statuses[status.b64].downloaded_h264_bytes / self.statuses[status.b64].total_h264_bytes) + await raw.write(chunk) + print("raw file is downloaded") + else: + print("File already content on server") print("logout from nvr, he is not more needed") nvr.logout() self.statuses[status.b64].avi = 0 - avi_file = await self.h264toavi(raw_file) + avi_file = raw_file + ".avi" + if not os.path.exists(avi_file) or reCreate: + avi_file = await self.h264toavi(raw_file) + else: + print("file avi format already exitst") self.statuses[status.b64].avi = 100 + self.statuses[status.b64].mp4 = 0 - mp4_file = await self.avitomp4(avi_file) + mp4_file = avi_file + ".mp4" + if not os.path.exists(mp4_file) or reCreate: + mp4_file = await self.avitomp4(avi_file) + else: + print("file mp4 format already exists") self.statuses[status.b64].mp4 = 100 self.statuses[status.b64].outFile = mp4_file diff --git a/frontend/ang_dvrip/src/app/components/history/history.component.html b/frontend/ang_dvrip/src/app/components/history/history.component.html index 1ac520f..f98af52 100644 --- a/frontend/ang_dvrip/src/app/components/history/history.component.html +++ b/frontend/ang_dvrip/src/app/components/history/history.component.html @@ -18,7 +18,7 @@ Choose a date - + MM/DD/YYYY diff --git a/frontend/ang_dvrip/src/app/components/history/history.component.ts b/frontend/ang_dvrip/src/app/components/history/history.component.ts index d036c42..4d992ad 100644 --- a/frontend/ang_dvrip/src/app/components/history/history.component.ts +++ b/frontend/ang_dvrip/src/app/components/history/history.component.ts @@ -41,7 +41,7 @@ export class HistoryComponent implements OnInit { getHistory() { const params = this.route.snapshot.paramMap; this.dataSource = new MatTableDataSource(); - this.http.get(`api/history/${params.get('recorderId')}/${params.get('channelId')}/${this.selected_stream}?start_date=${this.prepareDate(this.start_date)}&end_date=${this.prepareDate(this.end_date)}`) + this.http.get(`api/history/${params.get('recorderId')}/${params.get('channelId')}/${this.selected_stream}?start_date=${this.baseUtils.prepareDate(this.start_date, true)}&end_date=${this.baseUtils.prepareDate(this.end_date, false)}`) .subscribe((a:any) => { this.dataSource = new MatTableDataSource(a['data']); }) @@ -58,14 +58,10 @@ export class HistoryComponent implements OnInit { break; } } + console.log(this.start_date, this.end_date); this.getHistory(); } - prepareDate(date: Date|null): string { - if (date == null) return ""; - return date.toISOString().replace("T", " ").split(".")[0]; - } - openTransCodeDialog(b64:string) { const dialog = this.dialog.open(TranscodeModalComponent, {data:{b64:b64, recorder_index:this.route.snapshot.paramMap.get('recorderId')}}); } diff --git a/frontend/ang_dvrip/src/app/utils/BaseUtils.ts b/frontend/ang_dvrip/src/app/utils/BaseUtils.ts index f58c309..f1affb3 100644 --- a/frontend/ang_dvrip/src/app/utils/BaseUtils.ts +++ b/frontend/ang_dvrip/src/app/utils/BaseUtils.ts @@ -5,4 +5,14 @@ export class BaseUtils { if (size > 1024) return `${Math.round(size / 1024)} Кб`; return `${size} Б` } + + static prepareDate(date: Date|null, beginDay: boolean = true): string { + if (date == null) return ""; + var d: Date = new Date(date.getTime() - date.getTimezoneOffset() * 60000) + + if (beginDay) + return d.toISOString().split("T")[0] + " 00:00:00"; + else + return d.toISOString().split("T")[0] + " 23:59:59"; + } }