From 7147f6385eaaee58a4dd9c0c83a67ccbb45672f0 Mon Sep 17 00:00:00 2001 From: data Date: Sun, 18 May 2025 20:45:56 +0200 Subject: [PATCH] =?UTF-8?q?FrontEnd=20erweitert,=20L=C3=B6schen=20Funktion?= =?UTF-8?q?=20f=C3=BCr=20Warteschlange,=20Kleinigkeiten=20bereinigt=20und?= =?UTF-8?q?=20nach=20Server=20start=20das=20auslesen=20der=20Pfade=20und?= =?UTF-8?q?=20den=20Autostart?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __main__.py | 2 ++ app/class_file_convert.py | 9 ++++-- app/class_file_path.py | 22 +++++++------ app/class_media_file.py | 15 +++++---- app/main_server.py | 42 +++++++++++++++++++----- client/icons/fehler-96.png | Bin 0 -> 1088 bytes client/icons/wait-100.png | Bin 0 -> 1491 bytes client/icons/wait.gif | Bin 0 -> 11870 bytes client/index.html | 4 +-- client/index_style.css | 57 +++++++++++++++++++++++++++++++++ client/media_conversion.js | 64 +++++++++++++++++++++++++++++++------ 11 files changed, 178 insertions(+), 37 deletions(-) create mode 100644 client/icons/fehler-96.png create mode 100644 client/icons/wait-100.png create mode 100644 client/icons/wait.gif diff --git a/__main__.py b/__main__.py index 96f0475..46721f8 100644 --- a/__main__.py +++ b/__main__.py @@ -1,9 +1,11 @@ import asyncio import logging +from platform import python_version from app.main_server import Server if __name__ == "__main__": + print(python_version()) obj_server = Server() try: diff --git a/app/class_file_convert.py b/app/class_file_convert.py index 910b3a6..46acf92 100755 --- a/app/class_file_convert.py +++ b/app/class_file_convert.py @@ -1,9 +1,13 @@ import logging import asyncio import time +from typing import TYPE_CHECKING from app.class_file_convert_read_out import Process from app.class_media_file_stat import Stat +if TYPE_CHECKING: + from app.class_media_file import Media + class Convert: def __init__(self, websocket, cfg, obj_path): self.yaml = cfg @@ -85,13 +89,13 @@ class Convert: obj.convert_end = time.time() obj_stat.save_stat(obj) - - def convert_cmd(self, obj): command_convert = [ "ffmpeg", "-y", "-i", obj.source_file, + # "-init_hw_device", "vaapi=va:/dev/dri/renderD128", "-map", "0:0", "-c:v", "libsvtav1", + #"-c:v", "av1_qsv", "-preset", "5", "-crf", "30", "-g", "240", @@ -119,6 +123,7 @@ class Convert: ]) command_convert.append(obj.target_file) + obj.cmd = command_convert return command_convert def snake_update(self): diff --git a/app/class_file_path.py b/app/class_file_path.py index 3789b2a..0e990b9 100755 --- a/app/class_file_path.py +++ b/app/class_file_path.py @@ -39,15 +39,15 @@ class Path: paths_extrat_dict = {"paths": paths} try: - with open(f"app/cfg/{self.yaml["path_file"]}", "w", encoding="utf8") as file: + with open(f"app/cfg/{self.yaml['path_file']}", "w", encoding="utf8") as file: yaml.dump(paths_extrat_dict, file, default_flow_style=False, indent=4) logging.info(f"{len(self.paths)} paths were saved to file") return 1 except FileNotFoundError: - logging.error(f"File {self.yaml["path_file"]} not found") + logging.error(f"File {self.yaml['path_file']} not found") return 0 except IOError: - logging.critical(f"Error file {self.yaml["path_file"]} maybe damaged") + logging.critical(f"Error file {self.yaml['path_file']} maybe damaged") return 0 # Achtung Abrufen aus Datei und neu einlesen der ffprobe Daten fehlt noch @@ -57,18 +57,20 @@ class Path: :return: True or False """ try: - with open(f"app/cfg/{self.yaml["path_file"]}", "r", encoding="utf8") as file: + with open(f"app/cfg/{self.yaml['path_file']}", "r", encoding="utf8") as file: list_paths = yaml.safe_load(file) - if len(list_paths) > 0: + count = sum(1 for v in list_paths.values() if v) + + if count > 0: paths = list_paths - logging.info(f"{len(paths)} paths were read from file") + logging.info(f"{count} paths were read from file") return 1 except FileNotFoundError: - logging.error(f"File {self.yaml["path_file"]} not found") + logging.error(f"File {self.yaml['path_file']} not found") return 0 except IOError: - logging.critical(f"Error file {self.yaml["path_file"]} maybe damaged") + logging.critical(f"Error file {self.yaml['path_file']} maybe damaged") return 0 def delete_path(self, obj_id:int): @@ -139,6 +141,8 @@ class Path: elif select == "s": return json_data.get("streams", []) + return "" + def get_with_ffprobe(self, path:str): try: path = path.strip() @@ -189,7 +193,7 @@ class Path: list_active_paths = {} for obj in self.paths.values(): - if obj.status is None: + if obj.status is None or obj.status == 1 or obj.status == 2 or obj.status == 3: list_active_paths.update({obj.id: obj.to_dict_active_paths()}) return {"data_queue": list_active_paths} diff --git a/app/class_media_file.py b/app/class_media_file.py index 132a9f2..5f18bed 100755 --- a/app/class_media_file.py +++ b/app/class_media_file.py @@ -1,4 +1,3 @@ -import logging import os import math import time @@ -9,6 +8,7 @@ class Media: def __init__(self, path, streams_video, streams_audio, streams_subtitle, streams_format): # misc self.id = int(f"{int(time.time() * 1000)}{str(Media._id_counter).zfill(3)}") + self.cmd : list = None # source self.source_file: str = path self.source_path: str = os.path.dirname(path) @@ -20,7 +20,7 @@ class Media: self.source_time: int = 0 # target - self.target_file: str = f"{path.rsplit(".", 1)[0]}.webm" + self.target_file: str = f"{path.rsplit('.', 1)[0]}.webm" self.target_file_name: str = os.path.basename(self.target_file) self.target_size: int = 0 @@ -54,8 +54,8 @@ class Media: count = 1 string = "" for video_stream in stream_list: - string += f"{video_stream.get("codec_type").capitalize()} {count}" if video_stream.get( - "codec_type") else "Format" + string += f"{video_stream.get('codec_type').capitalize()} {count}" if video_stream.get( + 'codec_type') else "Format" for key, value in video_stream.items(): string += f" -- {key}: {value}" @@ -96,7 +96,10 @@ class Media: # target "target_file_name": self.target_file_name, "target_file": self.target_file, - "target_size": self.target_size + "target_size": self.target_size, + + #process + "status": self.status } def to_dict_stat(self): @@ -155,7 +158,7 @@ class Media: days = round(seconds // (24 * 3600)) seconds %= (24 * 3600) if days and str_day is not None: - d = (f"{days} {str_day}") + d = f"{days} {str_day}" else: d = "" diff --git a/app/main_server.py b/app/main_server.py index c0755c8..f3058bf 100755 --- a/app/main_server.py +++ b/app/main_server.py @@ -3,6 +3,7 @@ import asyncio import websockets import json import logging +import shlex from asyncio import CancelledError from websockets import InvalidUpgrade, ConnectionClosed, ConnectionClosedError @@ -26,6 +27,15 @@ class Server: self.obj_path = Path(self.yaml) self.obj_convert = Convert(self, self.yaml, self.obj_path) + async def start_convert(self): + global var_convert_active + + if var_convert_active == False and self.yaml['autostart']: + await self.obj_convert.snake_waiting() + var_convert_active = True + else: + self.obj_convert.snake_update() + async def send_websocket(self, message): message_json = json.dumps(message) @@ -52,15 +62,12 @@ class Server: if data.get("data_path"): self.obj_path.receive_paths(data.get("data_path")) await self.send_websocket(self.obj_path.queue_path_to_dict()) - - if var_convert_active == False and self.yaml['autostart']: - await self.obj_convert.snake_waiting() - var_convert_active = True - else: - self.obj_convert.snake_update() + await self.start_convert() elif data.get("data_command"): - pass + if data["data_command"]["cmd"] == "delete": + self.obj_path.delete_path(data["data_command"]["id"]) + await self.send_websocket(self.obj_path.queue_path_to_dict()) elif data.get("data_message"): logging.info(f"Server hat Empfangen: {data.get('data_message')}") @@ -80,6 +87,10 @@ class Server: var_convert_active = value async def server_websocket(self): + # Bei Server Start einmal ausführen + self.obj_path.read_paths() + await self.start_convert() + server = await websockets.serve(self.handle_client, self.yaml['server_ip'], self.yaml['websocket_port']) logging.info(f"Websocket Server läuft auf IP: {self.yaml['server_ip']} Port: {self.yaml['websocket_port']}") await server.wait_closed() @@ -106,17 +117,32 @@ class Server: return web.json_response(obj_stat.read_stat()) + # noinspection PyUnusedLocal + async def handle_cmd(self, request): + command = self.obj_convert.active_tasks # deine oben gepostete Funktion + + html = "" + + for obj in command: + # ffmpeg-Befehl als String (mit Shell-Escapes, falls Leerzeichen etc.) + cmd_str = " ".join([shlex.quote(arg) for arg in obj.cmd]) + + html += f"{cmd_str}

" + + return web.Response(text=html, content_type="text/html") + async def server_http(self): app = web.Application() app.router.add_get("/", self.handle_index) app.router.add_get("/api/ip", self.handle_ip) app.router.add_get("/api/stats", self.handle_stat) + app.router.add_get("/api/cmd", self.handle_cmd) app.router.add_static("/client/", path="./client", name="client") runner = web.AppRunner(app) await runner.setup() site = web.TCPSite(runner, "0.0.0.0", self.yaml["webserver_port"]) await site.start() - logging.info(f"HTTP Server läuft auf Port {self.yaml["webserver_port"]}") + logging.info(f"HTTP Server läuft auf Port {self.yaml['webserver_port']}") # Start Server ----------------------------------------------------------------------------------------------------- diff --git a/client/icons/fehler-96.png b/client/icons/fehler-96.png new file mode 100644 index 0000000000000000000000000000000000000000..10968a6eedeb9c7152a44eda0a2bf1539880b1c7 GIT binary patch literal 1088 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9GG!XV7ZFl&wk0|WCX zPZ!6KiaBrRczc98N*vGUKL5kXL_RZYS!}Q&w@~ivPVex%rcG1igeL07NO-0+vUzz4 zY0Q`wI8BPn_Qk@7l4ry&F7n{%YPogAjXN`NLT%yth1W_i?MXj3=lFm2`_JYboooEx z_`~kcXKm&9fo?zo4Xlc>-s*GjD$Vu%yUtE3E$-^$B36?#d;WPo@A;>3Kb_-X3&RdG z34@=-iW&YLHmiLk+N>4VP32IpU$;f*>f;g>lV=w@Hk*61Eyxx&dBYiM8+Y7sSJ>V! zm+i%!w!Zpk#U<72p>S@Wjy;2!uZ@l8*B!FVFQa~MQm?NQ-LhJ4yYhmG6LOE-?ElZ- zaQ1?S$GTS^t)s1fPFl?nr4?^2xg}&}Sy9Hys<%%r1Z}-_a^ccfTPHhvU(Hf)pSJ3{ zAD`~lhBBj!l|dlsuOR75TQ;YC57WB4Gx_4GyR(^fr>>ow?p55vcx8I3vv+Ft^PQh^ z5*d2iH!WDYY3t`d4|Nh5#QRblfHLW)FY+WZteyJuLeR}yH_K`^8#MH3>2C?yR#p~P z*~%ER)~|Wmse5ntlqva295_4ciYVKIO=@)pyXV?2H{)V{vEG;S+3}gyvwj?WSH?HT zSCFk>d7iTX`-At*!H%)=(!O^7^%}fO| zzydb~^?4Hhc&#yHwD9!q&D*s9U6&}^hi_Fqjf@s9V1d_hx;zhR{kIe{S~z;An%uPi z;>OMV*`g7}WCJrQ{o8w}ymGu6>oa#Gv8j?}tKR4ZK^geAqm< zX5T)$4gt0gxf(t}3}%;uG}Enr=G4k_39}h2Za>9&z%NScZI1f9@|NCF^>I`rl;lL)Yg> z=J+h@lr~gjPcYP-x^nK8jyAK<6t;+fV%KH=XLYV#a98w}XMO1RlOYe^Gu$^74sSHw zawX@jP1qc5o&}pKc2_b+IC_U>q*o@+GXTn8&seGT)@E;dH=I**Rnk3m_a|nx`g%vZ z-q^lkVCuQx7ZqUl_RHVE#}0vVvO1?0|N4|8_1zZ&wyk+UHx3vIVCg!0BBI? Ang9R* literal 0 HcmV?d00001 diff --git a/client/icons/wait-100.png b/client/icons/wait-100.png new file mode 100644 index 0000000000000000000000000000000000000000..b2143c9008ebd211bd10b6ba19895ab364dfe413 GIT binary patch literal 1491 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 literal 0 HcmV?d00001 diff --git a/client/index.html b/client/index.html index 1f5f893..02f4298 100755 --- a/client/index.html +++ b/client/index.html @@ -3,7 +3,7 @@ - Webm VCC + Webm VC @@ -24,7 +24,7 @@
-

Warteschleife

+

Warteschlange

diff --git a/client/index_style.css b/client/index_style.css index 82cb1a4..69f4ddc 100755 --- a/client/index_style.css +++ b/client/index_style.css @@ -140,10 +140,66 @@ nav button:hover { gap: 1rem; } +.queue_wait-card { + display: flex; + flex-direction: column; + height: 80%; + background-color: #1f1f1f; + padding: 1rem; + border-radius: 10px; + color: #eee; +} + +.card_wait-inner { + display: flex; + flex-direction: column; + height: 100%; +} + +.card-inner { + display: flex; + flex-direction: column; + height: 100%; +} + +#menu_wait { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: auto; /* ← Schiebt das Ding ganz nach unten */ +} + + #queue h2 { margin-top: 0; } +.conversion_wait_icons { + width: 25px; + height: auto; + cursor: pointer; +} + +.status_icons { + width: 25px; + height: auto; +} + +#menu_wait { + display: flex; + justify-content: space-between; /* Abstand dazwischen */ + align-items: center; /* Vertikal zentriert, optional */ + margin-top: auto; /* ← Schiebt das Ding ganz nach unten */ +} + +.links { + width: 25px; +} + +.rechts { + width: 25px; +} + /* === Statistik-Bereich === */ #statistics { padding: 1rem; @@ -159,6 +215,7 @@ nav button:hover { height: auto; } + .conversion_url { font-size: 0.7rem; text-align: center; diff --git a/client/media_conversion.js b/client/media_conversion.js index 24cd49b..06f2caa 100755 --- a/client/media_conversion.js +++ b/client/media_conversion.js @@ -4,6 +4,7 @@ let videoActive = [] let videoQueue = [] +let ws = null async function getServerConfig() { const response = await fetch('/api/ip'); @@ -20,13 +21,14 @@ getServerConfig() const externWebsocketUrl = data.extern_websocket_url; const websocketHttps = data.websocket_https + let connect; if (websocketHttps === 1){ connect = `wss://${externWebsocketUrl}` } else { connect = `ws://${externWebsocketUrl}` } - const ws = new WebSocket(connect); + ws = new WebSocket(connect); ws.onopen = function() { console.log("WebSocket ist geöffnet"); @@ -41,6 +43,7 @@ getServerConfig() if (packet.data_flow !== undefined){ updateVideoElement(packet); } else if(packet.data_convert !== undefined){ + deleteVideoElement(packet) createVideoElement(packet); } else if(packet.data_queue !== undefined){ createWaitingSnake(packet); @@ -62,6 +65,29 @@ getServerConfig() console.error('Error fetching settings:', error); }); +function sendCommand(command, id){ + if (ws && ws.readyState === WebSocket.OPEN) { + const payload = {"data_command": {"cmd": command, "id": id}}; + + ws.send(JSON.stringify(payload)); + } else { + console.warn("WebSocket ist nicht verbunden") + } +} + +function deleteVideoElement(packet) { + for (let key in videoActive){ + if (!(key in packet.data_convert)){ + const elem = document.getElementById(key); + if(elem){ + elem.remove(); + } + + delete videoActive[key]; + } + } + } + function createVideoElement(packet){ const active_Conversions = document.getElementById('active-conversions'); @@ -88,10 +114,7 @@ function createVideoElement(packet){
Speed: 0
Verbleibend: 0
Zeit: 0
-
- -
- Quelle: ${video.key}
+
`; @@ -101,23 +124,44 @@ function createVideoElement(packet){ }); } +function deepEqual(dict1, dict2) { + return JSON.stringify(dict2) === JSON.stringify(dict2); +} + function createWaitingSnake(packet){ const queue = document.getElementById('queue'); Object.keys(packet.data_queue).forEach(key => { const video = packet.data_queue[key]; + if(!deepEqual(videoActive[key], video)){ + const elem = document.getElementById(key); + if(elem){ + elem.remove(); + delete videoQueue[key]; + } + } + if(!videoQueue[key]){ const card = document.createElement('div'); - card.className = 'queue-card'; + card.className = 'queue_wait-card'; card.id = key + if(video.status === 1 || video.status === 2){ + status_img = `` + } else if(video.status === 3) { + status_img = `` + } else { + status_img = `` + } + card.innerHTML = ` - -
+

${video.source_file_name}

-
-
Quelle: ${video.key}
+
`;