|
|
@ -15,6 +15,10 @@ from global_funcs import * |
|
|
|
class NeedNVR(Exception): |
|
|
|
pass |
|
|
|
|
|
|
|
class ImageNoCreated(Exception): |
|
|
|
def __init__(self, msg): |
|
|
|
pass |
|
|
|
|
|
|
|
class Recorder: |
|
|
|
loop = asyncio.get_event_loop() |
|
|
|
def __init__(self, address, port, username, password, name = "", index = 0, name_overrides = {}): |
|
|
@ -155,6 +159,7 @@ class TranscodeTools: |
|
|
|
def __init__(self, tools_directory, transcode_directory, hide_checks = True, delete_temporary_files = False) -> None: |
|
|
|
self.delete_temporary_files = delete_temporary_files |
|
|
|
self.logger = create_logger(TranscodeTools.__name__) |
|
|
|
debug(self.logger) |
|
|
|
self.hide_checks = hide_checks |
|
|
|
self.tools_directory = tools_directory |
|
|
|
self.transcode_directory = transcode_directory |
|
|
@ -183,6 +188,20 @@ class TranscodeTools: |
|
|
|
self.logger.error("Cannot enabled transcode tools, have a errors on init, run config_parser with --no-hide-check parameters to more info") |
|
|
|
|
|
|
|
self.logger.info("Transcode tools " + "enabled" if self.enabled else "disabled") |
|
|
|
self.queue_encoding = asyncio.Queue() |
|
|
|
self.queue_images = asyncio.Queue() |
|
|
|
|
|
|
|
async def queue_encoding_task(self): |
|
|
|
self.logger.info("Start encoding queue") |
|
|
|
while True: |
|
|
|
await self.queue_encoding.get() |
|
|
|
await asyncio.sleep(1) |
|
|
|
|
|
|
|
async def queue_images_task(self): |
|
|
|
self.logger.info("Start images queue") |
|
|
|
while True: |
|
|
|
await self.queue_images.get() |
|
|
|
await asyncio.sleep(1) |
|
|
|
|
|
|
|
@property |
|
|
|
def check_exists_needed_files(self): |
|
|
@ -269,7 +288,7 @@ class TranscodeTools: |
|
|
|
if os.path.exists(out_file): |
|
|
|
return out_file |
|
|
|
else: |
|
|
|
raise Exception(f"{out_file} not be created") |
|
|
|
raise ImageNoCreated(f"{out_file} not be created") |
|
|
|
|
|
|
|
def deleteFile(self, source_file): |
|
|
|
try: |
|
|
@ -277,6 +296,12 @@ class TranscodeTools: |
|
|
|
except: |
|
|
|
pass |
|
|
|
|
|
|
|
async def processing_preview_task(self, file:File, nvr: NVR, ext = "webp", preview_pre_bytes = 1024 * 512): |
|
|
|
async def task(file, nvr, ext, preview_pre_bytes): |
|
|
|
await self.processing_preview(file, nvr, ext, preview_pre_bytes) |
|
|
|
|
|
|
|
self.queue_images.put_nowait(asyncio.create_task(task(file, nvr, ext, preview_pre_bytes))) |
|
|
|
|
|
|
|
async def processing_preview(self, file:File, nvr: NVR, ext = "webp", preview_pre_bytes = 1024 * 512): |
|
|
|
raw_file = file.previewPath(self.transcode_directory) |
|
|
|
preview_file = f"{raw_file}.{ext}" |
|
|
@ -303,6 +328,7 @@ class TranscodeTools: |
|
|
|
|
|
|
|
if not os.path.exists(raw_file) or os.path.getsize(raw_file) == 0: |
|
|
|
try: |
|
|
|
await nvr.login() |
|
|
|
async with asyncio.timeout(10): |
|
|
|
self.logger.info(f"download new preview {preview_file}") |
|
|
|
async with aiofiles.open(raw_file, "wb") as raw: |
|
|
@ -319,14 +345,24 @@ class TranscodeTools: |
|
|
|
raw_file_avi = await self.h264toavi(raw_file) |
|
|
|
if self.delete_temporary_files: |
|
|
|
self.deleteFile(raw_file) |
|
|
|
return await self.anytoimage(raw_file_avi, preview_file, self.delete_temporary_files) |
|
|
|
|
|
|
|
async def processing_safe(self, status: TranscodeStatus, file:File, nvr: NVR, reCreate:bool = False): |
|
|
|
try: |
|
|
|
await self.processing_mp4(status, file, nvr, reCreate) |
|
|
|
except Exception as e: |
|
|
|
traceback.print_exc() |
|
|
|
self.statuses[status.b64].error = str(e) |
|
|
|
return await self.anytoimage(raw_file_avi, preview_file, self.delete_temporary_files) |
|
|
|
except ImageNoCreated: |
|
|
|
clear_from_storage() |
|
|
|
self.logger.warning("Redownload with more size") |
|
|
|
return await self.processing_preview(file, nvr, ext, preview_pre_bytes * 2) |
|
|
|
|
|
|
|
async def processing_safe(self, status: TranscodeStatus, file:File, nvr: NVR, reCreate:bool = False): |
|
|
|
async def task(status: TranscodeStatus, file:File, nvr: NVR, reCreate): |
|
|
|
try: |
|
|
|
await self.processing_mp4(status, file, nvr, reCreate) |
|
|
|
except Exception as e: |
|
|
|
traceback.print_exc() |
|
|
|
self.statuses[status.b64].error = str(e) |
|
|
|
|
|
|
|
self.logger.info(f"Start enconding {file.filename_cleared}") |
|
|
|
self.queue_encoding.put_nowait(asyncio.create_task(task(status = status, file = file, nvr = nvr, reCreate = reCreate))) |
|
|
|
|
|
|
|
async def processing_mp4(self, status: TranscodeStatus, file:File, nvr: NVR, reCreate:bool = False): |
|
|
|
raw_file = file.localPath(self.transcode_directory) |
|
|
@ -334,16 +370,18 @@ class TranscodeTools: |
|
|
|
|
|
|
|
mp4_file = os.path.join(f"{raw_file}.avi.mp4") |
|
|
|
if os.path.exists(mp4_file) and os.path.getsize(mp4_file) != 0: |
|
|
|
nvr.logout() |
|
|
|
self.statuses[status.b64].outFile = mp4_file |
|
|
|
self.statuses[status.b64].done = True |
|
|
|
self.statuses[status.b64].outSize = os.path.getsize(mp4_file) |
|
|
|
return |
|
|
|
if not reCreate: |
|
|
|
nvr.logout() |
|
|
|
self.statuses[status.b64].outFile = mp4_file |
|
|
|
self.statuses[status.b64].done = True |
|
|
|
self.statuses[status.b64].outSize = os.path.getsize(mp4_file) |
|
|
|
return |
|
|
|
|
|
|
|
if not os.path.exists(raw_file) or os.path.getsize(raw_file) != file.size: |
|
|
|
if not os.path.exists(raw_file) or os.path.getsize(raw_file) != file.size or reCreate: |
|
|
|
self.logger.debug(f"save raw file to {raw_file}") |
|
|
|
async with aiofiles.open(raw_file, "wb") as raw: |
|
|
|
self.statuses[status.b64].total_h264_bytes = file.size |
|
|
|
await nvr.login() |
|
|
|
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) |
|
|
|