| | |
| | | const ( |
| | | BackendSenseVoice = "sensevoice" |
| | | BackendMoonshine = "moonshine" |
| | | BackendTransducer = "transducer" |
| | | BackendNemoTransducer = "nemo_transducer" |
| | | BackendQwen3ASR = "qwen3_asr" |
| | | BackendXASRStreaming = "x_asr_streaming" |
| | | ) |
| | | |
| | | var languageProfileOrder = []string{ |
| | | DefaultLanguageID, |
| | | EnglishLanguageID, |
| | | FrenchLanguageID, |
| | | GermanLanguageID, |
| | | SpanishLanguageID, |
| | | ItalianLanguageID, |
| | | PortugueseLanguageID, |
| | | JapaneseLanguageID, |
| | | KoreanLanguageID, |
| | | } |
| | | |
| | | var modelProfiles = map[string]ModelProfile{ |
| | | DefaultModelID: { |
| | |
| | | ProviderOrder: []string{"cpu"}, |
| | | NumThreads: 4, |
| | | }, |
| | | ParakeetV3ModelID: { |
| | | ID: ParakeetV3ModelID, |
| | | DisplayName: "Parakeet TDT v3", |
| | | BackendKind: BackendNemoTransducer, |
| | | Tier: "default", |
| | | SupportedLanguageIDs: []string{ |
| | | FrenchLanguageID, |
| | | GermanLanguageID, |
| | | SpanishLanguageID, |
| | | ItalianLanguageID, |
| | | PortugueseLanguageID, |
| | | }, |
| | | RecommendedFor: []string{ |
| | | FrenchLanguageID, |
| | | GermanLanguageID, |
| | | SpanishLanguageID, |
| | | ItalianLanguageID, |
| | | PortugueseLanguageID, |
| | | }, |
| | | Description: "欧洲多语种离线模型,适合法语、德语、西班牙语、意大利语和葡萄牙语听写。", |
| | | ApproxSize: "约 640 MiB 解压后模型目录", |
| | | DownloadURLs: []string{ |
| | | "https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-nemo-parakeet-tdt-0.6b-v3-int8.tar.bz2", |
| | | }, |
| | | InstallDirName: "parakeet-tdt-0.6b-v3", |
| | | RequiredFiles: []RequiredFileRule{ |
| | | { |
| | | Role: "encoder", |
| | | AllOf: []string{"encoder.int8.onnx"}, |
| | | Required: true, |
| | | }, |
| | | { |
| | | Role: "decoder", |
| | | AllOf: []string{"decoder.int8.onnx"}, |
| | | Required: true, |
| | | }, |
| | | { |
| | | Role: "joiner", |
| | | AllOf: []string{"joiner.int8.onnx"}, |
| | | Required: true, |
| | | }, |
| | | { |
| | | Role: "tokens", |
| | | AllOf: []string{"tokens.txt"}, |
| | | Required: true, |
| | | }, |
| | | }, |
| | | ProviderOrder: []string{"cpu"}, |
| | | NumThreads: 2, |
| | | }, |
| | | JapaneseModelID: { |
| | | ID: JapaneseModelID, |
| | | DisplayName: "Zipformer Japanese", |
| | | BackendKind: BackendTransducer, |
| | | Tier: "default", |
| | | SupportedLanguageIDs: []string{JapaneseLanguageID}, |
| | | RecommendedFor: []string{JapaneseLanguageID}, |
| | | Description: "日语专项离线模型,基于 ReazonSpeech 日语语料。", |
| | | ApproxSize: "约 165 MiB int8 关键模型文件,解压目录包含 fp32 对照文件", |
| | | DownloadURLs: []string{ |
| | | "https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-zipformer-ja-reazonspeech-2024-08-01.tar.bz2", |
| | | }, |
| | | InstallDirName: "zipformer-ja-reazonspeech", |
| | | RequiredFiles: []RequiredFileRule{ |
| | | { |
| | | Role: "encoder", |
| | | AllOf: []string{"encoder-epoch-99-avg-1.int8.onnx"}, |
| | | Required: true, |
| | | }, |
| | | { |
| | | Role: "decoder", |
| | | AllOf: []string{"decoder-epoch-99-avg-1.onnx"}, |
| | | Required: true, |
| | | }, |
| | | { |
| | | Role: "joiner", |
| | | AllOf: []string{"joiner-epoch-99-avg-1.int8.onnx"}, |
| | | Required: true, |
| | | }, |
| | | { |
| | | Role: "tokens", |
| | | AllOf: []string{"tokens.txt"}, |
| | | Required: true, |
| | | }, |
| | | }, |
| | | ProviderOrder: []string{"cpu"}, |
| | | NumThreads: 1, |
| | | }, |
| | | KoreanModelID: { |
| | | ID: KoreanModelID, |
| | | DisplayName: "Zipformer Korean", |
| | | BackendKind: BackendTransducer, |
| | | Tier: "default", |
| | | SupportedLanguageIDs: []string{KoreanLanguageID}, |
| | | RecommendedFor: []string{KoreanLanguageID}, |
| | | Description: "韩语专项离线模型,适合韩语听写。", |
| | | ApproxSize: "约 73 MiB int8 关键模型文件,解压目录包含 fp32 对照文件", |
| | | DownloadURLs: []string{ |
| | | "https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-zipformer-korean-2024-06-24.tar.bz2", |
| | | }, |
| | | InstallDirName: "zipformer-ko", |
| | | RequiredFiles: []RequiredFileRule{ |
| | | { |
| | | Role: "encoder", |
| | | AllOf: []string{"encoder-epoch-99-avg-1.int8.onnx"}, |
| | | Required: true, |
| | | }, |
| | | { |
| | | Role: "decoder", |
| | | AllOf: []string{"decoder-epoch-99-avg-1.onnx"}, |
| | | Required: true, |
| | | }, |
| | | { |
| | | Role: "joiner", |
| | | AllOf: []string{"joiner-epoch-99-avg-1.int8.onnx"}, |
| | | Required: true, |
| | | }, |
| | | { |
| | | Role: "tokens", |
| | | AllOf: []string{"tokens.txt"}, |
| | | Required: true, |
| | | }, |
| | | }, |
| | | ProviderOrder: []string{"cpu"}, |
| | | NumThreads: 2, |
| | | }, |
| | | Qwen3ASRModelID: { |
| | | ID: Qwen3ASRModelID, |
| | | DisplayName: "Qwen3-ASR", |
| | |
| | | DefaultModelID: MoonshineModelID, |
| | | UpgradeModelIDs: []string{ParakeetModelID, XASRZhEn960ModelID}, |
| | | }, |
| | | FrenchLanguageID: { |
| | | ID: FrenchLanguageID, |
| | | DisplayName: "French", |
| | | NativeName: "Français", |
| | | UILocale: "fr", |
| | | SystemMatchers: []string{"fr", "fr-FR", "fr-BE", "fr-CA", "fr-CH"}, |
| | | DefaultModelID: ParakeetV3ModelID, |
| | | }, |
| | | GermanLanguageID: { |
| | | ID: GermanLanguageID, |
| | | DisplayName: "German", |
| | | NativeName: "Deutsch", |
| | | UILocale: "de", |
| | | SystemMatchers: []string{"de", "de-DE", "de-AT", "de-CH"}, |
| | | DefaultModelID: ParakeetV3ModelID, |
| | | }, |
| | | SpanishLanguageID: { |
| | | ID: SpanishLanguageID, |
| | | DisplayName: "Spanish", |
| | | NativeName: "Español", |
| | | UILocale: "es", |
| | | SystemMatchers: []string{"es", "es-ES", "es-MX", "es-US", "es-AR"}, |
| | | DefaultModelID: ParakeetV3ModelID, |
| | | }, |
| | | ItalianLanguageID: { |
| | | ID: ItalianLanguageID, |
| | | DisplayName: "Italian", |
| | | NativeName: "Italiano", |
| | | UILocale: "it", |
| | | SystemMatchers: []string{"it", "it-IT", "it-CH"}, |
| | | DefaultModelID: ParakeetV3ModelID, |
| | | }, |
| | | PortugueseLanguageID: { |
| | | ID: PortugueseLanguageID, |
| | | DisplayName: "Portuguese", |
| | | NativeName: "Português", |
| | | UILocale: "pt", |
| | | SystemMatchers: []string{"pt", "pt-PT", "pt-BR"}, |
| | | DefaultModelID: ParakeetV3ModelID, |
| | | }, |
| | | JapaneseLanguageID: { |
| | | ID: JapaneseLanguageID, |
| | | DisplayName: "Japanese", |
| | | NativeName: "日本語", |
| | | UILocale: "ja", |
| | | SystemMatchers: []string{"ja", "ja-JP"}, |
| | | DefaultModelID: JapaneseModelID, |
| | | }, |
| | | KoreanLanguageID: { |
| | | ID: KoreanLanguageID, |
| | | DisplayName: "Korean", |
| | | NativeName: "한국어", |
| | | UILocale: "ko", |
| | | SystemMatchers: []string{"ko", "ko-KR"}, |
| | | DefaultModelID: KoreanModelID, |
| | | }, |
| | | } |
| | | |
| | | func GetModelProfile(id string) (ModelProfile, error) { |
| | |
| | | |
| | | func ListLanguageProfiles() []LanguageProfile { |
| | | profiles := make([]LanguageProfile, 0, len(languageProfiles)) |
| | | for _, profile := range languageProfiles { |
| | | profiles = append(profiles, profile) |
| | | seen := make(map[string]bool, len(languageProfiles)) |
| | | for _, id := range languageProfileOrder { |
| | | if profile, ok := languageProfiles[id]; ok { |
| | | profiles = append(profiles, profile) |
| | | seen[id] = true |
| | | } |
| | | } |
| | | for id, profile := range languageProfiles { |
| | | if !seen[id] { |
| | | profiles = append(profiles, profile) |
| | | } |
| | | } |
| | | sort.Slice(profiles, func(i, j int) bool { |
| | | if profiles[i].ID == DefaultLanguageID { |
| | | return true |
| | | } |
| | | if profiles[j].ID == DefaultLanguageID { |
| | | return false |
| | | left := languageOrderIndex(profiles[i].ID) |
| | | right := languageOrderIndex(profiles[j].ID) |
| | | if left != right { |
| | | return left < right |
| | | } |
| | | return profiles[i].ID < profiles[j].ID |
| | | }) |
| | | return profiles |
| | | } |
| | | |
| | | func languageOrderIndex(id string) int { |
| | | for i, orderedID := range languageProfileOrder { |
| | | if id == orderedID { |
| | | return i |
| | | } |
| | | } |
| | | return len(languageProfileOrder) |
| | | } |
| | | |
| | | func NormalizeLanguageID(id string) string { |
| | | if _, err := GetLanguageProfile(id); err != nil { |
| | | return DefaultLanguageID |