Konzept, Projektdefinition und Bildmarke

main
Samuel Zielke 1 month ago
parent 475f4ebbd8
commit c74eca2913

@ -1,2 +1,226 @@
# drop.two <div align="center">
<img src="assets/icon.svg" width="120" alt="drop.two">
<h1>drop.two</h1>
<p><strong>9:16 rein. 9:16 und 4:5 raus.</strong></p>
</div>
---
## 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
1. Eine oder mehrere 9:16-Dateien werden ausgewählt oder per Drag & Drop übergeben.
2. Aus dem Dateinamen wird das Projekt gelesen.
3. Im Zielordner entsteht ein Unterordner mit dem Projektnamen.
4. 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
## 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, `xcodebuild` und `notarytool`
- Homebrew
```bash
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.
```bash
xcodebuild -scheme DropTwo -configuration Debug build
xcodebuild -scheme DropTwoCoreTests test
```
## Release
Vor dem ersten Release einmalig einzurichten:
1. **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.
2. **Sparkle-Schlüsselpaar** per `generate_keys`. Der private Schlüssel bleibt im macOS-Schlüsselbund und **niemals im Repo**; der öffentliche wandert als `SUPublicEDKey` in die `Info.plist`.
3. **Team-ID** in `project.yml` unter `DEVELOPMENT_TEAM` eintragen.
> **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:
```bash
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:
1. `FileNameParser` samt Unit-Tests — inklusive Bindestrich-Kantenfällen
2. `VideoInspector` und `CropEngine`
3. `droptwo-cli` als Prüfstein, echte Datei durchjagen, **Ausgabequalität bewerten**
4. Erst danach die Oberfläche
5. Review-Ansicht
6. 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.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.1 KiB

@ -0,0 +1,104 @@
name: DropTwo
options:
bundleIdPrefix: dev.zielke
createIntermediateGroups: true
deploymentTarget:
macOS: "13.0"
settings:
base:
SWIFT_VERSION: "5.9"
MARKETING_VERSION: "0.1.0"
CURRENT_PROJECT_VERSION: "1"
# Ad-hoc-Signatur: laeuft lokal auf dem eigenen Rechner, braucht keine Team-ID.
# Fuer den ersten echten Release auf Manual + DEVELOPMENT_TEAM umstellen.
CODE_SIGN_STYLE: Automatic
CODE_SIGN_IDENTITY: "-"
configs:
Release:
ENABLE_HARDENED_RUNTIME: YES # Pflicht fuer die Notarisierung
# Sparkle kommt erst in Schritt 6 dazu. Bis dahin auskommentiert --
# das haelt fruehe Builds schnell und die Signierung unkompliziert.
# packages:
# Sparkle:
# url: https://github.com/sparkle-project/Sparkle
# from: "2.6.0"
targets:
# Kern ohne jede UI-Abhaengigkeit -- von App und CLI gemeinsam genutzt.
DropTwoCore:
type: framework
platform: macOS
sources:
- Sources/DropTwoCore
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: dev.zielke.droptwo.core
DropTwo:
type: application
platform: macOS
sources:
- Sources/DropTwo
dependencies:
- target: DropTwoCore
# - package: Sparkle
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: dev.zielke.droptwo
PRODUCT_NAME: drop.two
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
info:
path: Sources/DropTwo/Info.plist
properties:
CFBundleName: drop.two
CFBundleDisplayName: drop.two
LSMinimumSystemVersion: "13.0"
LSUIElement: false # true = reiner Menu-Bar-Betrieb ohne Dock-Icon
NSHumanReadableCopyright: "(c) Samuel Zielke"
# Sparkle-Schluessel und Feed-URL folgen in Schritt 6:
# SUFeedURL: https://.../droptwo/appcast.xml
# SUPublicEDKey: ...
# SUEnableAutomaticChecks: true
# Pruefstein fuer den Kern: echte Datei durchjagen, bevor Oberflaeche entsteht.
droptwo-cli:
type: tool
platform: macOS
sources:
- Sources/DropTwoCLI
dependencies:
- target: DropTwoCore
settings:
base:
PRODUCT_NAME: droptwo
DropTwoCoreTests:
type: bundle.unit-test
platform: macOS
sources:
- Tests/DropTwoCoreTests
dependencies:
- target: DropTwoCore
schemes:
DropTwo:
build:
targets:
DropTwo: all
run:
config: Debug
test:
config: Debug
targets:
- DropTwoCoreTests
droptwo-cli:
build:
targets:
droptwo-cli: all
run:
config: Debug
Loading…
Cancel
Save

Powered by TurnKey Linux.