videowatch: lokale Dateien, die keine Videos sind, sofort mit klarer Meldung abweisen #54

Closed
opened 2026-10-16 12:44:32 +00:00 by alf · 7 comments
Owner

Problem

Am 2026-10-16 wurde ein Screenshot (.png) in die videowatch-Queue gegeben. Die Queue nimmt ihn an, und er scheitert erst später im Lauf. Welche Fehlermeldung genau erschien, ist nicht festgehalten, und ich habe den Fall nicht nachgestellt. Die Beobachtungen unten stammen aus dem Code und aus ffprobe.

Befund

  • resolve_local() in skills/videowatch/download.py prüft nur, ob die Datei existiert. Bei einer Endung außerhalb von VIDEO_EXTS gibt sie nur die Warnung ... is not a known video extension, proceeding anyway aus und macht weiter.
  • ffprobe meldet für eine PNG-Datei einen Videostream mit Codec png, duration=N/A und keine Tonspur. Frame-Extraktion und Transkription haben damit nichts zu verarbeiten.
  • Die Queue-Einträge für lokale Pfade entstehen ohne jede Prüfung (process_queue.py, Titel = Dateiname). Erst der Lauf des watch_local.py scheitert, dann nach drei Versuchen.

Vorschlag

  • resolve_local() prüft per ffprobe, ob die Datei eine Dauer größer 0 oder eine Tonspur hat. Sonst bricht sie sofort ab mit einer klaren Meldung, zum Beispiel Keine Video- oder Audiodatei: <Name>. Eine Endung allein ist kein Kriterium (es gibt Videos mit anderer Endung).
  • Wiederholungen sparen: Ein solcher Fehler gehört ohne weitere Versuche auf failed.
  • Optional früher: Beim Hinzufügen eines lokalen Pfads (Mac-Server und Linux-Server, POST /videowatch/playlist und .../items) dieselbe Prüfung machen, damit gar kein Queue-Eintrag entsteht.

Offen

  • Sollen Bilder stattdessen eine eigene Verarbeitung bekommen (Bildbeschreibung statt Transkription)? Das wäre ein eigenes Feature, hier nur das Abweisen.
  • Reihenfolge der Prüfung auf dem Server oder im Worker: eine Stelle, damit Mac- und Linux-Server nicht auseinanderlaufen.

Zusammenhang: iris/Iris#50.

## Problem Am 2026-10-16 wurde ein Screenshot (`.png`) in die videowatch-Queue gegeben. Die Queue nimmt ihn an, und er scheitert erst später im Lauf. Welche Fehlermeldung genau erschien, ist nicht festgehalten, und ich habe den Fall nicht nachgestellt. Die Beobachtungen unten stammen aus dem Code und aus `ffprobe`. ## Befund - `resolve_local()` in `skills/videowatch/download.py` prüft nur, ob die Datei existiert. Bei einer Endung außerhalb von `VIDEO_EXTS` gibt sie nur die Warnung `... is not a known video extension, proceeding anyway` aus und macht weiter. - `ffprobe` meldet für eine PNG-Datei einen Videostream mit Codec `png`, `duration=N/A` und keine Tonspur. Frame-Extraktion und Transkription haben damit nichts zu verarbeiten. - Die Queue-Einträge für lokale Pfade entstehen ohne jede Prüfung (`process_queue.py`, Titel = Dateiname). Erst der Lauf des `watch_local.py` scheitert, dann nach drei Versuchen. ## Vorschlag - `resolve_local()` prüft per `ffprobe`, ob die Datei eine Dauer größer 0 oder eine Tonspur hat. Sonst bricht sie sofort ab mit einer klaren Meldung, zum Beispiel `Keine Video- oder Audiodatei: <Name>`. Eine Endung allein ist kein Kriterium (es gibt Videos mit anderer Endung). - Wiederholungen sparen: Ein solcher Fehler gehört ohne weitere Versuche auf `failed`. - Optional früher: Beim Hinzufügen eines lokalen Pfads (Mac-Server und Linux-Server, `POST /videowatch/playlist` und `.../items`) dieselbe Prüfung machen, damit gar kein Queue-Eintrag entsteht. ## Offen - Sollen Bilder stattdessen eine eigene Verarbeitung bekommen (Bildbeschreibung statt Transkription)? Das wäre ein eigenes Feature, hier nur das Abweisen. - Reihenfolge der Prüfung auf dem Server oder im Worker: eine Stelle, damit Mac- und Linux-Server nicht auseinanderlaufen. Zusammenhang: iris/Iris#50.
Author
Owner

