|
|
3 weeks ago | |
|---|---|---|
| Sources | 1 month ago | |
| Tests/DropTwoCoreTests | 1 month ago | |
| assets | 1 month ago | |
| scripts | 1 month ago | |
| site | 3 weeks ago | |
| .gitignore | 1 month ago | |
| README.md | 1 month ago | |
| project.yml | 1 month ago | |
README.md
drop.two
9:16 rein. 9:16 und 4:5 raus.
Warum
Alle Videos werden im Format 9:16 geschnitten. Nach der Freigabe müssen sie zusätzlich als 4:5 abgelegt werden. Das Framing wird beim Schnitt bereits so angelegt, dass der 4:5-Ausschnitt funktioniert — es braucht also keine zweite Timeline, sondern nur einen sauberen, mittigen Beschnitt des fertigen Masters.
Bisher passiert das über ein selbstgebautes Python-CLI. drop.two macht daraus ein Werkzeug, das auch Kolleginnen und Kollegen ohne Terminal benutzen können: Dateien reinziehen, Ziel prüfen, fertig.
Was die App macht
- Eine oder mehrere 9:16-Dateien werden ausgewählt oder per Drag & Drop übergeben.
- Aus dem Dateinamen wird das Projekt gelesen.
- Im Zielordner entsteht ein Unterordner mit dem Projektnamen.
- Dort landen beide Fassungen: das unveränderte 9:16-Original und die neu gerenderte 4:5-Version.
Kein Preset-Dschungel, keine Timeline, kein Export-Dialog.
Namenskonvention
[Projekt]-[Format]-[Version]-[Sprache].[ext]
Beispiel:
SOMOS-9x16-v3-DE.mp4 → SOMOS/SOMOS-9x16-v3-DE.mp4
SOMOS/SOMOS-4x5-v3-DE.mp4
Parsing-Regel: Es wird von rechts gelesen. Die letzten drei Segmente sind Sprache, Version und Format; alles davor ist der Projektname. Nur so bleiben Projektnamen mit eigenem Bindestrich intakt:
Somos-Pendant-9x16-v3-DE.mp4
└──── Projekt ────┘ └Fmt┘└Ver┘└Spr┘
Für die Zielversion wird ausschließlich das Format-Segment ersetzt: 9x16 → 4x5. Alle anderen Segmente bleiben zeichengleich erhalten.
Abbruchbedingungen — die App verarbeitet nicht und meldet es sichtbar:
- Dateiname entspricht nicht dem Schema (weniger als vier Segmente)
- Format-Segment ist nicht
9x16 - Quelldatei hat kein 9:16-Seitenverhältnis
- Zieldatei existiert bereits (überschreiben nur nach Rückfrage)
Crop-Logik
Der 4:5-Ausschnitt behält die volle Breite und beschneidet oben und unten:
Breite bleibt unverändert
Höhe = Breite × 5 ÷ 4 (auf gerade Zahl gerundet)
Anker vertikal zentriert (Offset später konfigurierbar)
| Quelle | Ziel |
|---|---|
| 1080 × 1920 | 1080 × 1350 |
| 2160 × 3840 | 2160 × 2700 |
Codec-Verhalten: Der Quell-Codec wird erkannt und passend ausgespielt — ProRes bleibt ProRes, H.264 bleibt H.264 mit vergleichbarer Bitrate. Die Audiospur läuft per Passthrough durch, ohne Neukodierung. Framerate, Farbraum und Dauer bleiben unangetastet.
Funktionsumfang
MVP
- Dateiauswahl und Drag & Drop
- Einstellbarer Quellordner (Dialog öffnet direkt dort)
- Einstellbarer Zielordner, Projekt-Unterordner wird automatisch angelegt
- Dateiauswahl vorsortiert nach zuletzt geändert
- Fortschrittsanzeige pro Datei und gesamt
- Fehlerliste statt stiller Abbrüche
Danach
- Review-Ansicht: 9:16-Master mit eingeblendetem 4:5-Rahmen zur Framing-Kontrolle, scrubbar
- Menu-Bar-Betrieb mit Drop-Target
- Vertikaler Crop-Offset pro Datei justierbar
- In-App-Updates über Sparkle
- Batch-Verlauf der letzten Durchläufe
- Hilfe-Bereich: klickbare Kurzanleitung zur Bedienung der App
- Rechtlich erforderliche Angaben (Impressum o.ä.) einbinden — Absicherung, wo genau (in-App, Download-Seite) noch offen
Tech-Stack
Swift + SwiftUI, macOS 13+.
| Baustein | Lösung |
|---|---|
| Oberfläche | SwiftUI, MenuBarExtra für den Hintergrundbetrieb |
| Video | AVFoundation — hardwarebeschleunigt über VideoToolbox |
| Review-Player | AVPlayer mit Overlay |
| Updates | Sparkle 2 gegen appcast.xml auf eigenem Server |
| Einstellungen | @AppStorage + Security-Scoped Bookmarks für Ordnerzugriff |
| Projektdatei | XcodeGen (project.yml) — textbasiert, merge-freundlich |
| Paket | Signiertes .dmg, ca. 5 MB |
Warum kein ffmpeg: Der Beschnitt ist rein geometrisch. AVFoundation erledigt ihn nativ über eine AVMutableVideoComposition. Das spart rund 80 MB Bundle-Größe, die GPL-Frage und ein mitzulieferndes Binary.
Warum nicht Python: py2app- und PyInstaller-Bundles sind fragil, starten träge, wiegen ein Vielfaches und machen Code-Signing sowie Notarisierung unnötig schwer. Für ein Werkzeug, das Kollegen installieren sollen, ist das der falsche Unterbau.
Architektur
DropTwoCore Framework, komplett UI-frei
├── FileNameParser zerlegt und baut Dateinamen
├── VideoInspector liest Dimension, Codec, Framerate, Dauer
├── CropEngine AVAsset → VideoComposition → Export
└── JobQueue async/await, 1–2 parallele Exports
DropTwo App-Target
├── Settings Pfade, Bookmarks, Presets
├── DropZone Auswahl und Drag & Drop
├── ProgressView Fortschritt und Fehlerliste
└── ReviewSheet AVPlayer mit 4:5-Overlay
droptwo-cli Kommandozeilen-Target gegen denselben Core
Der Kern kennt keine Oberfläche. Das hält ihn testbar und macht das CLI-Target zum ehrlichen Prüfstein: Was dort funktioniert, funktioniert in der App.
Projektstruktur
drop.two/
├── project.yml XcodeGen-Konfiguration
├── Sources/
│ ├── DropTwoCore/
│ ├── DropTwo/
│ └── DropTwoCLI/
├── Tests/
│ └── DropTwoCoreTests/
├── assets/
│ ├── icon.svg Bildmarke
│ └── icon-menubar.svg Template-Variante für die Menu-Bar
├── scripts/
│ ├── build.sh
│ └── release.sh
└── docs/
Die .xcodeproj wird nicht eingecheckt — sie entsteht aus project.yml.
Einrichtung
Voraussetzungen
- Xcode (vollständig, aus dem App Store) — wegen macOS-SDK,
xcodebuildundnotarytool - Homebrew
brew install xcodegen swiftformat
git clone https://git.samuelzielke.de/samuelzielke/drop.two.git
cd drop.two
xcodegen generate
open DropTwo.xcodeproj # nur bei Bedarf
Arbeiten ohne Xcode-Oberfläche: VS Code mit der offiziellen Swift-Extension (SourceKit-LSP) deckt Autovervollständigung, Fehleranzeige und Navigation ab. Gebaut wird per xcodebuild. Xcode selbst braucht es für SwiftUI-Previews, Zertifikate und Instruments.
xcodebuild -scheme DropTwo -configuration Debug build
xcodebuild -scheme DropTwoCoreTests test
Release
Vor dem ersten Release einmalig einzurichten:
- Apple Developer Program (99 €/Jahr, Anmeldung als Einzelperson). Liefert das Developer ID Application-Zertifikat. Ohne Signatur und Notarisierung blockiert Gatekeeper die App bei allen anderen.
- Sparkle-Schlüsselpaar per
generate_keys. Der private Schlüssel bleibt im macOS-Schlüsselbund und niemals im Repo; der öffentliche wandert alsSUPublicEDKeyin dieInfo.plist. - Team-ID in
project.ymlunterDEVELOPMENT_TEAMeintragen.
Den privaten Sparkle-Schlüssel sichern. Geht er verloren, lassen sich bereits installierte Kopien nie wieder aktualisieren — alle müssten neu installieren.
Ablauf pro Release:
xcodebuild -scheme DropTwo -configuration Release archive …
codesign --deep --options runtime --sign "Developer ID Application: …" DropTwo.app
create-dmg …
xcrun notarytool submit drop.two-1.0.dmg --keychain-profile "notary" --wait
xcrun stapler staple drop.two-1.0.dmg
sign_update drop.two-1.0.dmg # Signatur in appcast.xml eintragen
DMG und appcast.xml landen anschließend auf dem eigenen Server. Der Code liegt auf Gitea, die Release-Artefakte nicht.
Umsetzungsreihenfolge
Die Reihenfolge ist bewusst gewählt:
FileNameParsersamt Unit-Tests — inklusive Bindestrich-KantenfällenVideoInspectorundCropEnginedroptwo-clials Prüfstein, echte Datei durchjagen, Ausgabequalität bewerten- Erst danach die Oberfläche
- Review-Ansicht
- Signierung, Notarisierung, Sparkle
Schritt 3 entscheidet über das Projekt. Liefert AVFoundation nicht die nötige Qualität, muss das am ersten Tag auffallen — nicht nachdem die halbe App steht.
Offene Punkte
- Zielpfad-Schema bei mehreren Sprachen oder Versionen desselben Projekts
- Verhalten bei bereits vorhandenem Zielordner: ergänzen oder warnen
- Ob das 9:16-Original kopiert oder verschoben wird
- Bitrate-Strategie bei H.264: Quellbitrate übernehmen oder fester Qualitätsfaktor
- Vertikaler Offset — global, pro Projekt oder pro Datei
Gestaltung
Bildmarke: ein 9:16-Rahmen, darin der 4:5-Ausschnitt in voller Breite und vertikal zentriert — exakt das, was die App tut.
| Dark | #0B0B0C |
| Light | #F5F5F4 |
| Gold | #C8A96A |
| Mid Gray | #B8B5B0 |
Gold ist der einzige Akzent und bleibt sparsam eingesetzt.