Files
videogen/README.md
2026-08-15 13:43:52 +02:00

122 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BrandLoop (videogen)
KI-Video-Generierung mit lernender Brand-Knowledge-Base (Elo-Scoring über Attribute).
- **Prototyp:** [prototyp-app.html](prototyp-app.html) statische Preview unter `videogen.project.webklar.com`
- **Desktop-Ansicht:** Design-Handoff für die Desktop-Adaption in [design/desktop-ansicht/](design/desktop-ansicht/) (Spezifikation: [README.md](design/desktop-ansicht/README.md))
- **Backend:** selbst gehostetes Appwrite (`https://appwrite.webklar.com/v1`), Projekt **BrandLoop** `6a5cee34002bb8360c34`, Datenbank `brandloop`
## App (`client/`)
Expo / React Native, eine Codebase für Web und nativ. Stand: Gerüst aus E1
drei Tabs, sonst leer.
```bash
npm --prefix client run web
```
## Bildgenerierung
Die Warteschlange aus `jobs` arbeitet der Dispatcher ab **serverseitig**, weil
der Anbieter-Schlüssel nicht ins Client-Bundle darf:
```bash
BILD_ANBIETER=stub node scripts/job-dispatcher.mjs
```
`stub` erzeugt Platzhalterbilder und macht die ganze Kette prüfbar, ohne Kosten.
`ark` und `openrouter` sprechen die echten Modelle an beide setzen voraus,
dass das jeweilige Konto freigeschaltet bzw. aufgeladen ist:
- **BytePlus Ark:** Modell in der Konsole unter Model Service aktivieren
- **OpenRouter:** Guthaben aufladen
Danach reicht `BILD_ANBIETER=ark node scripts/job-dispatcher.mjs` am Code
ändert sich nichts.
## Demo-Daten
Demo-Daten zum Anschauen (Marke, zwei Ordner, vier Modelle mit echten Bildern
aus `uploads/`) legt alles als **Client** an, belegt damit nebenbei die
Rechte, und ist idempotent:
```bash
node scripts/seed-demo.mjs
```
Die Mandantentrennung lässt sich jederzeit nachprüfen legt zwei echte Konten an,
prüft über die API und räumt sich selbst auf:
```bash
node scripts/test-mandanten.mjs
```
Die Appwrite-SDKs sind **exakt** gepinnt (`appwrite@23.0.0`,
`react-native-appwrite@0.25.0`): der Server läuft 1.8.1, neuere SDKs sprechen
Response-Format 1.9.x. Beim Server-Upgrade beide zusammen anheben.
Konfiguration (Endpoint, Projekt-ID, DB-ID) steht in `client/app.json` unter
`expo.extra.appwrite`. Der Appwrite-**Server-Key** gehört dort **nicht** hinein
er landet sonst im Client-Bundle; er steht in der `.env` im Repo-Root und wird
nur von `scripts/` und später von Appwrite-Functions benutzt.
## Datenbank-Setup
Das komplette Schema (22 Tabellen, Indizes, 5 Storage-Buckets, internes Dev-Team) legt
[scripts/setup-appwrite.mjs](scripts/setup-appwrite.mjs) an idempotent, kann nach
Plan-Erweiterungen jederzeit erneut laufen:
```bash
# API-Key liegt als BRANDLOOP_APPWRITE_API_KEY in /home/webklar/apps/.env, dann einfach:
node scripts/setup-appwrite.mjs
# oder explizit:
APPWRITE_API_KEY=... node scripts/setup-appwrite.mjs
```
Der API-Key braucht die Scopes **Databases/Tables (read+write), Storage/Buckets (read+write), Teams (read+write)**.
## Prompt-Templates (P1P18)
Alle 18 Prompts des Prompt-Inventars liegen versioniert in [prompts/](prompts/) (Konventionen
und Slot-Registry: [prompts/README.md](prompts/README.md)) und werden mit
[scripts/seed-prompts.mjs](scripts/seed-prompts.mjs) in die Tabelle `prompt_templates`
geseedet — idempotent: Inhaltsänderung ⇒ neue Zeile `version+1`, alte Zeilen `aktiv=false`.
P8 ist eine Familie (1× Regie-Kern + 4 Modell-Adapter seedance/veo/sora/wan) = 22 Zeilen.
Das Skript seedet außerdem die 4 globalen Brand-Regeln in `rules`.
```bash
node scripts/seed-prompts.mjs
```
### Bewusste Abweichungen vom DB-Plan
- **Referenzen als indizierte String-Spalten (size 64) statt Relationship-Spalten.**
Appwrite-Relationships sind nicht filter-/indizierbar der Top-N-Index auf
`attribute_scores` (`brand_id, folder_id, category_id, score DESC`) und alle
Listen-Queries brauchen aber genau das. Many-to-many (`videos.attribute_ids`) ist ein String-Array
(`Query.contains`). IDs mit 64 Zeichen, weil uuid4 = 36 Zeichen.
- **`created_at`-Spalten entfallen** Appwrite pflegt `$createdAt` automatisch
(Indizes nutzen `$createdAt` direkt, z. B. `score_events`, `jobs`).
- **Enum-Werte ohne Umlaute** (`laeuft` statt `läuft`).
- **`attributes.tags`: Key-Index statt Volltext-Index** Appwrite verbietet
Fulltext auf Array-Spalten; Tag-Suche läuft über `Query.contains`.
- **S3/Hetzner-Backend für Storage** ist eine *instanzweite* Appwrite-Einstellung
(`_APP_STORAGE_DEVICE`) und betrifft alle Projekte auf dem Server wird daher
nicht vom Skript gesetzt, sondern muss bewusst am Server konfiguriert werden.
Aktuell: lokales Storage.
### Rechte-Modell
- `rules` + `prompt_templates`: Tabellen-Rechte nur für Team `internal` (Dev-Modus) 🔒
- Alle anderen Tabellen: `rowSecurity` an, keine Tabellen-Rechte Zeilen bekommen
beim Anlegen die Team-Permission der jeweiligen Brand (Multi-Tenant).
- `consents`-Bucket: zusätzlich Lese-Recht für Team `internal`.
- Append-only per Konvention (Server-Key schreibt): `score_events`, `video_metrics`, `jobs`.
### Noch offen (laut Plan)
- Appwrite **Functions**: `elo-update`, `favorit-berechnen`, `ads-metriken-holen`,
`kategorie-durchschnitt`, `archivierung`, `job-dispatcher`
- Stripe-Anbindung (metered billing über `usage_records`)