PR #63 gemergt: fix(videowatch): Dateien ohne Video und Ton sofort abweisen, ohne Wiederholungen (iris/Iris#54)

download.py: resolve_local prüft per ffprobe auf Audio oder einen Videostream mit Dauer und
wirft UnusableSourceError (Keine Video- oder Audiodatei: ); die Endung allein entscheidet
nicht mehr. watch_local.py beendet sich dafür mit Exit-Code 65, process_queue.py wiederholt
solche Läufe nicht. Unit-Tests in skills/videowatch/tests.

Co-Authored-By: Claude Sonnet 5.5 noreply@anthropic.com
alf/2ndbrain#63

Commits:

  • fix(videowatch): Dateien ohne Video und Ton sofort abweisen, ohne Wiederholungen (iris/Iris#54)
PR #63 gemergt: fix(videowatch): Dateien ohne Video und Ton sofort abweisen, ohne Wiederholungen (iris/Iris#54) download.py: resolve_local prüft per ffprobe auf Audio oder einen Videostream mit Dauer und wirft UnusableSourceError (Keine Video- oder Audiodatei: <Name>); die Endung allein entscheidet nicht mehr. watch_local.py beendet sich dafür mit Exit-Code 65, process_queue.py wiederholt solche Läufe nicht. Unit-Tests in skills/videowatch/tests. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> https://forgejo.lewerken.duckdns.org/alf/2ndbrain/pulls/63 Commits: - fix(videowatch): Dateien ohne Video und Ton sofort abweisen, ohne Wiederholungen (iris/Iris#54)
Author
Owner

Stand 2026-10-16: Worker-Teil umgesetzt (alf/2ndbrain PR #63)

Geändert (skills/videowatch/):

  • download.py: resolve_local() prüft per ffprobe, ob die Datei Audio oder einen Videostream mit mindestens 0,5 s Dauer enthält. Sonst UnusableSourceError("Keine Video- oder Audiodatei: <Name>"). Die Endung allein entscheidet nicht (ein Video mit Endung .bin wird angenommen, eine Textdatei .mp4 abgewiesen). Ein Video ohne Ton gilt weiter als gültig. Fehlt ffprobe, wird nicht abgewiesen, der spätere Schritt meldet das selbst.
  • watch_local.py: fängt den Fehler getrennt ab, schreibt [error] … ins Log, schickt die Benachrichtigung ohne den Zusatz „Unerwarteter Fehler" und beendet sich mit Exit-Code 65.
  • process_queue.py: NO_RETRY_EXIT_CODES = {65} — solche Einträge gehen sofort auf failed, ohne Wiederholungen und ohne Pause. lastError zeigt dank des Logs die Meldung.

Geprüft:

  • 8 Unit-Tests (skills/videowatch/tests/test_unusable_source.py, python3 -m unittest discover -s tests): PNG, Textdatei mit Video-Endung und fehlende Datei werden korrekt behandelt; stummes Video, reines Audio und Video mit anderer Endung werden angenommen; Exit-Code 65 gibt failed nach einem Versuch ohne Pause, Exit-Code 1 wird weiter wiederholt.
  • Die echte Screenshot-Datei vom 2026-10-16 liefert Keine Video- oder Audiodatei: Bildschirmfoto 2026-10-16 um 14.06.21.png.

Nicht geprüft / nicht umgesetzt:

  • Kein Lauf von watch_local.py und der Queue mit einem Bild. watch_local.py nimmt vor der Pipeline die globale Sequenz-Sperre; ich wollte nicht in eine laufende Queue eingreifen.
  • Der optionale frühe Abweis beim Hinzufügen (POST /videowatch/playlist und .../items, Mac- und Linux-Server) ist nicht umgesetzt. Der Eintrag entsteht weiter in der Queue und scheitert, sobald er an der Reihe ist. Er steht dann sofort auf failed mit klarer Meldung und lässt sich löschen (siehe iris/Iris#50).
  • Der Linux-Server nutzt vermutlich dasselbe process_queue.py; das habe ich nicht geprüft.
  • Bilder bekommen keine eigene Verarbeitung (Bildbeschreibung). Das wäre ein eigenes Feature.

Die Änderung ist über den Symlink ~/.hermes/skills/videowatch sofort für neue Läufe aktiv. Ein bereits laufender process_queue.py behält bis zu seinem Ende den alten Stand.

## Stand 2026-10-16: Worker-Teil umgesetzt (alf/2ndbrain PR #63) **Geändert** (`skills/videowatch/`): - `download.py`: `resolve_local()` prüft per `ffprobe`, ob die Datei Audio oder einen Videostream mit mindestens 0,5 s Dauer enthält. Sonst `UnusableSourceError("Keine Video- oder Audiodatei: <Name>")`. Die Endung allein entscheidet nicht (ein Video mit Endung `.bin` wird angenommen, eine Textdatei `.mp4` abgewiesen). Ein Video ohne Ton gilt weiter als gültig. Fehlt `ffprobe`, wird nicht abgewiesen, der spätere Schritt meldet das selbst. - `watch_local.py`: fängt den Fehler getrennt ab, schreibt `[error] …` ins Log, schickt die Benachrichtigung ohne den Zusatz „Unerwarteter Fehler" und beendet sich mit Exit-Code 65. - `process_queue.py`: `NO_RETRY_EXIT_CODES = {65}` — solche Einträge gehen sofort auf `failed`, ohne Wiederholungen und ohne Pause. `lastError` zeigt dank des Logs die Meldung. **Geprüft:** - 8 Unit-Tests (`skills/videowatch/tests/test_unusable_source.py`, `python3 -m unittest discover -s tests`): PNG, Textdatei mit Video-Endung und fehlende Datei werden korrekt behandelt; stummes Video, reines Audio und Video mit anderer Endung werden angenommen; Exit-Code 65 gibt `failed` nach einem Versuch ohne Pause, Exit-Code 1 wird weiter wiederholt. - Die echte Screenshot-Datei vom 2026-10-16 liefert `Keine Video- oder Audiodatei: Bildschirmfoto 2026-10-16 um 14.06.21.png`. **Nicht geprüft / nicht umgesetzt:** - Kein Lauf von `watch_local.py` und der Queue mit einem Bild. `watch_local.py` nimmt vor der Pipeline die globale Sequenz-Sperre; ich wollte nicht in eine laufende Queue eingreifen. - Der optionale frühe Abweis beim Hinzufügen (`POST /videowatch/playlist` und `.../items`, Mac- und Linux-Server) ist **nicht** umgesetzt. Der Eintrag entsteht weiter in der Queue und scheitert, sobald er an der Reihe ist. Er steht dann sofort auf `failed` mit klarer Meldung und lässt sich löschen (siehe iris/Iris#50). - Der Linux-Server nutzt vermutlich dasselbe `process_queue.py`; das habe ich nicht geprüft. - Bilder bekommen keine eigene Verarbeitung (Bildbeschreibung). Das wäre ein eigenes Feature. Die Änderung ist über den Symlink `~/.hermes/skills/videowatch` sofort für neue Läufe aktiv. Ein bereits laufender `process_queue.py` behält bis zu seinem Ende den alten Stand.
Author
Owner

PR #64 gemergt: fix(videowatch): yt-dlp-Grund in der Meldung, dauerhafte Fehler ohne Wiederholung (iris/Iris#54)

download.py fängt stderr von yt-dlp ab (vorher am Lauf-Log vorbei) und nimmt die letzte ERROR-Zeile
in die Meldung auf. Unsupported URL, Private video, Video unavailable u. ä. beenden den Lauf mit
Exit-Code 65 (UnusableSourceError), ohne Wiederholungen; 403/429 bleiben wiederholbar.
process_queue.py: Präfix SystemExit aus lastError entfernt. 5 neue Tests.

Co-Authored-By: Claude Sonnet 5.5 noreply@anthropic.com
alf/2ndbrain#64

Commits:

  • fix(videowatch): yt-dlp-Grund in der Meldung, dauerhafte Fehler ohne Wiederholung (iris/Iris#54)
PR #64 gemergt: fix(videowatch): yt-dlp-Grund in der Meldung, dauerhafte Fehler ohne Wiederholung (iris/Iris#54) download.py fängt stderr von yt-dlp ab (vorher am Lauf-Log vorbei) und nimmt die letzte ERROR-Zeile in die Meldung auf. Unsupported URL, Private video, Video unavailable u. ä. beenden den Lauf mit Exit-Code 65 (UnusableSourceError), ohne Wiederholungen; 403/429 bleiben wiederholbar. process_queue.py: Präfix SystemExit aus lastError entfernt. 5 neue Tests. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> https://forgejo.lewerken.duckdns.org/alf/2ndbrain/pulls/64 Commits: - fix(videowatch): yt-dlp-Grund in der Meldung, dauerhafte Fehler ohne Wiederholung (iris/Iris#54)
Author
Owner

PR #11 gemergt: fix(videowatch): Fehler- und Hinweismeldung der Queue verschwindet nach 10 Sekunden (iris/Iris#54)

Co-Authored-By: Claude Sonnet 5.5 noreply@anthropic.com
iris/2ndbrain-ios#11

Commits:

  • fix(videowatch): Fehler- und Hinweismeldung der Queue verschwindet nach 10 Sekunden (iris/Iris#54)
PR #11 gemergt: fix(videowatch): Fehler- und Hinweismeldung der Queue verschwindet nach 10 Sekunden (iris/Iris#54) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> https://forgejo.lewerken.duckdns.org/iris/2ndbrain-ios/pulls/11 Commits: - fix(videowatch): Fehler- und Hinweismeldung der Queue verschwindet nach 10 Sekunden (iris/Iris#54)
Author
Owner

PR #55 gemergt: fix(videowatch): Fehler- und Hinweismeldung der Queue verschwindet nach 10 Sekunden (iris/Iris#54)

Co-Authored-By: Claude Sonnet 5.5 noreply@anthropic.com
#55

Commits:

  • fix(videowatch): Fehler- und Hinweismeldung der Queue verschwindet nach 10 Sekunden (iris/Iris#54)
PR #55 gemergt: fix(videowatch): Fehler- und Hinweismeldung der Queue verschwindet nach 10 Sekunden (iris/Iris#54) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> https://forgejo.lewerken.duckdns.org/iris/Iris/pulls/55 Commits: - fix(videowatch): Fehler- und Hinweismeldung der Queue verschwindet nach 10 Sekunden (iris/Iris#54)
Author
Owner

Nachtrag 2026-10-16: yt-dlp-Grund, keine Wiederholung bei dauerhaften Fehlern, Meldung räumt sich auf

Anlass: Beim bewussten Testen mit falschen Eingaben zeigten zwei Einträge nur SystemExit: yt-dlp did not produce a video file in /var/folders/… (exit 1), und die Queue versuchte beide dreimal. Die wirklichen Gründe, mit yt-dlp --simulate geprüft: für die Adobe-Learn-Seite Unsupported URL, für hsyuLbgtQw8 (vierter Eintrag der Playlist) Private video.

Ursache der fehlenden Meldung: subprocess.run(..., stderr=sys.stderr) reicht den echten Dateideskriptor weiter. Die ERROR:-Zeile von yt-dlp erreichte deshalb das Lauf-Log nicht, das nur über Pythons eigenen Schreiber mitschreibt.

Geändert

  • alf/2ndbrain #64, skills/videowatch/download.py: stderr von yt-dlp wird abgefangen, ins Log weitergereicht, und die letzte ERROR:-Zeile kommt in die Meldung. Dauerhafte Gründe (Unsupported URL, Private video, Video unavailable, has been removed, is not available, members-only, only available to) lösen UnusableSourceError aus, also Exit-Code 65 und kein Wiederholen. HTTP 403/429 und „Sign in to confirm you're not a bot" bleiben bewusst wiederholbar. Bei Fehlern ohne ERROR:-Zeile bleibt der Exit-Code in der Meldung.
  • process_queue.py: Das Präfix SystemExit: fällt aus lastError weg.
  • iris/Iris #55 und iris/2ndbrain-ios #11: Fehler- und Hinweismeldung der Queue verschwinden nach 10 Sekunden (vorher blieb zum Beispiel die Ablehnung eines Löschversuchs stehen, bis die nächste Aktion kam).

Geprüft: 13 Unit-Tests insgesamt (5 neu: Unsupported URL, Private video, wiederholbarer 403, Fehler ohne Grundzeile, Präfix); mit den echten URLs aus dem Test über download.py: yt-dlp: [youtube] hsyuLbgtQw8: Private video und yt-dlp: Unsupported URL: https://www.adobe.com/…. Builds von Iris.xcodeproj und der iOS-App sind erfolgreich.

Nicht geprüft / offen

  • Kein Durchlauf in der Oberfläche; die laufende Iris.app hat die Meldungs-Änderung erst nach einem Neubau, die Worker-Änderung ist über den Symlink schon aktiv.
  • Die Liste der dauerhaften Gründe stammt aus den yt-dlp-Meldungen, die ich kenne. Meldungen anderer Seiten oder Sprachen werden nicht erkannt und bleiben wiederholbar.
  • Der frühe Abweis beim Hinzufügen (Mac- und Linux-Server) ist weiter nicht umgesetzt.
## Nachtrag 2026-10-16: yt-dlp-Grund, keine Wiederholung bei dauerhaften Fehlern, Meldung räumt sich auf **Anlass:** Beim bewussten Testen mit falschen Eingaben zeigten zwei Einträge nur `SystemExit: yt-dlp did not produce a video file in /var/folders/… (exit 1)`, und die Queue versuchte beide dreimal. Die wirklichen Gründe, mit `yt-dlp --simulate` geprüft: für die Adobe-Learn-Seite `Unsupported URL`, für `hsyuLbgtQw8` (vierter Eintrag der Playlist) `Private video`. **Ursache der fehlenden Meldung:** `subprocess.run(..., stderr=sys.stderr)` reicht den echten Dateideskriptor weiter. Die `ERROR:`-Zeile von yt-dlp erreichte deshalb das Lauf-Log nicht, das nur über Pythons eigenen Schreiber mitschreibt. **Geändert** - alf/2ndbrain #64, `skills/videowatch/download.py`: `stderr` von yt-dlp wird abgefangen, ins Log weitergereicht, und die letzte `ERROR:`-Zeile kommt in die Meldung. Dauerhafte Gründe (`Unsupported URL`, `Private video`, `Video unavailable`, `has been removed`, `is not available`, `members-only`, `only available to`) lösen `UnusableSourceError` aus, also Exit-Code 65 und kein Wiederholen. HTTP 403/429 und „Sign in to confirm you're not a bot" bleiben bewusst wiederholbar. Bei Fehlern ohne `ERROR:`-Zeile bleibt der Exit-Code in der Meldung. - `process_queue.py`: Das Präfix `SystemExit:` fällt aus `lastError` weg. - iris/Iris #55 und iris/2ndbrain-ios #11: Fehler- und Hinweismeldung der Queue verschwinden nach 10 Sekunden (vorher blieb zum Beispiel die Ablehnung eines Löschversuchs stehen, bis die nächste Aktion kam). **Geprüft:** 13 Unit-Tests insgesamt (5 neu: Unsupported URL, Private video, wiederholbarer 403, Fehler ohne Grundzeile, Präfix); mit den echten URLs aus dem Test über `download.py`: `yt-dlp: [youtube] hsyuLbgtQw8: Private video` und `yt-dlp: Unsupported URL: https://www.adobe.com/…`. Builds von `Iris.xcodeproj` und der iOS-App sind erfolgreich. **Nicht geprüft / offen** - Kein Durchlauf in der Oberfläche; die laufende Iris.app hat die Meldungs-Änderung erst nach einem Neubau, die Worker-Änderung ist über den Symlink schon aktiv. - Die Liste der dauerhaften Gründe stammt aus den yt-dlp-Meldungen, die ich kenne. Meldungen anderer Seiten oder Sprachen werden nicht erkannt und bleiben wiederholbar. - Der frühe Abweis beim Hinzufügen (Mac- und Linux-Server) ist weiter nicht umgesetzt.
Author
Owner

Geschlossen auf Wunsch von Alf nach eigener Prüfung: funktioniert. Umgesetzt in alf/2ndbrain #63 und #64, iris/Iris #55, iris/2ndbrain-ios #11. Offen geblieben und bewusst nicht Teil dieses Issues: der frühe Abweis beim Hinzufügen (Mac- und Linux-Server).

Geschlossen auf Wunsch von Alf nach eigener Prüfung: funktioniert. Umgesetzt in alf/2ndbrain #63 und #64, iris/Iris #55, iris/2ndbrain-ios #11. Offen geblieben und bewusst nicht Teil dieses Issues: der frühe Abweis beim Hinzufügen (Mac- und Linux-Server).
alf closed this issue 2026-10-16 13:28:40 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
iris/Iris#54
No description provided.