diff --git a/arcane-vm-setup-unix.sh b/arcane-vm-setup-unix.sh new file mode 100644 index 0000000..d05012a --- /dev/null +++ b/arcane-vm-setup-unix.sh @@ -0,0 +1,42 @@ +#!/bin/bash +set -e +echo "=== Arcane VM Setup ===" +echo "Tu77ceu2zzvx!" | sudo -S apt-get update +echo "Tu77ceu2zzvx!" | sudo -S apt-get upgrade -y +curl -fsSL https://get.docker.com | sudo sh +echo "Tu77ceu2zzvx!" | sudo -S usermod -aG docker arcane +mkdir -p /opt/docker/projects +chown arcane:arcane /opt/docker/projects +mkdir -p /usr/local/lib/docker/cli-plugins +curl -SL https://github.com/docker/compose/releases/download/v2.29.2/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose +chmod +x /usr/local/lib/docker/cli-plugins/docker-compose +ENCRYPTION_KEY=$(openssl rand -hex 32) +JWT_SECRET=$(openssl rand -hex 32) +cat > /opt/docker-compose.yml << COMPOSEEOF +version: "3.8" +services: + arcane: + image: ghcr.io/getarcaneapp/manager:latest + container_name: arcane + ports: + - "3552:3552" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - arcane-data:/app/data + - /opt/docker/projects:/app/data/projects + environment: + - PROJECTS_DIRECTORY=/app/data/projects + - APP_URL=http://192.168.178.162:3552 + - PUID=1000 + - PGID=1000 + - ENCRYPTION_KEY=$ENCRYPTION_KEY + - JWT_SECRET=$JWT_SECRET + restart: unless-stopped +volumes: + arcane-data: +COMPOSEEOF +cd /opt +docker compose up -d +echo "=== Setup abgeschlossen ===" +echo "Arcane ist erreichbar unter: http://192.168.178.162:3552" +echo "Projects Directory: /opt/docker/projects" diff --git a/arcane-vm-setup.sh b/arcane-vm-setup.sh index ba78d58..6b420c3 100644 --- a/arcane-vm-setup.sh +++ b/arcane-vm-setup.sh @@ -1,62 +1,42 @@ #!/bin/bash -# Arcane VM Setup Script für Ubuntu VM -# Führe dies auf der Arcane VM aus - set -e - echo "=== Arcane VM Setup ===" - -# System aktualisieren -echo "System aktualisieren..." -apt-get update && apt-get upgrade -y - -# Docker installieren -echo "Installiere Docker..." -curl -fsSL https://get.docker.com | sh - -# User zu Docker-Gruppe hinzufügen -usermod -aG docker arcane - -# Verzeichnisse erstellen -mkdir -p /opt/docker/projects -chown arcane:arcane /opt/docker/projects - -# Docker Compose installieren -echo "Installiere Docker Compose..." +echo "Tu77ceu2zzvx!" | sudo -S apt-get update -y +echo "Tu77ceu2zzvx!" | sudo -S apt-get upgrade -y +curl -fsSL https://get.docker.com | sudo sh +echo "Tu77ceu2zzvx!" | sudo -S usermod -aG docker arcane +mkdir -p /home/arcane/projects +chown arcane:arcane /home/arcane/projects mkdir -p /usr/local/lib/docker/cli-plugins curl -SL https://github.com/docker/compose/releases/download/v2.29.2/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose chmod +x /usr/local/lib/docker/cli-plugins/docker-compose - -# Docker Compose Datei erstellen -cat > /opt/docker-compose.yml << 'EOF' -version: '3.8' +ENCRYPTION_KEY=$(openssl rand -hex 32) +JWT_SECRET=$(openssl rand -hex 32) +cat > /home/arcane/docker-compose.yml << COMPOSEEOF +version: "3.8" services: arcane: image: ghcr.io/getarcaneapp/manager:latest container_name: arcane ports: - - '3552:3552' + - "3552:3552" volumes: - /var/run/docker.sock:/var/run/docker.sock - arcane-data:/app/data - - /opt/docker/projects:/app/data/projects + - /home/arcane/projects:/app/data/projects environment: - PROJECTS_DIRECTORY=/app/data/projects - APP_URL=http://192.168.178.162:3552 - PUID=1000 - PGID=1000 - - ENCRYPTION_KEY=$(openssl rand -hex 32) - - JWT_SECRET=$(openssl rand -hex 32) + - ENCRYPTION_KEY=$ENCRYPTION_KEY + - JWT_SECRET=$JWT_SECRET restart: unless-stopped volumes: arcane-data: -EOF - -# Arcane starten -echo "Starte Arcane..." -cd /opt +COMPOSEEOF +cd /home/arcane docker compose up -d - -echo "=== Arcane VM Setup abgeschlossen ===" +echo "=== Setup abgeschlossen ===" echo "Arcane ist erreichbar unter: http://192.168.178.162:3552" -echo "Projects Directory: /opt/docker/projects" +echo "Projects Directory: /home/arcane/projects" diff --git a/create-docker-compose.sh b/create-docker-compose.sh new file mode 100644 index 0000000..00c3e8f --- /dev/null +++ b/create-docker-compose.sh @@ -0,0 +1,26 @@ +ENCRYPTION_KEY=$(openssl rand -hex 32) +JWT_SECRET=$(openssl rand -hex 32) +cat > /home/arcane/docker-compose.yml << EOF +version: '3.8' +services: + arcane: + image: ghcr.io/getarcaneapp/manager:latest + container_name: arcane + ports: + - '3552:3552' + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - arcane-data:/app/data + - /home/arcane/projects:/app/data/projects + environment: + - PROJECTS_DIRECTORY=/app/data/projects + - APP_URL=http://192.168.178.162:3552 + - PUID=1000 + - PGID=1000 + - ENCRYPTION_KEY=$ENCRYPTION_KEY + - JWT_SECRET=$JWT_SECRET + restart: unless-stopped +volumes: + arcane-data: +EOF +cat /home/arcane/docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml index cfd8c38..9d3d1e9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -90,6 +90,7 @@ services: - ./docker/worker:/app - ./udev:/app/udev - /dev:/dev:ro + - ./output:/output networks: - rippy-backend depends_on: diff --git a/docker/worker/Dockerfile b/docker/worker/Dockerfile index e271fe5..b7c568e 100644 --- a/docker/worker/Dockerfile +++ b/docker/worker/Dockerfile @@ -4,6 +4,10 @@ WORKDIR /app RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ + abcde \ + flac \ + ffmpeg \ + handbrake-cli \ && rm -rf /var/lib/apt/lists/* RUN pip install --no-cache-dir \ diff --git a/docker/worker/ripping.py b/docker/worker/ripping.py new file mode 100644 index 0000000..3de4cda --- /dev/null +++ b/docker/worker/ripping.py @@ -0,0 +1,86 @@ +import os +import subprocess +import re +from celery_app import celery_app + + +def get_progress_from_line(line: str) -> int: + """Extrahiert Fortschritt in Prozent aus HandBrake-Ausgabe.""" + match = re.search(r'(\d+\.\d+)%', line) + if match: + return int(float(match.group(1))) + return 0 + + +def run_handbrake(device_path: str, output_path: str) -> dict: + """Rippt eine DVD/Blu-ray mit HandBrakeCLI.""" + try: + cmd = [ + "HandBrakeCLI", + "--input", device_path, + "--output", output_path, + "--all", + "--progress", + "--preset", "Fast 1080p30" + ] + + process = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + bufsize=1 + ) + + for line in process.stdout: + progress = get_progress_from_line(line) + if progress > 0: + celery_app.send_task( + "worker.ripping.update_progress", + kwargs={ + "progress": progress, + "status": "ripping", + "message": f"Rippe Titel {progress}%" + } + ) + + process.wait() + + if process.returncode == 0: + return { + "status": "success", + "output_path": output_path, + "return_code": process.returncode + } + else: + return { + "status": "error", + "error": f"HandBrake failed with code {process.returncode}", + "return_code": process.returncode + } + + except Exception as e: + return { + "status": "error", + "error": str(e) + } + + +@celery_app.task(bind=True, name="worker.ripping.rip_dvd") +def rip_dvd(self, device_path: str, disc_id: str) -> dict: + """Rippt eine DVD mit HandBrake.""" + output_dir = f"/output/dvd/{disc_id}" + os.makedirs(output_dir, exist_ok=True) + output_path = f"{output_dir}/dvd_{disc_id}.mkv" + + return run_handbrake(device_path, output_path) + + +@celery_app.task(bind=True, name="worker.ripping.rip_bluray") +def rip_bluray(self, device_path: str, disc_id: str) -> dict: + """Rippt eine Blu-ray mit HandBrake.""" + output_dir = f"/output/bluray/{disc_id}" + os.makedirs(output_dir, exist_ok=True) + output_path = f"{output_dir}/bluray_{disc_id}.mkv" + + return run_handbrake(device_path, output_path) diff --git a/docker/worker/tasks.py b/docker/worker/tasks.py index 0bc557c..3677aee 100644 --- a/docker/worker/tasks.py +++ b/docker/worker/tasks.py @@ -1,15 +1,55 @@ import os +import subprocess from celery_app import celery_app +from ripping import rip_dvd, rip_bluray -@celery_app.task(bind=True, name="worker.tasks.detect_disc") -def detect_disc(self, device_path: str, disc_type: str): - """Dummy-Disk-Erkennungstask.""" - print(f"Disc erkannt: {disc_type}, Device: {device_path}") +def detect_disc_type(device_path: str) -> str: + """Erkennt den Disc-Typ anhand des Gerätepfads.""" + try: + result = subprocess.run( + ["file", "-L", device_path], + capture_output=True, + text=True, + timeout=10 + ) + + output = result.stdout.lower() + + if "dvd" in output or "video_ts" in output: + return "dvd" + elif "bluray" in output or "bdmv" in output: + return "bluray" + elif "audio" in output or "cda" in output: + return "cd" + else: + return "unknown" - return { - "status": "success", - "message": f"Disc erkannt: {disc_type}", - "device_path": device_path, - "disc_type": disc_type - } + except Exception: + return "unknown" + + +@celery_app.task(bind=True, name="worker.tasks.rip_disc") +def rip_disc(self, device_path: str, disc_id: str = None): + """Rippt eine Disc basierend auf ihrem Typ.""" + disc_type = detect_disc_type(device_path) + + if not disc_id: + disc_id = device_path.replace("/", "_") + + if disc_type == "cd": + return { + "status": "not_implemented", + "message": "CD-Ripping mit abcde noch nicht implementiert", + "disc_type": disc_type + } + elif disc_type == "dvd": + return rip_dvd(device_path, disc_id) + elif disc_type == "bluray": + return rip_bluray(device_path, disc_id) + else: + return { + "status": "error", + "message": f"Unbekannter Disc-Typ: {disc_type}", + "disc_type": disc_type + }