diff --git a/app/main.py b/app/main.py index 796c276..ed3fed8 100755 --- a/app/main.py +++ b/app/main.py @@ -15,6 +15,18 @@ from fastapi.templating import Jinja2Templates import app.video_class as vc +# Settings +language = ["ger", "eng"] +subtitle_codec_blacklist = ["hdmv_pgs_subtitle", "dvd_subtitle"] +max_tasks = 2 + +# Globale Variablen +queue = asyncio.Queue() +read_output_task = None +video_files = {} +active_process = set() +active_tasks = set() +connected_clients = set() semaphore = threading.Semaphore(1) date = date.today() @@ -34,18 +46,12 @@ app = FastAPI() app.mount("/webs", StaticFiles(directory="app/webs"), name="webs") templates = Jinja2Templates(directory="app/templates") -queue = asyncio.Queue() -read_output_task = None +def obj_list(): + list_json = [] + for obj_video in video_files.values(): + list_json.append(obj_video.get_vars()) -# Settings -language = ["ger", "eng"] -subtitle_codec_blacklist = ["hdmv_pgs_subtitle", "dvd_subtitle"] -max_tasks = 2 - -video_files = {} -active_process = set() -active_tasks = set() -connected_clients = set() + return json.dumps({"list_video":list_json}) # Media ---------------------------------------------------------------------------------------------------------------- def get_video_information(media_path): @@ -117,10 +123,10 @@ def video_convert(obj): "ffmpeg", "-y", "-i", obj.source_file, "-map", "0:0", "-c:v", "libsvtav1", - "-preset", "5", - "-crf", "24", + "-preset", "8", + "-crf", "30", "-g", "240", - "-pix_fmt", "yuv420p", + "-pix_fmt", "yuv420p10le", "-svtav1-params", "tune=0:film-grain=8", ] @@ -154,25 +160,21 @@ def video_convert(obj): ) active_process.add(obj) - logging.info(f"{obj.file_name}") + obj.finished = 3 - print(obj.process.poll()) while obj.process.poll() is None: logging.info(f"{obj.file_name} ... Running") - time.sleep(30) - print(obj.process.poll()) + time.sleep(10) if obj.process.poll() == 0: obj.finished = 1 logging.info(f"Process Finished({obj.process.returncode}): {obj.file_name}") - json_data = json.dumps(obj.to_dict()) - loop.run_until_complete(queue.put(json_data)) + loop.run_until_complete(queue.put(obj.to_dict())) elif obj.process.poll() != 0: obj.finished = 2 logging.info(f"Process Failure({obj.process.returncode}): {obj.file_name}") - json_data = json.dumps(obj.to_dict()) - loop.run_until_complete(queue.put(json_data)) + loop.run_until_complete(queue.put(obj.to_dict())) active_process.discard(obj) active_tasks.discard(obj) @@ -182,10 +184,6 @@ def video_convert(obj): obj.finished = 2 logging.error(f"Convert Process Failure: {e}") - -#test = {"files":["/mnt/Storage/11 - Downloads - JDownloader/01 - Fertig/Star Trek: Deep Space Nine - S01E03 - Die Khon-Ma.mkv /mnt/Storage/11 - Downloads - JDownloader/01 - Fertig/Star Trek: Deep Space Nine - S01E04 - Unter Verdacht.mkv"]} -#get_video_information(test) - #UviCorn WebServer Teil #---------------------------------------------------------------------------------------------------------------------- def read_output(qu): @@ -196,25 +194,25 @@ def read_output(qu): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) + print(active_process) + while True: if not len(active_process): - loop.run_until_complete(asyncio.sleep(30)) # Keine aktiven Prozesse → kurze Pause + time.sleep(30) continue for obj in list(active_process): line_error = obj.process.stderr.read(1024) - if not line_error: - continue line_error_decoded = line_error.decode() - logging.info(f"Datenpaket {obj.file_name}: {line_error_decoded}") + logging.info(f"Data ffmpeg: {line_error_decoded}") obj.extract_convert_data(line_error_decoded) - json_data = json.dumps(obj.to_dict()) - # Verwende den Event-Loop, um die Daten in die asyncio Queue zu legen - loop.run_until_complete(qu.put(json_data)) + logging.info(f"Data Packet created: {obj.to_dict()}") + loop.run_until_complete(qu.put(obj.to_dict())) + @app.post("/") async def receive_video_file(data: dict): @@ -244,6 +242,8 @@ async def websocket_v(websocket: WebSocket): read_output_task = threading.Thread(target=read_output, args=(queue,)) read_output_task.start() + # await queue.put(obj_list()) + try: while True: message = await queue.get() # Warten auf neue Nachricht aus der Queue diff --git a/app/video_class.py b/app/video_class.py index 0fcfd1c..1d73674 100644 --- a/app/video_class.py +++ b/app/video_class.py @@ -1,3 +1,4 @@ +import json import logging import os import re @@ -11,7 +12,7 @@ class Video: self.source_file = path self.file_name = os.path.basename(self.source_file) self.duration = self.time_in_sec(video_streams[0]["tags"].get("DURATION" or "duration", "00:00:00")) - self.frame_rate = int(video_streams[0].get("r_frame_rate", "0/0").split("/")[0]) + self.frame_rate = self.frame_rate(video_streams) self.frames_max = self.frame_rate * self.duration self.output_file = f"{path.rsplit(".", 1)[0]}.webm" @@ -86,7 +87,7 @@ class Video: self.time_deque.append(self.time) self.time_estimated = self.duration - time_estimated - return { + data_packet = { "source": os.path.basename(self.source_file), "target": os.path.basename(self.output_file), "path": os.path.dirname(self.source_file), @@ -105,6 +106,11 @@ class Video: "time_remaining": self.time_remaining } + return json.dumps({"data_flow":data_packet}) + + def get_vars(self): + return json.dumps({"obj_list":vars(self)}) + def extract_convert_data(self, line_decoded): frame = re.findall(r"frame=\s*(\d+)", line_decoded) self.frame = int(frame[0]) if frame else 0 @@ -120,7 +126,7 @@ class Video: time = re.findall(r"time=\s*(\d+:\d+:\d+)", line_decoded) time_v = time[0] if time else "00:00:00" - self.time_in_sec(time_v) + self.time = self.time_in_sec(time_v) bitrate = re.findall(r"bitrate=\s*(\d+)", line_decoded) self.bitrate = self.convert_kb_mb(bitrate[0]) if bitrate else 0 @@ -160,6 +166,16 @@ class Video: else: return 0 + @staticmethod + def frame_rate(video_streams): + var_frame_rate = video_streams[0].get("r_frame_rate", "0/0").split("/") + if int(var_frame_rate[1]) > 0: + int_frame_rate = int(var_frame_rate[0]) / int(var_frame_rate[1]) + else: + int_frame_rate = 0 + + return int_frame_rate + @staticmethod def format_time(seconds): # Berechne die Anzahl der Tage, Stunden, Minuten und Sekunden diff --git a/app/webs/webs.js b/app/webs/webs.js index ae48cb0..cf030be 100644 --- a/app/webs/webs.js +++ b/app/webs/webs.js @@ -3,15 +3,28 @@ let videoQueue = {}; // Hier speichern wir alle laufenden Videos ws.onmessage = function(event) { try { - let message = JSON.parse(event.data); + let packet = JSON.parse(event.data); + console.log(packet); - // Falls das Video noch nicht existiert, erstelle ein neues Element - if (!videoQueue[message.id]) { - videoQueue[message.id] = createVideoElement(message.id, message.source, message.target, message.path); + if (packet.data_flow !== undefined) { + let message = packet.data_flow; + console.log(message); + + // Überprüfen, ob die erwarteten Felder existieren + if (message.id && message.source && message.target && message.path) { + // Falls das Video noch nicht existiert, erstelle ein neues Element + if (!videoQueue[message.id]) { + videoQueue[message.id] = createVideoElement(message.id, message.source, message.target, message.path); + } + + // Update der UI + updateVideoElement(message.id, message); + } else { + console.error("Fehlende Felder in der Nachricht", message); + } + } else { + console.error("Kein data_flow in der empfangenen Nachricht", packet); } - - // Update der UI - updateVideoElement(message.id, message); } catch (e) { console.error("Fehler beim Parsen der WebSocket-Nachricht:", e, event.data); }