Make rendering failure-safe and project editing reproducible

This commit is contained in:
Mikei386 committed 2026-09-13 09:20:37 +02:00
1 parent c530fe025a
commit 73961f6afe
13 files changed
+1019 -212

No files matched your search

+2
View File
@@ -1,5 +1,7 @@
# Technische Bestandsaufnahme
> Historische Bestandsaufnahme vor Version 0.3.0. Umgesetzte Korrekturen und aktuelle Grenzen stehen in [VERBESSERUNGEN.md](VERBESSERUNGEN.md).
Stand: 13. September 2026, Ausgangscommit `0b85f7d73a8ae09a8711038a4d08ae34642c6243`.
## Bestand
+109
View File
@@ -0,0 +1,109 @@
# Funktionsanalyse GrowthLapse
> Historische Bestandsaufnahme vor Version 0.3.0. Umgesetzte Korrekturen und aktuelle Grenzen stehen in [VERBESSERUNGEN.md](VERBESSERUNGEN.md).
Stand: 13. September 2026, Commit `c530fe0`. Grundlage ist die Prüfung der aktiven Quellcodepfade. Die unten angegebenen Szenarien sind aus dem Code hergeleitet, nicht durch vollständige UI-/Video-Tests reproduziert. Es wurden keine Laufzeitfunktionen geändert.
## Funktionsumfang und Ablauf
1. **Import:** Dateien eines Ordners einlesen, Ausgabe ausschließen, Dauer und Abmessungen mit FFprobe ermitteln, sortieren und Varianten auswählen.
2. **Segmentplanung:** Ausschnitt aus Mitte/Offset oder anhand von Gesicht-/Augenbewertung wählen. Segmentlänge auf Quelldauer begrenzen.
3. **Verarbeitung:** Optional stabilisieren, Gesicht ausrichten, Geschwindigkeit und Format normalisieren. Audio entfernen oder zeitlich anpassen; bei fehlendem Audio eine stille Spur erzeugen.
4. **Zusammenfügen:** Ohne Übergänge Stream-Copy; mit Übergängen Video-Xfade und optional Audio-Crossfade.
5. **Nachbearbeitung:** Projekt speichern/laden, Segmentstarts und Varianten ändern, Clips umsortieren und Cache wiederverwenden.
Die Funktionen decken einen persönlichen Wachstums-Zeitraffer gut ab. Der größte Verbesserungsbedarf liegt bei verlässlicher Nachbearbeitung und Erhaltung bereits erstellter Ergebnisse.
## Priorisierte Befunde
### P1: Ausgabeziel und Projekt laufen beim erneuten Rendern auseinander
**Szenario:** Projekt A rendern, in der Oberfläche Ausgabe B wählen, „Änderungen neu rendern“ ausführen.
**Befund:** `VideoProcessor.swift:243` verwendet das neue Ziel und erstellt dessen Arbeitsordner. Bei Zeile 275 wird aber das alte Projekt unverändert übernommen. Dessen `outputFilePath`, `cacheDirectoryPath` und Clip-Pfade zeigen weiter auf A; `saveProject` bei Zeile 1638 speichert entsprechend bei A. Auch die gespeicherten Zielabmessungen werden bei Formatänderungen nicht aktualisiert.
**Folge:** Video B und gespeichertes Projekt passen nicht zusammen. Bei fehlendem alten Cache können Schreibzugriffe auf die alten Clip-Pfade scheitern, obwohl der neue Cache angelegt wurde.
**Vorschlag:** Einen expliziten „Projekt speichern unter“-Ablauf einführen. Ausgabe, Cache, Clip-Pfade und Zielabmessungen gemeinsam aktualisieren; vorhandene gültige Clips kontrolliert übernehmen.
**Abnahmetest:** A nach B exportieren, B-Projekt laden und einen Clip erneut rendern. A bleibt unverändert, alle B-Verweise sind konsistent.
### P1: Abbruch und Fehler können vorhandene Ergebnisse oder Cache vernichten
**Befund:** `handleCancellation` (`VideoProcessor.swift:2054`) löscht `temporaryDirectory` vollständig, auch wenn dies der bestehende Review-Cache ist. Ein neuer Render löscht den alten Cache bereits bei `createWorkingDirectory` (Zeile 1469), vor erfolgreichem Import. FFmpeg schreibt mit `-y` direkt ins Ausgabeziel; `replaceOutput` (Zeile 1650) löscht zunächst das alte Ergebnis und kopiert danach.
**Folge:** Ein abgebrochener Nachbearbeitungsversuch entfernt auch unveränderte Cache-Clips. Ein Fehler während der Endausgabe kann ein zuvor gutes Video durch eine unvollständige Datei ersetzen.
**Vorschlag:** Neue oder geänderte Clips und Endausgabe zunächst in einen separaten Arbeitsbereich schreiben, nach Erfolg übernehmen. Bei Abbruch nur Dateien des aktuellen Durchlaufs entfernen. Bereits bestätigte Ergebnisse bis zur erfolgreichen Übernahme erhalten.
**Abnahmetest:** Ein vorhandenes Ergebnis samt Cache sichern, Neurender während Normalisierung und Endausgabe abbrechen sowie einen Schreibfehler provozieren. Das bisherige Ergebnis bleibt abspielbar und unveränderte Cache-Clips bleiben erhalten.
### P1: Cache-Löschung vertraut ungeprüften Projektpfaden
**Befund:** `loadProject` (`VideoProcessor.swift:160`) decodiert externe JSON-Pfade ohne Verzeichnisvalidierung. „Ergebnis bestätigen“ entfernt bei Zeile 191 rekursiv genau `cacheDirectoryPath`.
**Folge:** Eine falsch bearbeitete oder fremde Projektdatei kann ein anderes beschreibbares Verzeichnis als Cache deklarieren. Die Löschaktion ist nicht auf einen von GrowthLapse erzeugten Cache begrenzt.
**Vorschlag:** Cache-Verzeichnis über eine eigene Kennung und validierte Projektzuordnung absichern; Pfade einschließlich Symlinks prüfen. Ungültige Projekte vor Übernahme ablehnen. Löschfehler anzeigen, statt anschließend immer Erfolg zu protokollieren.
**Abnahmetest:** Ein Projekt verweist auf einen separaten Testordner mit einer Markerdatei. Laden oder Löschen wird abgelehnt; Marker bleibt erhalten. Ausschließlich mit temporären Testverzeichnissen prüfen.
### P2: Globale Segmentparameter werden bei Nachbearbeitung ignoriert
**Szenario:** Nach dem ersten Render die Ausschnittlänge von 8 auf 4 Sekunden ändern und erneut rendern.
**Befund:** `normalizeVideos` (`VideoProcessor.swift:915`) verwendet weiterhin `projectClip.segmentLength`. `makeProject` und `initialSegmentStart` laufen nur für neue Projekte. Der Fingerprint (Zeile 1580) enthält weder Ausschnittlänge noch Offset oder automatische Segmentwahl.
**Folge:** Die Oberfläche suggeriert die Übernahme geänderter Einstellungen, die Segmentplanung bleibt jedoch unverändert. Auch die globale Variantenwahl wird beim Neurender nicht erneut angewandt.
**Vorschlag:** Einstellungen als „nur für neuen Import“ kennzeichnen oder eine ausdrückliche Aktion „Segmente neu berechnen“ anbieten. Manuelle Clip-Korrekturen dabei gezielt erhalten oder nach Auswahl ersetzen.
**Abnahmetest:** Globale Änderung verändert die geplanten Clips nachvollziehbar oder die Oberfläche erklärt eindeutig, warum sie nicht gilt.
### P2: Eingebrannte Clipnummern bleiben nach Umsortieren veraltet
**Befund:** `reorderedProject` (`VideoProcessor.swift:1603`) ändert `index`, setzt aber nicht `needsRender`. Der Fingerprint berücksichtigt keine Reihenfolge. `normalizeVideos` verwendet gültige Cache-Clips unverändert; darin ist die Nummer bereits eingebrannt.
**Folge:** Nach geänderter Sortierung stimmen Nummer im Video und Position in der Projektliste nicht mehr überein.
**Vorschlag:** Bei aktivierten Nummern verschobene Clips invalidieren oder Nummern erst beim finalen Export einblenden.
**Abnahmetest:** Zwei Clips mit Nummern rendern, Reihenfolge wechseln, neu rendern. Sichtbare Nummern folgen der neuen Position.
### P2: STOP erreicht laufende Bildanalysen nicht direkt
**Befund:** `BestSegmentAnalyzer.detectBestSegment` (Zeile 2459) und `FaceAlignmentAnalyzer.detect` (Zeile 2605) starten `Task.detached` und warten auf `.value`. Ein Handle zur expliziten Weiterleitung des Abbruchs fehlt. Die Abbruchprüfungen laufen innerhalb des eigenständigen Tasks.
**Folge:** STOP kann während einer umfangreichen Analyse bis zu deren Ende warten, obwohl der äußere Render-Task bereits abgebrochen ist.
**Vorschlag:** Analyse-Task per Cancellation-Handler explizit abbrechen und CancellationError nicht als gewöhnlichen Analyse-Fallback behandeln.
**Abnahmetest:** Lange Analyse abbrechen; messen, dass nach Abschluss der gerade laufenden Einzeloperation keine weiteren Frames analysiert werden.
### P2: Projekte speichern keine vollständigen Render-Einstellungen
**Befund:** `GrowthLapseProject` speichert Clipdaten und Fingerprint, aber keinen vollständigen Einstellungssatz. `ContentView.swift:620` lädt nur Ausgabe- und Eingabepfad ins aktuelle Einstellungsmodell.
**Folge:** Projekt A nach Arbeit an B laden und neu rendern kann A mit den globalen Einstellungen von B erzeugen. Ein Fingerprint erkennt Unterschiede, stellt aber die ursprünglichen Werte nicht wieder her.
**Vorschlag:** Versioniertes Projektschema mit Render-Einstellungen; Migration alter Dateien mit sichtbarem Hinweis. Werkzeugsuche und andere reine Rechnerpräferenzen separat halten.
**Abnahmetest:** Zwei Projekte mit verschiedenen FPS, Audio- und Ausgabeformaten abwechselnd laden; jedes stellt seine eigenen Einstellungen wieder her.
## Weitere Verbesserungen
- **Vorabprüfung:** Filter und Encoder vor dem Rendern vollständig prüfen. VidStab-Fallback darf Deshake nur wählen, wenn vorhanden (`VideoProcessor.swift:568`).
- **Cache-Gültigkeit:** Quellgröße und Änderungszeit oder einen Inhaltshash erfassen. Ein extern ersetztes Video am selben Pfad invalidiert aktuell keinen Cache automatisch.
- **Projektvalidierung:** Leere Cliplisten, ungültige Längen, fehlende Quellen und inkonsistente Pfade ablehnen. `videos[0]` in Zeile 271 setzt eine nicht leere Liste voraus; die Oberfläche verhindert nicht alle Wege mit einem leeren geladenen Projekt.
- **Prozessausgabe:** Den Pipe-Reader bis EOF auslesen und Exit sowie Ausgabe synchron zusammenführen (`FFmpegService.swift:137`). Ob heute Ausgabe verloren geht, muss ein gezielter Stresstest klären.
- **Skalierung:** Xfade öffnet alle Clips in einem Prozess (`VideoProcessor.swift:1387`). Mit 10/50/100 Clips Speicherbedarf und Laufzeit messen, dann gegebenenfalls blockweise rendern. Ein Ressourcenproblem ist hier noch nicht gemessen.
- **Bedienung:** Importliste vor dem Rendern, geschätzte Enddauer, Vergleich Original/Ergebnis, sichtbare Kennzeichnung gecachter und neu zu rendernder Clips. Gesichtsauswahl bei mehreren Personen wäre eine sinnvolle Erweiterung.
- **Portabilität:** Relative Projektpfade und eine Funktion zum Wiederfinden verschobener Quellen ergänzen.
## Empfohlene Reihenfolge
1. Ausgabe und Cache gegen Abbruch/Fehler schützen, geladene Pfade validieren.
2. Projektziele und Einstellungen konsistent machen; Segment-Neuberechnung und Cache-Invalidierung klären.
3. STOP für Analysen, Werkzeug-Vorabprüfung und Prozessausgabe absichern.
4. Automatisierte Integrationstests mit synthetischen Videos ergänzen: ein/zwei Clips, Audio gemischt, Übergänge an/aus, Formatwechsel, Neurender, Speichern/Laden und Abbruch. Dauer, Auflösung, FPS und Audiospuren per FFprobe prüfen.
5. Erst danach größere Komfortfunktionen oder das deaktivierte Foto-Morphing ausbauen.
+49
View File
@@ -0,0 +1,49 @@
# GrowthLapse 0.3.0 – zuverlässige Nachbearbeitung
## Änderungen
- Jeder Render erhält einen eigenen Arbeitsbereich. Bestehende Zwischenclips werden nur gelesen/kopiert. Abbruch und Renderfehler entfernen ausschließlich den neuen Arbeitsbereich.
- Video und Projektdatei werden erst nach erfolgreichem Rendern übernommen. Dateiaustausch erfolgt per Rename; bei einem nachfolgenden Fehler wird zurückgerollt. Scheitert auch die Wiederherstellung, bleiben Sicherungen erhalten und ihr Pfad wird angezeigt.
- Ausgabeziel, Cache-Pfade und Projektabmessungen bleiben beim Neurender und bei einem neuen Ausgabeziel konsistent. Das ursprüngliche Projekt bleibt beim Export unter anderem Namen erhalten.
- Cache-Löschung verlangt eine Eigentumsmarkierung und passende Verzeichniszuordnung; Symlinks werden abgelehnt. Historische unmarkierte Caches werden nicht automatisch entfernt.
- Projektschema 2 speichert Render-Einstellungen. Alte Projekte bleiben lesbar; fehlende Einstellungen werden mit einem Hinweis kenntlich gemacht. Lokal gewählte FFmpeg-/FFprobe-Pfade werden beim Laden erhalten.
- Geänderte Quelldateien werden anhand von Größe/Änderungsdatum erkannt, erneut geprüft und neu gerendert. Segmentgrenzen werden an eine geänderte Quelldauer angepasst.
- Geänderte Reihenfolge invalidiert verschobene Clips, sodass eingebrannte Nummern korrekt erneuert werden.
- „Änderungen neu rendern“ erhält manuelle Ausschnitte. „Segmente neu planen“ wendet Länge, Offset und automatische Segmentwahl auf alle vorhandenen Clips an.
- Bildanalysen erhalten den Abbruch des aufrufenden Render-Tasks. FFmpeg-Aufrufe besitzen einen eigenen Abbruchzustand und lesen ihre Ausgabe bis EOF.
- Fehlende Encoder/Stabilisierungsfilter führen vor der Verarbeitung zu einer verständlichen Fehlermeldung.
- Leere/inkonsistente Projekte, ungültige Clipdaten und versehentlich gewählte Quellvideos als neue Ausgabe werden abgefangen.
- Nachbearbeitung ist während eines Renders gesperrt. Die Oberfläche zeigt die erwartete Ergebnisdauer, bietet eine Ergebnisvorschau und macht den Clip-Editor scrollbar.
- Versionierte Bundle-Metadaten liegen unter `Resources/Info.plist`; die historische App in `dist/` wird nicht als aktuelle Version ausgegeben.
## Verifikation
`bash scripts/integration-tests.sh` kompiliert die produktiven Render-Klassen ohne XCTest und prüft mit synthetischen Videos:
1. Neutrale Startwerte, Einstellungs-Roundtrip und ältere JSON-Einstellungen.
2. Vollständige Ausgabe kurzlebiger Prozesse einschließlich Unicode sowie Prozessabbruch.
3. Abbruchweiterleitung an eine Bildanalyse.
4. Zwei-Clip-Render mit Originalauflösung und entfernter Tonspur.
5. Ablehnung von Cache-Symlinks und versehentlichem Überschreiben von Quellen.
6. Erhalt der bisherigen Dateien bei ungültigem Ausgabeziel.
7. Neues Ausgabeziel, Cache-Wiederverwendung, Projektdatei und erneutes Laden.
8. Erhalt von Video/Projekt bei simuliertem FFmpeg-Fehler in der Endausgabe.
9. Wiederherstellung nach einem Fehler beim zweiten Dateiaustausch.
10. Erhalt manueller Ausschnitte, explizite Neuplanung und Invalidierung bei Sortierung.
11. Überblendung mit gemischten Quellen mit/ohne Audio; gemessene Gesamtdauer 1,8 Sekunden.
12. Abbruch während laufender Endausgabe ohne Verlust des alten Videos/Caches.
13. Erneute Metadatenanalyse und gültige Segmentgrenzen nach Änderung einer Quelle.
14. Einzelclip mit Stabilisierung und Vision-Fallback bei fehlendem Gesicht.
15. Schutz fremder Verzeichnisse, Ablehnung leerer Projekte, sofortiger Abbruch und kontrollierte Cache-Löschung.
Diese Integrationstests sind auf dem lokalen Mac bestanden. Die bestehenden XCTest-Dateien benötigen weiterhin vollständiges Xcode; ihre Einstellungsfälle werden zusätzlich im Integrationstest geprüft. Release-Build und lokale Ad-hoc-Signierung funktionieren. Projektladen, Neurender, das korrigierte Clip-Layout und Wiedergabe in der neuen Ergebnisvorschau wurden zusätzlich über die native Oberfläche mit Testdateien geprüft.
## Verbleibende Grenzen
- Die Übernahme mehrerer Dateien ist nicht gegen einen Stromausfall zwischen zwei Dateiaustauschen abgesichert.
- Während des Renders wird zusätzlicher Speicherplatz für neue Clips und Sicherungen benötigt.
- Cache-Erkennung nutzt Größe und Änderungsdatum, keinen vollständigen Inhaltshash.
- Reale Gesichtsaufnahmen, HDR-Farben und sehr große Clipmengen benötigen weiterhin Qualitäts-/Belastungstests. Synthetische Bilder belegen keine Qualität der Gesichtsausrichtung.
- Foto-Morphing bleibt deaktiviert. Notarisierung, universelle Builds und Lizenzentscheidung sind nicht Teil dieser Überarbeitung.
Für isolierte Oberflächentests kann `GROWTHLAPSE_SETTINGS_PATH` auf einen absoluten Pfad zu einer separaten Einstellungsdatei gesetzt werden.