|
|
2 weeks ago | |
|---|---|---|
| Sources | 2 weeks ago | |
| Tests/DropTwoCoreTests | 2 weeks ago | |
| assets | 1 month ago | |
| scripts | 1 month ago | |
| site | 2 weeks ago | |
| .gitignore | 1 month ago | |
| README.md | 2 weeks ago | |
| project.yml | 2 weeks 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 Zeichen bleiben gleich erhalten.
Schreibweisen: Das Format darf groß oder klein (9x16, 9X16, 9×16) und mit -, _ oder Leerzeichen abgetrennt sein; die Trenner bleiben in der Zielfassung erhalten (Kampagne_9X16_v2 → Kampagne_4x5_v2). Ein Rest hinter dem Format ist nicht nötig.
Kein Format im Namen: Die App zeigt das schon beim Reinziehen und bietet „4x5 anhängen“ an. Dann wird der ganze Dateistamm zum Projekt, und 4x5 wird mit dem Trenner angehängt, den der Name schon benutzt (Sommerfest Teaser.mov → Sommerfest Teaser/Sommerfest Teaser 4x5.mp4). Ohne diese Wahl wird die Datei übersprungen.
Abbruchbedingungen — die App verarbeitet nicht und meldet es sichtbar:
- Kein
9x16mit Projektnamen davor im Namen (Ausweg: „4x5 anhängen“, s. o.) - 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 (pro Datei verschiebbar, s. u.)
Ausschnitt verschieben: In der Review-Ansicht lässt sich der 4:5-Rahmen mit der Maus nach oben oder unten ziehen. Für Clips mit Szenenwechsel gibt es Positionsmarken: an die Stelle spulen, Marke setzen (Taste M), Rahmen ziehen. Jede Marke gilt ab ihrem Frame bis zur nächsten, als harter Schnitt ohne Fahrt dazwischen. Tasten: Leertaste spielt ab, ←/→ springen um ein Frame. Der Plan gilt pro Datei und wird mit Übernehmen gesetzt; die Dateiliste zeigt angepasste Ausschnitte in Gold.
| Quelle | Ziel |
|---|---|
| 1080 × 1920 | 1080 × 1350 |
| 2160 × 3840 | 2160 × 2700 |
Codec-Verhalten: Die 4:5-Fassung ist immer MP4 mit H.264 (High Profile) und AAC 128 kbit/s, das Zielformat für Feed und Meta Ads, egal ob ProRes, H.264 oder HEVC reinkommt. Die Bitrate richtet sich nach Auflösung und Framerate. Framerate 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, mit Positionsmarken für Szenenwechsel
- In-App-Updates über Sparkle (automatisch plus „Nach Updates suchen …“ im App-Menü)
- Batch-Verlauf der letzten Durchläufe
- Hilfe-Bereich: klickbare Kurzanleitung zur Bedienung der App
- Rechtliche Angaben: Website verlinkt Impressum & Datenschutz von zielke.studio (wie Patchcord)
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
├── CropPlan Ausschnitt-Position(en) über die Laufzeit
├── 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.
Landingpage (site/)
Die Seite unter droptwo.zielke.studio liegt in site/ und wird nicht von publish-release.sh hochgeladen. Die Versionsnummer liest sie selbst aus appcast.xml, nach einem Release muss sie also nicht angefasst werden. Nach Änderungen an der Seite:
rsync -a --chmod=D755,F644 site/index.html site/favicon.svg site/fonts site/og samuelzielke@10.0.5.223:/var/www/updates/droptwo/
Schriften liegen selbst gehostet in site/fonts/ (keine Anfragen an Google). Das Vorschaubild für geteilte Links site/og/og-de.png entsteht aus og-de.html:
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --headless=new --hide-scrollbars \
--window-size=1200,630 --screenshot="$PWD/site/og/og-de.png" "file://$PWD/site/og/og-de.html"
Die Übersicht aller Apps und das Statistik-Dashboard liegen im Repo zielke-apps.
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
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.