Phase 5: Der eigene API Dienst mit FastAPI
Bis hierhin läuft alles auf dem Server selbst. Jetzt kommt der interessante Teil. Wir bauen einen HTTP Endpunkt, den Du von jedem Rechner im Netzwerk aufrufen kannst. Prompt rein, WAV Datei raus.
Das Repository liefert dafür nur eine Gradio Oberfläche. Die ist für manuelles Ausprobieren nett, für die Anbindung eigener Anwendungen aber ungeeignet. Also schreiben wir einen schlanken FastAPI Wrapper.
Der Dienst soll am Ende drei Dinge können. Beim Systemstart automatisch hochfahren. Auf Port 8770 im LAN erreichbar sein. Und WAV Dateien direkt als Response zurückgeben.
Schritt 1: Zusätzliche Pakete installieren
FastAPI und der ASGI Server Uvicorn fehlen noch in der Umgebung. Beide kommen über uv dazu.
Befehl: cd ~/stable-audio-3
Befehl: uv pip install fastapi uvicorn
Prüfe kurz, ob die Binary in der virtuellen Umgebung liegt.
Befehl: ls -l ~/stable-audio-3/.venv/bin/uvicorn
Diesen Pfad brauchst Du später für den systemd Dienst. Merke ihn Dir.
Schritt 2: Die Datei sa3_api.py anlegen
Damit dieser Beitrag nicht komplett ausufert, habe ich das Python Programm als ZIP Datei zum Download bereitgestellt.
Download: sa3_api.zip
Lade die Datei herunter, entpacke sie und lege sa3_api.py direkt in das geklonte Repository. Der Pfad muss also ~/stable-audio-3/sa3_api.py lauten.
Wichtig: nicht in den Unterordner stable_audio_3 kopieren. Das ist das Python Paket selbst. Von dort aus findet der Import das Modul nicht mehr.
Befehl: ls -l ~/stable-audio-3/sa3_api.py
Was der Python Code macht
Der Wrapper stellt einen API Endpunkt bereit, über den Du Tierstimmen, Umgebungsgeräusche und andere Audiospuren erzeugen kannst. Drei Details sind erklärungsbedürftig.
Der Lock in _generate_sync serialisiert die Anfragen. Parallele Diffusionsläufe auf einer Karte bringen kaum Durchsatz. Sie erhöhen nur das Risiko für Out of Memory. Ein Request nach dem anderen ist hier die richtige Strategie.
Der Warmup im Lifespan erzeugt beim Start einmal eine Sekunde Audio. Damit zahlt der erste echte Request nicht mehr die Initialisierungszeit der CUDA Kernel.
Der API Key wird über den Header X-API-Key geprüft. Setzt Du die Variable nicht, ist der Dienst ohne Authentifizierung erreichbar. Im eigenen LAN mag das reichen, sauber ist es nicht.
Schritt 3: Erster manueller Start
Vor dem systemd Dienst testen wir von Hand. So siehst Du Fehler sofort im Terminal.
Befehl: cd ~/stable-audio-3
Befehl: export HF_TOKEN=hf_dein_token_hier
Befehl: export CUDA_VISIBLE_DEVICES=0
Wenn Du einen API Key möchtest, setzt Du zusätzlich diese Variable. Andernfalls lässt Du sie einfach weg.
Befehl: export SA3_API_KEY=mein-geheimer-key
Jetzt der Start:
Befehl: uv run uvicorn sa3_api:app --host 0.0.0.0 --port 8770
Wichtig ist --host 0.0.0.0. Der Standardwert wäre 127.0.0.1. Dann wäre der Dienst nur lokal erreichbar und Dein Ziel verfehlt.
Der Start dauert einen Moment. Das Modell wird geladen und der Warmup läuft. Warte auf die Zeilen Warmup ok und Application startup complete.
Schritt 4: Der erste Test
Öffne eine zweite SSH Sitzung. Zuerst der Gesundheitscheck direkt auf dem Server.
Befehl: curl http://localhost:8770/health
Und derselbe Aufruf über das Netzwerk, von Deinem Arbeitsrechner aus.
Befehl: curl http://<IP-Adresse des Servers>:8770/health
Die Antwort enthält den Modellnamen und den Namen der GPU. Jetzt die eigentliche Generierung. So sieht der Aufruf mit API Key aus:
Befehl: curl -X POST http://localhost:8770/generate -H "Content-Type: application/json" -H "X-API-Key: mein-geheimer-key" -d '{"prompt":"cow mooing in a barn, close mic","duration":4}' --output /tmp/test.wav
Und so ohne API Key, hier mit der IP Adresse meines Servers:
Befehl: curl -X POST http://192.168.2.119:8770/generate -H "Content-Type: application/json" -d '{"prompt":"cow mooing in a barn, close mic","duration":4}' --output /tmp/test.wav
Achte darauf, den Parameter -H wirklich wegzulassen, wenn kein API Key gesetzt ist. Ein einzelnes -H ohne Wert schluckt den nachfolgenden Parameter. curl meldet dann eine fehlerhafte URL.
Kontrolle:
Befehl: ffprobe /tmp/test.wav
Wenn hier 44100 Hz und vier Sekunden stehen, läuft der Dienst. Ein Hinweis noch: bei --output schreibt curl auch Fehlermeldungen in die Zieldatei. Mit file /tmp/test.wav siehst Du sofort, ob echtes Audio drin ist oder eine JSON Fehlermeldung.
Den manuellen Start beendest Du jetzt mit Strg C.
Schritt 5: Die Firewall öffnen (optional)
Falls ufw aktiv ist, blockiert es eventuell den Port. In diesem Fall gibst Du ihn für Dein eigenes Subnetz frei.
Befehl: sudo ufw status
Befehl: sudo ufw allow from 192.168.2.0/24 to any port 8770 proto tcp
Passe das Subnetz an Dein Netzwerk an. Eine Freigabe für die ganze Welt braucht hier niemand.
Schritt 6: Die Environment Datei anlegen
Der Hugging Face Token und der API Key gehören nicht in die Unit Datei. Die liegt unter /etc und ist für alle lesbar. Besser ist eine separate Datei mit stark eingeschränkten Rechten.
Befehl: sudo nano /etc/stable-audio-3.env
Kopiere den folgenden Inhalt hinein, natürlich mit Deinen eigenen Werten.
# Pflicht: Zugang zu den Modellgewichten
HF_TOKEN=hf_dein_token_hier
# Modellvariante
SA3_MODEL=small-sfx
# Muss dem Index aus nvidia-smi entsprechen.
# Bei nur einer Karte ist das die 0.
CUDA_VISIBLE_DEVICES=0
# Optional: nur setzen, wenn Du einen API Key nutzen willst
#SA3_API_KEY=mein-geheimer-key
# Optional: nur setzen, wenn Du den Cache verschoben hast
#HF_HOME=/opt/hf-cache
Speichern mit Strg O, beenden mit Strg X.
Zwei Punkte sind hier wichtig. Setze keine Anführungszeichen um die Werte, systemd nimmt sie sonst als Teil des Wertes. Und HF_HOME muss exakt dem Wert entsprechen, den Du in Phase 3 verwendet hast. Sonst lädt der Dienst alle Gewichte erneut herunter.
Jetzt noch die Rechte einschränken.
Befehl: sudo chown root:root /etc/stable-audio-3.env
Befehl: sudo chmod 600 /etc/stable-audio-3.env
Schritt 7: Die systemd Datei anlegen
Befehl: sudo nano /etc/systemd/system/stable-audio-3.service
Kopiere den folgenden Inhalt hinein:
[Unit]
Description=Stable Audio 3 SFX API
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=ingmar
Group=ingmar
WorkingDirectory=/home/ingmar/stable-audio-3
EnvironmentFile=/etc/stable-audio-3.env
ExecStart=/home/ingmar/stable-audio-3/.venv/bin/uvicorn sa3_api:app --host 0.0.0.0 --port 8770
Restart=on-failure
RestartSec=10
TimeoutStartSec=300
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Speichern mit Strg O, beenden mit Strg X.
Drei Punkte machen hier häufig Ärger.
- Erstens der Pfad zu uvicorn. Ich rufe direkt die Binary aus der virtuellen Umgebung auf, nicht
uv run. Das ist robuster. systemd hat kein sinnvolles PATH und uv würde zusätzlich versuchen, die Umgebung zu synchronisieren. - Zweitens der Benutzer. Er muss dem Besitzer des Repositorys und des Hugging Face Caches entsprechen. Bei mir ist das ingmar. Passe alle vier Zeilen an, in denen mein Benutzername vorkommt.
- Drittens TimeoutStartSec. Modell laden und Warmup brauchen Zeit. Der Standardwert von 90 Sekunden kann knapp werden.
Schritt 8: Dienst aktivieren und starten
Damit der Dienst wirklich läuft, musst Du ihn aktivieren und starten. Das machst Du mit den folgenden drei Befehlen.
Befehl: sudo systemctl daemon-reload
Befehl: sudo systemctl enable stable-audio-3.service
Befehl: sudo systemctl start stable-audio-3.service
Wenn alles geklappt hat, prüfst Du den Status wie folgt:
Befehl: sudo systemctl status stable-audio-3.service
Erwartet wird active (running). Direkt nach dem Start läuft noch der Warmup. Das Log zeigt Dir den Fortschritt.
Befehl: sudo journalctl -u stable-audio-3.service -f
Beenden der Logausgabe mit Strg C.
Schritt 9: Der Test vom anderen Rechner
Jetzt kommt der Moment der Wahrheit. Wechsle auf Deinen Arbeitsrechner und führe im Terminal den folgenden Befehl aus. Er zeigt Dir, ob der Dienst läuft.
Befehl: curl http://192.168.2.119:8770/health
Kommt eine Antwort mit dem Status ok, ist der Dienst im Netzwerk erreichbar.
Mit dem folgenden Befehl generierst Du die erste Tierstimme. Schau Dir den Aufbau in Ruhe an, um ihn zu verstehen.
Befehl: curl -X POST http://192.168.2.119:8770/generate -H "Content-Type: application/json" -d '{"prompt":"wolf howling in a distant forest at night","duration":6}' --output wolf.wav
Oder dieses Beispiel:
Befehl: curl -X POST http://192.168.2.119:8770/generate -H "Content-Type: application/json" -d '{"prompt":"cow mooing in a barn, close mic","duration":4}' --output cow.wav
Die Datei landet in dem Verzeichnis, in dem Du Dich gerade befindest. Öffne sie mit einem beliebigen Player.
Die interaktive Dokumentation Deines API Endpunktes liefert FastAPI gleich mit. Rufe sie im Browser auf:
Adresse: http://192.168.2.119:8770/docs
Dort testest Du Prompts direkt im Browser, ganz ohne curl.
Schritt 10: Anbindung aus Python
Für Deine eigene Anwendung reichen ein paar Zeilen.
import requests
resp = requests.post(
"http://192.168.2.119:8770/generate",
json={"prompt": "heavy rain on a metal roof, steady", "duration": 10},
timeout=120,
)
resp.raise_for_status()
with open("regen.wav", "wb") as f:
f.write(resp.content)
print("Dauer:", resp.headers.get("X-Generation-Seconds"), "Sekunden")
Wenn Du einen API Key gesetzt hast, ergänzt Du noch den passenden Header.
headers={"X-API-Key": "mein-geheimer-key"},
Und wenn Du das Audio lieber eingebettet bekommst, setzt Du "format": "json". Dann liefert der Dienst die Datei als Base64 String zurück, zusammen mit Samplerate und Generierungsdauer. Praktisch für Web Frontends.
Nützliche Befehle im Betrieb
| Zweck | Befehl |
|---|---|
| Dienst neu starten | sudo systemctl restart stable-audio-3 |
| Dienst stoppen | sudo systemctl stop stable-audio-3 |
| Autostart deaktivieren | sudo systemctl disable stable-audio-3 |
| Letzte 100 Logzeilen | sudo journalctl -u stable-audio-3 -n 100 |
| Logs seit heute | sudo journalctl -u stable-audio-3 --since today |
| VRAM Belegung prüfen | nvidia-smi |
Ein Wort zur Sicherheit
Der Dienst läuft unverschlüsselt über HTTP. Im eigenen LAN ist das vertretbar. Sobald er über Dein Netzwerk hinaus erreichbar sein soll, gehört ein Reverse Proxy davor. Nginx mit einem Let’s Encrypt Zertifikat ist der klassische Weg.
Meine bevorzugte Variante ist eine andere. Ich lasse den Dienst an das LAN gebunden und greife von unterwegs über Tailscale darauf zu. Kein offener Port nach außen, keine Zertifikatsverwaltung, verschlüsselt ist es trotzdem.
Und noch ein Hinweis: der API Key im Klartext Header ist keine ernsthafte Authentifizierung. Er hält versehentliche Zugriffe fern, mehr nicht. Für ein Homelab reicht das.
Troubleshooting
Installation und Modell
| Symptom | Ursache und Lösung |
|---|---|
| 401 oder 403 beim Download | Lizenz auf Hugging Face nicht bestätigt oder HF_TOKEN fehlt |
| RuntimeError: No CUDA GPUs are available | CUDA_VISIBLE_DEVICES zeigt auf einen Index, den es nicht gibt. Mit nvidia-smi prüfen. |
| CUDA out of memory | Andere Prozesse belegen die Karte, Belegung mit nvidia-smi prüfen |
| Torch findet keine GPU | CUDA Version passt nicht zum Treiber, Torch neu installieren |
| Volle Systempartition | HF_HOME wurde nicht gesetzt, Cache liegt unter home |
| Erster Lauf sehr langsam | Normal, Modelldownload und Initialisierung |
| flash_attn not installed | Kein Fehler. Small SFX braucht Flash Attention nicht. |
Der Dienst
| Symptom | Ursache und Lösung |
|---|---|
| status 203/EXEC | Der Pfad in ExecStart stimmt nicht. Mit ls prüfen. |
| Dienst startet, dann timeout | TimeoutStartSec erhöhen, Warmup braucht länger. |
| 401 invalid api key | Header X-API-Key fehlt oder stimmt nicht mit der env Datei überein. |
| Connection refused von extern | host 0.0.0.0 fehlt oder die Firewall blockt. |
| ModuleNotFoundError stable_audio_3 | WorkingDirectory zeigt nicht auf das Repository, oder sa3_api.py liegt im falschen Ordner. |
| Permission denied auf den Cache | HF_HOME gehört einem anderen Benutzer als der Dienst. |
| curl: URL rejected | Ein Parameter im curl Aufruf hat keinen Wert, meist ein leeres -H. |
Ein Wort zur Lizenz
Stable Audio 3 steht unter der Stability AI Community License. Das ist keine OSI zertifizierte Open Source Lizenz. Die Nutzung ist kostenlos für Forschung, Privatpersonen und Unternehmen unterhalb einer Million US Dollar Jahresumsatz. Darüber ist eine Enterprise Lizenz erforderlich.
Positiv fällt die Datenbasis auf. Stability AI hat ausschließlich lizenziertes Material und Creative Commons Aufnahmen verwendet. Ein Teil stammt aus dem Freesound Archiv unter CC0, CC BY und CC Sampling Plus. Das ist bei generativen Audiomodellen keine Selbstverständlichkeit.
Zusätzlich gelten die Gemma Terms of Use für den Text Encoder. Deren Nutzungsbeschränkungen in Abschnitt 3.2 solltest Du vor einem produktiven Einsatz kennen.
Fazit
Die Installation hat mich keine halbe Stunde gekostet. Der Download der Gewichte war der längste Teil. Das ist für ein generatives Audiomodell erfreulich unspektakulär.
Was mich überzeugt: der minimale Ressourcenbedarf. Zwei bis drei Gigabyte VRAM sind nichts. Das Modell teilt sich die Karte problemlos mit anderen Diensten. Für ein Homelab, in dem ohnehin jede GPU doppelt belegt ist, macht das einen echten Unterschied.
Was Du wissen solltest: Prompt Engineering ist auch hier entscheidend. Vage Beschreibungen liefern matschige Ergebnisse. Präzise Angaben zu Mikrofonabstand, Umgebung und Aufnahmequalität verbessern die Ausgabe deutlich. Für Umgebungsgeräusche, Regen, Wind oder mechanische Sounds liefert das Modell erstaunlich brauchbares Material.
Der eigentliche Gewinn ist für mich aber der API Endpunkt. Damit wird aus einem Kommandozeilenwerkzeug ein Baustein, den jede Anwendung im Netzwerk nutzen kann. Genau das ist für mich souveräne KI. Keine Cloud, keine externen Zugangsdaten, keine Abhängigkeit. Alles läuft im eigenen Rack.
Im nächsten Beitrag baue ich darauf auf und binde den Endpunkt in eine konkrete Anwendung ein.
Hier geht es zum Teil 1: Stable Audio 3 Small SFX auf dem eigenen Server: Installation, Konfiguration und erster Smoke Test 1/2






Ein toller Guide der leicht zugänglich und verständlich ist. Perfekt für ein kleines Side-Project geeignet. Aktuell half mir noch mein…
Thank you for this great tutorial, could you share n8n workflow and comfyui workflow please?
Hallo Anton, die Meldung besagt das in meinem Beisiel Methoden verwendet werden die veraltet (deprecated) sind. Also müsstest Du die…
Danke für das Tool! Ich habe erst kürzlich angefangen mich mit der Thematik zu beschäftigen und bin für meine Erwartungen…
Hallo, ich habe ihre Anleitung befolgt und bekomme im letzten Schritt leider immer folgende Meldung im Terminal: bash <(wget -qO-…