Shorts-Pipeline mit Hermes Agent
Mein Raspberry Pi 5 postet auf YouTube. Dreimal täglich produziert der Hermes Agent einen kompletten Short: tagesaktuelle Recherche, Skript, Stimme, Bilder, Schnitt und Upload. Die eigentliche Arbeit steckt nicht in der Technik, sondern in den Produktionsregeln und der Iteration an Qualität.
Dieser Beitrag ist der dritte Teil des Raspberry-Pi-Projekts. Teil eins war die Grundhärtung, Teil zwei das Einsperren des Agenten. Jetzt geht es um das, wofür beides gebaut wurde: eine Kurzvideo-Pipeline, die ohne mich läuft.
Die Nische findet der Agent selbst
Bevor ein einziges Video entstand, bekam der Agent einen Recherche-Auftrag: sechs Content-Nischen nach fünf Kriterien bewerten, unter anderem Quellenlage, Automatisierbarkeit und rechtliche Risiken. Gewonnen hat eine Nische mit täglich frischen, seriösen Quellen, kaum Bildrechte-Problemen und hoher Fehlertoleranz. Welche es genau ist, behalte ich bewusst für mich: Der Kanal läuft getrennt von dieser Website. Kinder-Content flog trotz guter Reichweiten-Prognose sofort raus: COPPA-Regeln und Plattform-Vorgehen gegen KI-Massenware sind das Risiko nicht wert.
Die Pipeline in einem Bild
Hermes Agent (Raspberry Pi 5)
Recherche web_search → lokales SearXNG (nur Loopback)
Skript gpt-5.5
Sprachspur Edge TTS (deutsche Neural-Stimme)
Bilder Bildgenerierung (gpt-image)
Schnitt ffmpeg im Docker-Container (9:16, 1080x1920, 40-50 s)
Upload YouTube Data API v3, Credentials read-only im Container
Hochformat und unter drei Minuten reichen, damit YouTube den Upload automatisch als Short einstuft. Die schwere Arbeit läuft in der Cloud, lokal bleiben ffmpeg und die Websuche. Deshalb reicht der Pi dafür locker aus, mit einer Einschränkung: Er hat keinen Hardware-H.264-Encoder, ffmpeg encodiert in Software auf vier Kernen. Bei drei Videos am Tag völlig egal.
YouTube-API: der Papierkram
Der Upload läuft über ein eigenes Google-Cloud-Projekt mit einem einzigen Scope: youtube.upload. Der wichtigste Haken steckt im OAuth-Consent-Status. Im Status „Testing" laufen Refresh-Tokens nach sieben Tagen ab, Dauerbetrieb unmöglich. Erst der Status „In Produktion" macht den Token unbegrenzt haltbar.
Den Refresh-Token auf einer headless Maschine zu erzeugen ist ein kleiner Tanz: Das Auth-Skript startet einen lokalen Callback-Server auf dem Pi, der Browser läuft auf der Workstation, ein SSH-Tunnel verbindet beide für den Redirect. Zwei Stolpersteine aus der Praxis: Ein frisches Google-Konto braucht erst einen YouTube-Kanal, sonst antwortet die API mit youtubeSignupRequired. Und bei einer erneuten Autorisierung desselben Clients gibt Google nur dann wieder einen Refresh-Token heraus, wenn access_type=offline und prompt=consent gesetzt sind.
Eine Doku-Überraschung gab es auch, im positiven Sinn: Die dokumentierte Sperre, dass Videos unauditierter API-Projekte privat bleiben müssen, griff in der Praxis nicht. Privat hochgeladen, in Studio geprüft, per Klick öffentlich. Das Quota-Budget reicht ebenfalls: Ein Upload kostet 1.600 von 10.000 Tages-Units, etwa sechs Uploads pro Tag wären drin.
Geschriebene Regeln reichen nicht
Die wichtigste Lektion des ganzen Projekts. Alle Produktionsregeln stehen in einer Datei, die der Agent vor jedem Lauf liest: keine echten Links, Logos oder Telefonnummern, Beispiel-Screens tragen sichtbar BEISPIEL, ein Quellenlog pro Video, feste Struktur von Hook bis Merksatz. Trotzdem improvisierte der Agent die technische Umsetzung jedes Mal neu: plötzlich eine andere Untertitelgröße, pauschale Schnitte statt inhaltlicher, leiserer Ton.
Die Lösung: Der Videobau wurde aus dem besten Video in ein festes Skript eingefroren. TTS-Parameter, Lautheits-Normalisierung, Untertitel-Layout, Umlaute, alles Code statt Text. Seitdem gilt der Merksatz:
Kreative Schritte dürfen variieren.
Technische Schritte müssen Code sein.
Eine Änderung pro Runde
Das Lehrstück dazu lieferte eine frühe Iterationsrunde: vier Verbesserungen auf einmal, und alles wurde schlechter. Eine neue Stimme, ein phonetischer Aussprache-Hack, ein Zoom-Effekt und Text in den Bildern. Ergebnis: Die multilinguale TTS-Stimme kippte wegen des phonetischen Hacks ins Niederländische, der Zoom ruckelte, und der Bildtext wurde vom 9:16-Zuschnitt abgeschnitten.
Die Learnings daraus sind seitdem feste Regeln: nur eine Änderung pro Runde. Kein Text in generierte Bilder, Botschaften gehören ins Untertitel-Overlay. Untertitel sind der komplette Sprechtext in kurzen Segmenten, nicht nur Kernaussagen. Und keine phonetischen Umschreibungen im Sprechtext, die Sprach-Autoerkennung der Stimme ist empfindlich. Ein Rest bleibt: Englische Fachbegriffe spricht die Stimme teils eingedeutscht aus. Damit kann ich leben, ein Fix über phonetische Tricks wäre riskanter als der Makel.
Cron ohne .bashrc
Automatisiert wird klassisch: Die Crontab des Agent-Users startet morgens und nachmittags einen Wrapper. Der Rootless-Docker-Stolperstein aus dem Sicherheits-Beitrag kehrt dabei wieder, denn Cron lädt keine .bashrc. Der Wrapper setzt die Umgebungsvariablen deshalb selbst und ruft den Agenten im Oneshot-Modus auf. Jeder Lauf startet mit frischem Kontext: Regeln und Werkzeuge leben in Dateien, nicht im Sitzungsgedächtnis.
export XDG_RUNTIME_DIR=/run/user/$(id -u)
export DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock
hermes -z "Produziere den nächsten Short ..." >> logs/daily_$(date +%F).log
Der Rückschlag: fünfmal dasselbe Bild
Dann kam der Lauf, der technisch perfekt war und trotzdem nicht veröffentlicht wurde. Video gebaut, hochgeladen, kein Fehler im Log. Aber alle fünf Szenen waren praktisch dasselbe flache Symbolbild in Variationen, eine Infografik-Slideshow statt eines Videos. Dazu war das Thema zu nah an den Vorgängern, die Duplikat-Erkennung griff zu grob.
Die Regeln wurden daraufhin deutlich verschärft: Duplikat-Prüfung nach Themen-Kategorie statt nur nach Quelle, dieselbe Kategorie höchstens einmal in den letzten fünf Shorts. Vor der Bildgenerierung entsteht ein Bildplan mit Motiv, Ort, Perspektive und finalem Prompt pro Szene. Finale Szenenbilder müssen aus der Bildgenerierung kommen, lokal gezeichnete Grafiken sind verboten. Und vor dem Upload steht ein Qualitätsgate: Bei Symbol-Slideshows, kaputten Händen oder zu ähnlichen Szenen wird nicht hochgeladen.
Der eigentliche Fehler: ein Pfad, den es nicht gibt
Warum wich der Agent überhaupt auf selbst gezeichnete Grafiken aus, obwohl die Bildgenerierung gute, realistische Bilder liefert? Die Ursache war ein Architektur-Detail. Die Bildgenerierung läuft im Host-Prozess des Agenten und legt ihre Bilder in einem Cache im Home-Verzeichnis ab. Die Shell-Befehle des Agenten laufen aber im Docker-Container, und der sah diesen Pfad schlicht nicht. Der Agent erzeugte also ein gutes Bild, bekam einen Host-Pfad gemeldet, fand ihn im Container nicht, und improvisierte dann lokal. Genau das Verhalten, das die Regeln verbieten wollten, hatte eine technische Wurzel.
Der Fix passt zum Least-Privilege-Konzept: Der Bilder-Cache wird read-only in den Container gemountet, als eigener Pfad, nur dieser eine Unterordner. Dazu kam eine Config-Falle: Die Volume-Liste steht bei Hermes sowohl in der YAML-Konfiguration als auch in der .env, und die .env gewinnt. Wer nur die YAML ändert, wundert sich, warum der Mount nicht auftaucht. Zuletzt bekamen die Produktionsregeln den Container-Pfad ausdrücklich beschrieben, statt auf den Host-Pfad zu zeigen.
Der Volltest danach war der bisher beste Lauf des Projekts: fünf echte, unterschiedliche Szenen mit Tiefe und Alltagskontext. Das Qualitätsgate arbeitete dabei sichtbar mit, der Agent generierte eine Szene eigenständig neu, weil ihm im ersten Versuch störende Beschriftungen auffielen. Der Sprung gegenüber der Symbol-Slideshow ist enorm.
Review bleibt menschlich
Vollautomatisch heißt nicht unkontrolliert. Jeder Upload landet privat auf dem Kanal. Ich prüfe das Video und das Quellenlog in YouTube Studio, dann ist Veröffentlichen ein Klick. Dieser letzte menschliche Schritt bleibt, bis der Agent sich bewiesen hat. Sobald er über längere Zeit konstant guten Content hochlädt, stelle ich die Pipeline um und die Videos gehen direkt nach dem Upload öffentlich live.
Meine Checkliste
[x] Nische mit täglich frischen, seriösen Quellen
[x] YouTube-Projekt: Scope nur upload, Consent In Produktion
[x] Refresh-Token headless per SSH-Tunnel erzeugt
[x] Produktionsregeln als Datei, vor jedem Lauf gelesen
[x] Videobau als eingefrorenes Skript, nicht als Textregel
[x] Eine Änderung pro Iterationsrunde
[x] Kein Text in generierten Bildern, Untertitel als Overlay
[x] Cron-Wrapper setzt Rootless-Docker-Envs selbst
[x] Bilder-Cache read-only in den Container gemountet
[x] Duplikat-Prüfung nach Kategorie, Bildplan pro Szene
[x] Qualitätsgate vor jedem Upload
[x] Upload privat, Review in Studio, dann öffentlich
Die Pipeline läuft jetzt dreimal täglich unbeaufsichtigt. Als Nächstes stehen eine breitere Quellenbasis und TikTok als zweite Plattform auf der Liste. Der Stand des Gesamtprojekts inklusive Roadmap: Raspberry Pi 5.