Browse Source

feat: expand recognition language options and fix initial hotkey activation bug

main
Ali Alavi 2 weeks ago
parent
commit
ac3b71722e
  1. 4
      src/AppDelegate.swift
  2. 24
      src/SonioxClient.swift
  3. 23
      src/SonioxSettings.swift

4
src/AppDelegate.swift

@ -54,7 +54,11 @@ public final class AppDelegate: NSObject, NSApplicationDelegate {
} }
} }
// Initial Hotkey Registration (immediate and deferred for AX permission readiness)
HotkeyManager.shared.registerHotkeys() HotkeyManager.shared.registerHotkeys()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
HotkeyManager.shared.registerHotkeys()
}
// Listen to live audio levels & update HUD // Listen to live audio levels & update HUD
audioRecorder.onAudioLevelUpdate = { [weak self] level in audioRecorder.onAudioLevelUpdate = { [weak self] level in

24
src/SonioxClient.swift

@ -86,10 +86,18 @@ public final class SonioxLiveSession {
self.targetLanguage = effectiveTarget self.targetLanguage = effectiveTarget
let hints = languageHints.map { "language_hints=\($0)" }.joined(separator: "&") let hints = languageHints.map { "language_hints=\($0)" }.joined(separator: "&")
var urlStr = "\(endpoint)?\(hints)&enable_speaker_diarization=false&enable_language_identification=true&enable_endpoint_detection=false&providers=soniox"
var queryParams: [String] = []
if !hints.isEmpty {
queryParams.append(hints)
}
queryParams.append("enable_speaker_diarization=false")
queryParams.append("enable_language_identification=true")
queryParams.append("enable_endpoint_detection=false")
queryParams.append("providers=soniox")
if let target = effectiveTarget, !target.isEmpty, target != "off" { if let target = effectiveTarget, !target.isEmpty, target != "off" {
urlStr += "&target_language=\(target)"
queryParams.append("target_language=\(target)")
} }
let urlStr = "\(endpoint)?" + queryParams.joined(separator: "&")
guard let url = URL(string: urlStr) else { return } guard let url = URL(string: urlStr) else { return }
var request = URLRequest(url: url) var request = URLRequest(url: url)
@ -374,10 +382,18 @@ public final class SonioxLiveSession {
) { ) {
let isTranslationMode = targetLanguage != nil && !targetLanguage!.isEmpty && targetLanguage != "off" let isTranslationMode = targetLanguage != nil && !targetLanguage!.isEmpty && targetLanguage != "off"
let hints = languageHints.map { "language_hints=\($0)" }.joined(separator: "&") let hints = languageHints.map { "language_hints=\($0)" }.joined(separator: "&")
var urlStr = "\(endpoint)?\(hints)&enable_speaker_diarization=false&enable_language_identification=true&enable_endpoint_detection=false&providers=soniox"
var queryParams: [String] = []
if !hints.isEmpty {
queryParams.append(hints)
}
queryParams.append("enable_speaker_diarization=false")
queryParams.append("enable_language_identification=true")
queryParams.append("enable_endpoint_detection=false")
queryParams.append("providers=soniox")
if let target = targetLanguage, !target.isEmpty, target != "off" { if let target = targetLanguage, !target.isEmpty, target != "off" {
urlStr += "&target_language=\(target)"
queryParams.append("target_language=\(target)")
} }
let urlStr = "\(endpoint)?" + queryParams.joined(separator: "&")
guard let url = URL(string: urlStr) else { guard let url = URL(string: urlStr) else {
completion(.failure(NSError(domain: "Soniox", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"]))) completion(.failure(NSError(domain: "Soniox", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])))
return return

23
src/SonioxSettings.swift

@ -3,33 +3,51 @@ import Cocoa
public enum RecognitionLanguage: String, CaseIterable { public enum RecognitionLanguage: String, CaseIterable {
case multi = "multi" case multi = "multi"
case all = "all"
case persian = "fa" case persian = "fa"
case english = "en" case english = "en"
case arabic = "ar"
case persianEnglish = "fa_en" case persianEnglish = "fa_en"
case persianArabic = "fa_ar"
case persianEnglishArabic = "fa_en_ar"
public var displayName: String { public var displayName: String {
switch self { switch self {
case .multi: case .multi:
return "Multilingual (Persian, English, Arabic)" return "Multilingual (Persian, English, Arabic)"
case .all:
return "🌍 All Languages (Automatic Full Detection)"
case .persian: case .persian:
return "Persian Only (فارسی)" return "Persian Only (فارسی)"
case .english: case .english:
return "English Only" return "English Only"
case .arabic:
return "Arabic Only (عربی)"
case .persianEnglish: case .persianEnglish:
return "Persian + English" return "Persian + English"
case .persianArabic:
return "Persian + Arabic"
case .persianEnglishArabic:
return "Persian + English + Arabic"
} }
} }
public var hints: [String] { public var hints: [String] {
switch self { switch self {
case .multi:
case .multi, .persianEnglishArabic:
return ["fa", "en", "ar"] return ["fa", "en", "ar"]
case .all:
return [] // When empty, Soniox auto-identifies all 60+ global languages!
case .persian: case .persian:
return ["fa"] return ["fa"]
case .english: case .english:
return ["en"] return ["en"]
case .arabic:
return ["ar"]
case .persianEnglish: case .persianEnglish:
return ["fa", "en"] return ["fa", "en"]
case .persianArabic:
return ["fa", "ar"]
} }
} }
} }
@ -108,6 +126,9 @@ public final class SonioxSettings {
private let defaults = UserDefaults.standard private let defaults = UserDefaults.standard
private init() { private init() {
if defaults.object(forKey: "SonioxHotkeyPreset") == nil {
defaults.set(HotkeyPreset.option.rawValue, forKey: "SonioxHotkeyPreset")
}
ensureHardwareKeyRemapping() ensureHardwareKeyRemapping()
} }

Loading…
Cancel
Save