Skip to content

Add dashboard diarize action#3

Open
PsychOsmosis wants to merge 4 commits into
abn:allow-openai-transcription-apifrom
PsychOsmosis:feature/dashboard-diarize-button
Open

Add dashboard diarize action#3
PsychOsmosis wants to merge 4 commits into
abn:allow-openai-transcription-apifrom
PsychOsmosis:feature/dashboard-diarize-button

Conversation

@PsychOsmosis

@PsychOsmosis PsychOsmosis commented Jun 17, 2026

Copy link
Copy Markdown

Summary:

  • Add a dashboard action to trigger diarization for existing transcriptions.
  • Add the API route/handler and service flow needed to run diarization from the dashboard.
  • Add persistent diarization worker controls that use profile Hugging Face tokens.
  • Reserve idle CUDA VRAM for persistent PyAnnote and Sortformer workers, releasing it during diarization requests.
  • Add worker argument tests for default and overridden VRAM reservation values.

Testing:

  • python3 -m py_compile internal/transcription/adapters/py/pyannote/pyannote_worker.py internal/transcription/adapters/py/nvidia/sortformer_worker.py
  • GOCACHE=/tmp/scriberr-gocache GOMODCACHE=/tmp/scriberr-gomodcache /usr/local/go/bin/go test ./...

@PsychOsmosis

Copy link
Copy Markdown
Author

I rebased this branch with your recent changes.
I find it useful to be able to rediarize with Sortformer when Pyannote did a bad job without having to retranscribe everytime.

@PsychOsmosis

Copy link
Copy Markdown
Author

@abn What do you think ?

@PsychOsmosis

Copy link
Copy Markdown
Author

@abn I also added a way to keep the diarization model always loaded on VRAM.
That was my last remaining pain point with Scriberr and now it's fixed.
You can choose to auto-load a model on startup or not, and load and unload it on the fly with a clickable button.

@abn

abn commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Awesome @PsychOsmosis Let me try get to this over the weekend (that magical weekend 😄 )

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a “diarize” action for already-transcribed jobs in the dashboard UI and introduces a backend “diarization-only” flow, including support for a persistent (resident) diarization worker that can be loaded/unloaded (and optionally loaded at server startup).

Changes:

  • Frontend: adds a diarize action in the transcription list (desktop + swipe actions) and reuses the existing profile dialog to run diarization-only with optional forced diarization settings.
  • Backend: adds /api/v1/transcription/:id/diarize plus DiarizationOnly job handling to load an existing transcript and merge new diarization results without re-transcribing.
  • Adds a persistent diarization worker manager (PyAnnote + Sortformer) with new API routes and UI controls, plus a user setting to request loading a diarization model at startup.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
web/frontend/src/features/transcription/components/AudioFilesTable.tsx Adds a dashboard “Diarize” action and submits diarization-only jobs against completed transcripts.
web/frontend/src/features/settings/components/ProfileSettings.tsx Adds a user setting to choose a diarization model to keep loaded at startup.
web/frontend/src/components/ui/swipeable-item.tsx Adds an optional “Diarize” swipe action and dynamically sizes the action area.
web/frontend/src/components/transcription/TranscriptionConfigDialog.tsx Extends WhisperXParams typing to include diarization_only.
web/frontend/src/components/TranscribeDDialog.tsx Generalizes dialog copy/labels and adds forceDiarization to show diarization settings even if profile disables them.
web/frontend/src/components/Header.tsx Adds UI + polling + load/unload dialog for the persistent diarization worker.
internal/transcription/unified_service.go Implements diarization-only processing by loading an existing transcript and optionally running diarization separately.
internal/transcription/queue_integration.go Exposes persistent diarization worker operations via the unified job processor.
internal/transcription/adapters/sortformer_adapter.go Adds persistent-worker execution path and embeds/copies the worker script.
internal/transcription/adapters/pyannote_adapter.go Adds persistent-worker execution path and relaxes HF token requirement when the resident model is loaded.
internal/transcription/adapters/py/pyannote/pyannote_worker.py Adds a long-lived PyAnnote diarization worker process (stdin/stdout JSON protocol).
internal/transcription/adapters/py/nvidia/sortformer_worker.py Adds a long-lived Sortformer diarization worker process (stdin/stdout JSON protocol).
internal/transcription/adapters/persistent_diarization_manager.go Adds the Go manager that owns the single resident worker process and request protocol.
internal/models/transcription.go Adds diarization_only to job parameters and startup_diarization_model to users.
internal/api/router.go Registers the new transcription diarize route and diarization-worker management routes.
internal/api/handlers.go Implements StartDiarization and persistent diarization worker load/unload/status endpoints + user setting validation.
cmd/server/main.go Loads a persistent diarization model at startup based on user settings and resolves HF token from a profile.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +394 to +406
func (w *persistentDiarizationWorker) Stop(ctx context.Context) error {
w.stopMu.Lock()
if w.stopped {
w.stopMu.Unlock()
return nil
}
w.stopped = true
w.stopMu.Unlock()

_ = w.protocolEnc.Encode(map[string]interface{}{
"id": fmt.Sprintf("shutdown-%d", time.Now().UnixNano()),
"action": "shutdown",
})
Comment thread cmd/server/main.go
Comment on lines +308 to +316
hfToken := strings.TrimSpace(*profile.Parameters.HfToken)
params["hf_token"] = hfToken
if err := os.Setenv("HF_TOKEN", hfToken); err != nil {
logger.Warn("Failed to set HF_TOKEN from default transcription profile", "user_id", userID, "profile_id", profileID, "error", err)
return
}

logger.Info("Resolved HF_TOKEN from default transcription profile for startup diarization", "user_id", userID, "profile_id", profileID)
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove that if you want. I just included this to avoid leaving my HF_token in plaintext in my docker-compose.yml

Comment thread cmd/server/main.go
Comment on lines +255 to +265
users, _, err := userRepo.List(ctx, 0, 100)
if err != nil {
logger.Warn("Failed to load startup diarization preference", "error", err)
return
}

for _, user := range users {
modelID := strings.TrimSpace(strings.ToLower(user.StartupDiarizationModel))
if modelID == "" || modelID == "none" {
continue
}
Comment on lines +97 to +103
// Load starts a resident diarization worker and waits until the model is loaded.
func (m *PersistentDiarizationManager) Load(ctx context.Context, modelID string, params map[string]interface{}) (PersistentDiarizationStatus, error) {
modelID = normalizePersistentDiarizationModel(modelID)
if modelID == "" {
return m.Status(), fmt.Errorf("unsupported diarization model")
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants