kurmann / videoschnitt

Teilautomatisierung und Verwaltung für privaten Videoschnitt – das Kraftwerk für Familienfilme
Apache License 2.0
0 stars 0 forks source link

Establish web api #547

Open kurmann opened 1 month ago

kurmann commented 1 month ago

Hier ist eine Markdown-Anleitung, die dir den Einstieg in die Umstellung deines Projekts auf eine Architektur mit Click für die CLI und FastAPI für die Web-API erleichtert. Ich werde dir die wesentlichen Schritte zeigen und dir einen Ansatz bieten, wie du bestehende Skripte wie integrate-new-media und import-new-media umsetzen kannst.


Projektstruktur und Übersicht

Bevor du loslegst, solltest du die Projektstruktur so anpassen, dass die neuen Komponenten klar voneinander getrennt sind:

my_project/
├── app/
│   ├── __init__.py
│   ├── cli/
│   │   ├── __init__.py
│   │   └── integrate_new_media.py
│   ├── api/
│   │   ├── __init__.py
│   │   └── main.py
│   ├── config/
│   │   └── config.yaml
│   ├── core/
│   │   ├── __init__.py
│   │   ├── media_integration.py
│   │   └── compressor.py
├── .venv/
├── tests/
│   ├── __init__.py
│   └── test_media.py
├── README.md
├── setup.py
└── pyproject.toml

1. CLI mit Click

Das Ziel ist es, die bisherige Logik in eine CLI mit Click zu verpacken. Hier ein Beispiel für integrate_new_media.py, das in der cli/-Komponente liegt.

integrate_new_media.py

import click
from app.core.media_integration import integrate_new_media

@click.command()
@click.option('--source', '-s', default=None, help='Pfad zum Quellverzeichnis')
@click.option('--destination', '-d', default=None, help='Pfad zum Zielverzeichnis')
@click.option('--compress', '-c', is_flag=True, help='Aktiviert die Kompression')
def cli(source, destination, compress):
    """
    CLI für die Integration neuer Medien.
    """
    # Hier kannst du deine Logik aus dem bisherigen Script einbinden
    integrate_new_media(source, destination, compress)

if __name__ == '__main__':
    cli()

setup.py

Damit Click funktioniert, musst du den Entry-Point in der setup.py angeben:

from setuptools import setup, find_packages

setup(
    name="kurmann_videoschnitt",
    version="0.1.0",
    packages=find_packages(),
    install_requires=[
        'click',
        'fastapi',
        'uvicorn',
    ],
    entry_points={
        'console_scripts': [
            'integrate-new-media=app.cli.integrate_new_media:cli',
        ],
    },
)

Jetzt kannst du den Befehl integrate-new-media direkt über das Terminal verwenden und deine Parameter mitgeben.

2. Web-API mit FastAPI

Zusätzlich möchtest du eine API zur Steuerung deiner Prozesse bereitstellen. Dazu erstellst du eine API-Komponente.

api/main.py

from fastapi import FastAPI
from pydantic import BaseModel
from app.core.media_integration import integrate_new_media

app = FastAPI()

class MediaRequest(BaseModel):
    source: str
    destination: str
    compress: bool = False

@app.post("/integrate")
def integrate_media(request: MediaRequest):
    integrate_new_media(request.source, request.destination, request.compress)
    return {"status": "success", "source": request.source, "destination": request.destination}

# Starte den Server: uvicorn app.api.main:app --reload

Start der API

Um die API zu starten, verwendest du uvicorn:

uvicorn app.api.main:app --host 0.0.0.0 --port 8000 --reload

3. Logik in der Core-Komponente bündeln

Die eigentliche Logik zur Medienintegration sollte in einer zentralen Komponente organisiert sein, die sowohl die CLI als auch die API nutzen können.

core/media_integration.py

def integrate_new_media(source_directory, destination_directory, compress_flag):
    # Deine bisherige Logik, die sowohl CLI als auch API nutzen kann
    print(f"Verwende Quellverzeichnis: {source_directory}")
    print(f"Verwende Zielverzeichnis: {destination_directory}")
    print(f"Kompression aktiviert: {compress_flag}")

    # Führe die Integration der Medien durch
    # ...

4. Konfigurationsmanagement

