feat: upload audio, get a private Swedish transcript, discuss it (#33, ADR-033) #39

Merged
mathias merged 299 commits from feat/33-audio-upload-transcript into main 2026-10-03 14:13:37 +00:00
Showing only changes of commit 1c5d85f5c6 - Show all commits
+21
View File
@@ -207,6 +207,27 @@ func cmdServe(ctx context.Context, log *slog.Logger) error {
log.Info("web chat enabled (stored-transcript only)", "models", chatModels(cfg)) log.Info("web chat enabled (stored-transcript only)", "models", chatModels(cfg))
} }
// Audio upload -> private transcript (ADR-033). Off unless TAPIR_UPLOADS_ENABLED:
// the image must carry ffmpeg first. The worker is IN-PROCESS and one job at a
// time, so it inherits the single-replica assumption below (its queue is
// process-local); it stops with the same ctx as the server.
intake, worker, err := buildUploads(ctx, cfg, st, log)
if err != nil {
return err
}
if intake != nil {
app.Uploads = intake
app.UploadLimits = uploadLimits(cfg)
go worker.Run(ctx)
log.Info("audio upload enabled", "model", cfg.TranscribeModel, "fallback", cfg.TranscribeFallbackModel,
"max_mb", cfg.UploadMaxBytes>>20, "max_minutes", int(cfg.UploadMaxDuration.Minutes()))
log.Warn("audio upload assumes a SINGLE replica: the transcription queue is process-local (ADR-033, ADR-018)")
if cfg.TranscribeFallbackModel != "" {
log.Warn("audio upload fallback is a CLOUD endpoint: if the primary fails, private audio leaves the homelab",
"fallback", cfg.TranscribeFallbackModel)
}
}
// User onboarding is handled by the IdP (Authentik invite flow), not Tapir — // User onboarding is handled by the IdP (Authentik invite flow), not Tapir —
// the Dex local-password provisioning path was removed (ADR-019). An // the Dex local-password provisioning path was removed (ADR-019). An
// authenticated subject with no Tapir user is routed to /register. // authenticated subject with no Tapir user is routed to /register.