SIGN IN SIGN UP

Refactor SpeakerKit around a reusable ModelManager base class (#452)

Introduces a reusable `ModelManager` base class and `ModelLoader` protocol extracting common download/load/unload lifecycle logic. Owns `modelState`, `ModelDownloader`, and coordination for any model-backed kit.

SpeakerKit: Protocol-based architecture
- New `Diarizer` protocol: defines the interface for all diarization backends (Pyannote, and Sortformer in SpeakerKitPro)
- New `SpeakerKitConfig` base class: configuration with dependency injection via `diarizer: (any Diarizer)?`
- `PyannoteConfig` now inherits `SpeakerKitConfig`: enables subclassing for extended variants
- `SpeakerKit` stores protocol existential: `public var diarizer: any Diarizer`
- Config-based initialization: `SpeakerKit.init(_:)` takes config, handles download/load internally
- `SpeakerKitDiarizer` changed from protocol to concrete ModelManager subclass implementing `Diarizer`; the old protocol role is now served by the `Diarizer` protocol
- `SpeakerKitModelManager` class deleted: replaced by `SpeakerKitDiarizer`; deprecated typealias `SpeakerKitModelManager = SpeakerKitDiarizer` provided for migration

Public API Changes
- `SpeakerKit.init(_ SpeakerKitConfig)` — new primary initializer (default: PyannoteConfig())
- `SpeakerKit.diarizer: any Diarizer` — replaces old SpeakerKitDiarizer? protocol property
- `PyannoteConfig(modelFolder: String)` — takes String instead of URL
- `SpeakerKit.init(models:)` → @available(*, unavailable) — use init(_:) instead
- `SpeakerKitModelManager` → deprecated typealias for SpeakerKitDiarizer
- `DiarizationTimings` (concrete struct) → renamed `PyannoteDiarizationTimings`; `DiarizationTimings` is now an empty protocol for backend-agnostic timing objects
- `DiarizationOptionsProtocol` → renamed `DiarizationOptions`
A
Andrey Leonov committed
67f45304cd4b08119ac3d0c349ba9d68bff6b8c1
Parent: 3817d28
Committed by GitHub <noreply@github.com> on 4/1/2026, 3:19:04 AM