Du kannst eine zentrale config.yaml nutzen, die in beiden Varianten – CLI und API – geladen wird.

config/config.yaml

source_directory: "/path/to/source"
destination_directory: "/path/to/destination"
compress_flag: false

Die Konfiguration kann dann in den Skripten geladen werden, falls keine Parameter übergeben werden.

5. Hinweise zur Nutzung von CLI und API

6. Ergänzende Hinweise zur Übergabe von Parametern

Ein typisches Problem ist, dass unterschiedliche Umgebungen (CLI und API) eventuell Parameter oder Umgebungsvariablen unterschiedlich behandeln. Deshalb:


Fazit

Mit diesem Ansatz behältst du die Flexibilität der Kommandozeilenaufrufe, während du gleichzeitig eine moderne Web-API hinzufügst, die deine Prozesse zentral steuert.

kurmann commented 1 month ago

Du hast das wirklich grossartig gemacht. Ich habe lediglich noch eine Frage bei der Projektstruktur. Wo würdest du dann die einzelnen Python-Packages unterbringen? Sind die im Core drin? Weil diese machen ja die eigentliche Arbeit, von denen gibt es relativ viele.


Vielen Dank für dein Feedback! Die Python-Packages, die die eigentliche Arbeit machen, solltest du nicht direkt in der core-Komponente unterbringen, sondern sie strukturiert auf eine Weise organisieren, die sowohl für die CLI als auch für die API sinnvoll ist. Lass mich dir die überarbeitete Projektstruktur erklären.

Überarbeitete Projektstruktur

my_project/
├── app/
│   ├── __init__.py
│   ├── cli/
│   │   ├── __init__.py
│   │   └── integrate_new_media.py
│   ├── api/
│   │   ├── __init__.py
│   │   └── main.py
│   ├── config/
│   │   └── config.yaml
│   ├── core/
│   │   ├── __init__.py
│   │   └── media_manager.py  # Hier wird die Logik orchestriert, nicht ausgeführt
│   ├── services/  # Hier kommen die eigentlichen Python-Packages hin
│   │   ├── __init__.py
│   │   ├── media_integration/
│   │   │   ├── __init__.py
│   │   │   ├── integrate.py  # Spezifische Logik für Medienintegration
│   │   │   └── helpers.py  # Helferfunktionen und Utility-Skripte
│   │   ├── compressor/
│   │   │   ├── __init__.py
│   │   │   ├── compress.py  # Logik für Apple Compressor
│   │   │   └── helpers.py  # Helferfunktionen für Kompressionslogik
│   ├── utils/  # Allgemeine Helfer- und Utility-Skripte, die in mehreren Bereichen gebraucht werden
│   │   ├── __init__.py
│   │   └── logger.py  # Zentrales Logging
├── .venv/
├── tests/
│   ├── __init__.py
│   └── test_media.py
├── README.md
├── setup.py
└── pyproject.toml

Erläuterung der Struktur

Beispiel für ein Service-Package

services/media_integration/integrate.py

def integrate(source_directory, destination_directory, compress_flag):
    # Die eigentliche Logik für die Medienintegration
    print(f"Integrating media from {source_directory} to {destination_directory}")
    if compress_flag:
        print("Kompression ist aktiviert.")
    else:
        print("Kompression ist deaktiviert.")
    # Hier weitere Logik für die Integration und ggf. die Kompression

services/compressor/compress.py

def compress_files(source_directory, destination_directory):
    # Logik für den Apple Compressor
    print(f"Kompression der Dateien aus {source_directory} nach {destination_directory}")
    # Weitere Kompressionslogik

Beispiel für die Nutzung in der Core-Komponente

core/media_manager.py

from app.services.media_integration.integrate import integrate
from app.services.compressor.compress import compress_files

def handle_media_integration(source_directory, destination_directory, compress_flag):
    # Orchestriert die Medienintegration und Kompression
    integrate(source_directory, destination_directory, compress_flag)
    if compress_flag:
        compress_files(source_directory, destination_directory)

Fazit

Mit dieser Struktur erreichst du eine klare Trennung der Verantwortlichkeiten:

Du behältst also die Flexibilität für Kommandozeilen-Tools und gleichzeitig eine zentrale Web-API.