feat: add WhisperKit transcriber and transcribe probe
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
import Foundation
|
||||
import SstWhisper
|
||||
|
||||
func runTranscribeProbe() async {
|
||||
guard let samples = await recordSamples(seconds: 6) else { return }
|
||||
print("Model laden (eerste keer: download ≈1.5 GB)…")
|
||||
let transcriber = WhisperKitTranscriber()
|
||||
do {
|
||||
try await transcriber.load()
|
||||
let started = Date.now
|
||||
let text = try await transcriber.transcribe(samples)
|
||||
let elapsed = Date.now.timeIntervalSince(started)
|
||||
print(String(format: "(%.2f s) ", elapsed) + text)
|
||||
} catch {
|
||||
print("mislukt:", error.localizedDescription)
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ case "hotkey":
|
||||
runHotkeyProbe()
|
||||
case "record":
|
||||
await runRecordProbe()
|
||||
case "transcribe":
|
||||
await runTranscribeProbe()
|
||||
default:
|
||||
print("usage: sst-probe hotkey|record")
|
||||
print("usage: sst-probe hotkey|record|transcribe")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import Foundation
|
||||
import SstCore
|
||||
import WhisperKit
|
||||
|
||||
public final class WhisperKitTranscriber: Transcriber {
|
||||
public enum TranscriberError: Error, LocalizedError {
|
||||
case notLoaded
|
||||
|
||||
public var errorDescription: String? { "Spraakmodel is nog niet geladen." }
|
||||
}
|
||||
|
||||
private let modelName: String
|
||||
private var pipeline: WhisperKit?
|
||||
|
||||
public init(model: String = "large-v3-v20240930_turbo") {
|
||||
self.modelName = model
|
||||
}
|
||||
|
||||
/// Downloads the model on first run (≈1.5 GB) and loads it into memory.
|
||||
public func load() async throws {
|
||||
pipeline = try await WhisperKit(WhisperKitConfig(model: modelName))
|
||||
}
|
||||
|
||||
public func transcribe(_ samples: [Float]) async throws -> String {
|
||||
guard let pipeline else { throw TranscriberError.notLoaded }
|
||||
// language nil + detectLanguage: Whisper picks NL or EN per utterance.
|
||||
let options = DecodingOptions(
|
||||
task: .transcribe,
|
||||
language: nil,
|
||||
detectLanguage: true,
|
||||
skipSpecialTokens: true,
|
||||
withoutTimestamps: true
|
||||
)
|
||||
let results = try await pipeline.transcribe(audioArray: samples, decodeOptions: options)
|
||||
return results
|
||||
.map(\.text)
|
||||
.joined(separator: " ")
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user