Native Windows-Auslieferung statt Container
Docker faellt weg. Das Projekt hat keine npm-Abhaengigkeiten und Node fuehrt TypeScript direkt aus - der Container schrieb nur noch drei Programme fest, und dafuer braucht es keine Virtualisierung, sondern einen Ordner. Der Anlass war, dass ADR-0004 zwar `docker compose pull` versprach, es aber nie ein veroeffentlichtes Image gab. Wer installieren wollte, musste whisper.cpp aus dem Quelltext uebersetzen. Plattformschicht (packages/core/src/platform.ts): - Programme werden neben der Anwendung gesucht, nicht im PATH - Daten unter %LOCALAPPDATA%, damit Installation und Update ohne Administratorrechte auskommen - Schriften mitgeliefert: ohne fontsdir setzt libass wortlos eine Ersatzschrift ein - gemessen 720 statt 826 Pixel Zeilenbreite Windows-Eigenheiten, an echtem ffmpeg 8.1 durchprobiert: - Pfade im Filtergraphen brauchen alle drei Schritte (Vorwaertsschraegstriche, escapter Doppelpunkt, Anfuehrungszeichen); je zwei davon reichen nicht - `nice` gibt es nicht, ersetzt durch os.setPriority Auslieferung: - scripts/build-package.ts baut das Paket, laeuft auch unter Linux - install.ps1 ohne Administratorrechte, Autostart ueber den Aufgabenplaner - update legt neue Fassungen bereit; eingespielt wird beim naechsten Start, nie mitten im Stream - ZIP lesen und schreiben ohne Abhaengigkeiten (packages/core/src/zip.ts) Kein `irm ... | iex`-Einzeiler: git.zeasy.dev antwortete instanzweit mit einer Umleitung auf /user/login, und `iex` fuehrte die Anmeldeseite als PowerShell aus. Der Updater verfolgt Umleitungen jetzt nicht und hat keine erfundene Vorgabeadresse mehr. Ausserdem: backup.ps1 war an zwei Stellen dokumentiert, aber nie geschrieben. ADR-0007 ersetzt ADR-0004. 84 Tests, Typpruefung sauber. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AhVSfMFdWnXKCv5JfLnArZ
This commit is contained in:
1 parent
71dd660d01
commit
5f6301268a
41 files changed
+2254
-312
No files matched your search
@@ -0,0 +1,63 @@
|
||||
// Auswertung einer OBS-Szene gegen den 9:16-Ausschnitt.
|
||||
//
|
||||
// Der Anlass: In einem fertigen Clip lagen fremde Untertitel im Bild, und
|
||||
// niemand wusste, woher sie kommen. Raten hilft da nicht - sie sind ins
|
||||
// Streambild eingebrannt, also muss man nachsehen, welche Quelle sie malt.
|
||||
// Die reine Rechnerei steht hier, damit sie pruefbar ist; das Anzeigen und
|
||||
// das Reden mit OBS bleibt im Entrypoint.
|
||||
|
||||
import type { Rect } from '#core/config.ts';
|
||||
|
||||
export type Box = { x: number; y: number; w: number; h: number };
|
||||
|
||||
/**
|
||||
* Quellenarten und Namen, hinter denen erfahrungsgemaess Untertitel stecken.
|
||||
* Bewusst weit gefasst: ein Fehlalarm kostet einen Blick, eine uebersehene
|
||||
* Quelle kostet jeden Clip.
|
||||
*/
|
||||
export const CAPTION_HINTS =
|
||||
/caption|untertitel|subtitle|transcri|speech|vocal|stt|dictat|closed.?cc|(^|\W)cc(\W|$)/i;
|
||||
|
||||
/** Wie viel Prozent des Ausschnitts die Quelle ueberdeckt. */
|
||||
export function overlapPercent(box: Box, r: Rect): number {
|
||||
const w = Math.max(0, Math.min(box.x + box.w, r.x + r.w) - Math.max(box.x, r.x));
|
||||
const h = Math.max(0, Math.min(box.y + box.h, r.y + r.h) - Math.max(box.y, r.y));
|
||||
const area = r.w * r.h;
|
||||
return area > 0 ? Math.round(((w * h) / area) * 100) : 0;
|
||||
}
|
||||
|
||||
export type SourceVerdict = {
|
||||
cam: number;
|
||||
game: number;
|
||||
/** Steht die Quelle im fertigen Short? */
|
||||
inShort: boolean;
|
||||
/** Sieht sie nach fremden Untertiteln aus? */
|
||||
suspectCaption: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Urteil ueber eine einzelne Quelle.
|
||||
*
|
||||
* Ausgeblendete Quellen sind nie im Bild - egal wo sie liegen. Und eine
|
||||
* Untertitelquelle ausserhalb des Ausschnitts ist kein Problem, sondern genau
|
||||
* das, was docs/obs-layout.md vorschlaegt: im Stream sichtbar lassen, aus dem
|
||||
* Gameplay-Band herausschieben.
|
||||
*/
|
||||
export function judgeSource(args: {
|
||||
box: Box;
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
kind: string;
|
||||
url?: string;
|
||||
cam: Rect;
|
||||
game: Rect;
|
||||
}): SourceVerdict {
|
||||
const cam = overlapPercent(args.box, args.cam);
|
||||
const game = overlapPercent(args.box, args.game);
|
||||
const inShort = args.enabled && (cam > 0 || game > 0);
|
||||
return {
|
||||
cam, game, inShort,
|
||||
suspectCaption: inShort &&
|
||||
CAPTION_HINTS.test(`${args.name} ${args.kind} ${args.url ?? ''}`),
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user