From 106042bbb20f97cba9c4b4181452a703efc69eae Mon Sep 17 00:00:00 2001 From: Mark Backman Date: Mon, 18 Nov 2024 15:22:04 -0500 Subject: [PATCH] Make language support more robust --- src/pipecat/services/aws.py | 50 ++- src/pipecat/services/azure.py | 308 ++++++++++++++++- src/pipecat/services/cartesia.py | 23 +- src/pipecat/services/elevenlabs.py | 35 +- src/pipecat/services/gladia.py | 80 ++++- src/pipecat/services/google.py | 115 ++++++- src/pipecat/services/lmnt.py | 27 +- src/pipecat/services/xtts.py | 31 +- src/pipecat/transcriptions/language.py | 452 ++++++++++++++++++++++--- 9 files changed, 991 insertions(+), 130 deletions(-) diff --git a/src/pipecat/services/aws.py b/src/pipecat/services/aws.py index d913bf37e..6a74731b5 100644 --- a/src/pipecat/services/aws.py +++ b/src/pipecat/services/aws.py @@ -34,35 +34,77 @@ except ModuleNotFoundError as e: def language_to_aws_language(language: Language) -> str | None: language_map = { + # Arabic + Language.AR: "arb", + Language.AR_AE: "ar-AE", + # Catalan Language.CA: "ca-ES", - Language.ZH: "cmn-CN", + # Chinese + Language.ZH: "cmn-CN", # Mandarin + Language.YUE: "yue-CN", # Cantonese + Language.YUE_CN: "yue-CN", + # Czech + Language.CS: "cs-CZ", + # Danish Language.DA: "da-DK", + # Dutch Language.NL: "nl-NL", Language.NL_BE: "nl-BE", - Language.EN: "en-US", - Language.EN_US: "en-US", + # English + Language.EN: "en-US", # Default to US English Language.EN_AU: "en-AU", Language.EN_GB: "en-GB", - Language.EN_NZ: "en-NZ", Language.EN_IN: "en-IN", + Language.EN_NZ: "en-NZ", + Language.EN_US: "en-US", + Language.EN_ZA: "en-ZA", + # Finnish Language.FI: "fi-FI", + # French Language.FR: "fr-FR", + Language.FR_BE: "fr-BE", Language.FR_CA: "fr-CA", + # German Language.DE: "de-DE", + Language.DE_AT: "de-AT", + Language.DE_CH: "de-CH", + # Hindi Language.HI: "hi-IN", + # Icelandic + Language.IS: "is-IS", + # Italian Language.IT: "it-IT", + # Japanese Language.JA: "ja-JP", + # Korean Language.KO: "ko-KR", + # Norwegian Language.NO: "nb-NO", + Language.NB: "nb-NO", + Language.NB_NO: "nb-NO", + # Polish Language.PL: "pl-PL", + # Portuguese Language.PT: "pt-PT", Language.PT_BR: "pt-BR", + Language.PT_PT: "pt-PT", + # Romanian Language.RO: "ro-RO", + # Russian Language.RU: "ru-RU", + # Spanish Language.ES: "es-ES", + Language.ES_MX: "es-MX", + Language.ES_US: "es-US", + # Swedish Language.SV: "sv-SE", + # Turkish Language.TR: "tr-TR", + # Welsh + Language.CY: "cy-GB", + Language.CY_GB: "cy-GB", } + return language_map.get(language) diff --git a/src/pipecat/services/azure.py b/src/pipecat/services/azure.py index 96c2a9004..ce845459d 100644 --- a/src/pipecat/services/azure.py +++ b/src/pipecat/services/azure.py @@ -63,49 +63,325 @@ except ModuleNotFoundError as e: def language_to_azure_language(language: Language) -> str | None: language_map = { + # Afrikaans + Language.AF: "af-ZA", + Language.AF_ZA: "af-ZA", + # Amharic + Language.AM: "am-ET", + Language.AM_ET: "am-ET", + # Arabic + Language.AR: "ar-AE", # Default to UAE Arabic + Language.AR_AE: "ar-AE", + Language.AR_BH: "ar-BH", + Language.AR_DZ: "ar-DZ", + Language.AR_EG: "ar-EG", + Language.AR_IQ: "ar-IQ", + Language.AR_JO: "ar-JO", + Language.AR_KW: "ar-KW", + Language.AR_LB: "ar-LB", + Language.AR_LY: "ar-LY", + Language.AR_MA: "ar-MA", + Language.AR_OM: "ar-OM", + Language.AR_QA: "ar-QA", + Language.AR_SA: "ar-SA", + Language.AR_SY: "ar-SY", + Language.AR_TN: "ar-TN", + Language.AR_YE: "ar-YE", + # Assamese + Language.AS: "as-IN", + Language.AS_IN: "as-IN", + # Azerbaijani + Language.AZ: "az-AZ", + Language.AZ_AZ: "az-AZ", + # Bulgarian Language.BG: "bg-BG", + Language.BG_BG: "bg-BG", + # Bengali + Language.BN: "bn-IN", # Default to Indian Bengali + Language.BN_BD: "bn-BD", + Language.BN_IN: "bn-IN", + # Bosnian + Language.BS: "bs-BA", + Language.BS_BA: "bs-BA", + # Catalan Language.CA: "ca-ES", - Language.ZH: "zh-CN", - Language.ZH_TW: "zh-TW", + Language.CA_ES: "ca-ES", + # Czech Language.CS: "cs-CZ", + Language.CS_CZ: "cs-CZ", + # Welsh + Language.CY: "cy-GB", + Language.CY_GB: "cy-GB", + # Danish Language.DA: "da-DK", - Language.NL: "nl-NL", - Language.EN: "en-US", - Language.EN_US: "en-US", - Language.EN_AU: "en-AU", - Language.EN_GB: "en-GB", - Language.EN_NZ: "en-NZ", - Language.EN_IN: "en-IN", - Language.ET: "et-EE", - Language.FI: "fi-FI", - Language.NL_BE: "nl-BE", - Language.FR: "fr-FR", - Language.FR_CA: "fr-CA", + Language.DA_DK: "da-DK", + # German Language.DE: "de-DE", + Language.DE_AT: "de-AT", Language.DE_CH: "de-CH", + Language.DE_DE: "de-DE", + # Greek Language.EL: "el-GR", + Language.EL_GR: "el-GR", + # English + Language.EN: "en-US", # Default to US English + Language.EN_AU: "en-AU", + Language.EN_CA: "en-CA", + Language.EN_GB: "en-GB", + Language.EN_HK: "en-HK", + Language.EN_IE: "en-IE", + Language.EN_IN: "en-IN", + Language.EN_KE: "en-KE", + Language.EN_NG: "en-NG", + Language.EN_NZ: "en-NZ", + Language.EN_PH: "en-PH", + Language.EN_SG: "en-SG", + Language.EN_TZ: "en-TZ", + Language.EN_US: "en-US", + Language.EN_ZA: "en-ZA", + # Spanish + Language.ES: "es-ES", # Default to Spain Spanish + Language.ES_AR: "es-AR", + Language.ES_BO: "es-BO", + Language.ES_CL: "es-CL", + Language.ES_CO: "es-CO", + Language.ES_CR: "es-CR", + Language.ES_CU: "es-CU", + Language.ES_DO: "es-DO", + Language.ES_EC: "es-EC", + Language.ES_ES: "es-ES", + Language.ES_GQ: "es-GQ", + Language.ES_GT: "es-GT", + Language.ES_HN: "es-HN", + Language.ES_MX: "es-MX", + Language.ES_NI: "es-NI", + Language.ES_PA: "es-PA", + Language.ES_PE: "es-PE", + Language.ES_PR: "es-PR", + Language.ES_PY: "es-PY", + Language.ES_SV: "es-SV", + Language.ES_US: "es-US", + Language.ES_UY: "es-UY", + Language.ES_VE: "es-VE", + # Estonian + Language.ET: "et-EE", + Language.ET_EE: "et-EE", + # Basque + Language.EU: "eu-ES", + Language.EU_ES: "eu-ES", + # Persian + Language.FA: "fa-IR", + Language.FA_IR: "fa-IR", + # Finnish + Language.FI: "fi-FI", + Language.FI_FI: "fi-FI", + # Filipino + Language.FIL: "fil-PH", + Language.FIL_PH: "fil-PH", + # French + Language.FR: "fr-FR", + Language.FR_BE: "fr-BE", + Language.FR_CA: "fr-CA", + Language.FR_CH: "fr-CH", + Language.FR_FR: "fr-FR", + # Irish + Language.GA: "ga-IE", + Language.GA_IE: "ga-IE", + # Galician + Language.GL: "gl-ES", + Language.GL_ES: "gl-ES", + # Gujarati + Language.GU: "gu-IN", + Language.GU_IN: "gu-IN", + # Hebrew + Language.HE: "he-IL", + Language.HE_IL: "he-IL", + # Hindi Language.HI: "hi-IN", + Language.HI_IN: "hi-IN", + # Croatian + Language.HR: "hr-HR", + Language.HR_HR: "hr-HR", + # Hungarian Language.HU: "hu-HU", + Language.HU_HU: "hu-HU", + # Armenian + Language.HY: "hy-AM", + Language.HY_AM: "hy-AM", + # Indonesian Language.ID: "id-ID", + Language.ID_ID: "id-ID", + # Icelandic + Language.IS: "is-IS", + Language.IS_IS: "is-IS", + # Italian Language.IT: "it-IT", + Language.IT_IT: "it-IT", + # Inuktitut + Language.IU_CANS_CA: "iu-Cans-CA", + Language.IU_LATN_CA: "iu-Latn-CA", + # Japanese Language.JA: "ja-JP", + Language.JA_JP: "ja-JP", + # Javanese + Language.JV: "jv-ID", + Language.JV_ID: "jv-ID", + # Georgian + Language.KA: "ka-GE", + Language.KA_GE: "ka-GE", + # Kazakh + Language.KK: "kk-KZ", + Language.KK_KZ: "kk-KZ", + # Khmer + Language.KM: "km-KH", + Language.KM_KH: "km-KH", + # Kannada + Language.KN: "kn-IN", + Language.KN_IN: "kn-IN", + # Korean Language.KO: "ko-KR", - Language.LV: "lv-LV", + Language.KO_KR: "ko-KR", + # Lao + Language.LO: "lo-LA", + Language.LO_LA: "lo-LA", + # Lithuanian Language.LT: "lt-LT", + Language.LT_LT: "lt-LT", + # Latvian + Language.LV: "lv-LV", + Language.LV_LV: "lv-LV", + # Macedonian + Language.MK: "mk-MK", + Language.MK_MK: "mk-MK", + # Malayalam + Language.ML: "ml-IN", + Language.ML_IN: "ml-IN", + # Mongolian + Language.MN: "mn-MN", + Language.MN_MN: "mn-MN", + # Marathi + Language.MR: "mr-IN", + Language.MR_IN: "mr-IN", + # Malay Language.MS: "ms-MY", + Language.MS_MY: "ms-MY", + # Maltese + Language.MT: "mt-MT", + Language.MT_MT: "mt-MT", + # Burmese + Language.MY: "my-MM", + Language.MY_MM: "my-MM", + # Norwegian + Language.NB: "nb-NO", + Language.NB_NO: "nb-NO", Language.NO: "nb-NO", + # Nepali + Language.NE: "ne-NP", + Language.NE_NP: "ne-NP", + # Dutch + Language.NL: "nl-NL", + Language.NL_BE: "nl-BE", + Language.NL_NL: "nl-NL", + # Odia + Language.OR: "or-IN", + Language.OR_IN: "or-IN", + # Punjabi + Language.PA: "pa-IN", + Language.PA_IN: "pa-IN", + # Polish Language.PL: "pl-PL", + Language.PL_PL: "pl-PL", + # Pashto + Language.PS: "ps-AF", + Language.PS_AF: "ps-AF", + # Portuguese Language.PT: "pt-PT", Language.PT_BR: "pt-BR", + Language.PT_PT: "pt-PT", + # Romanian Language.RO: "ro-RO", + Language.RO_RO: "ro-RO", + # Russian Language.RU: "ru-RU", + Language.RU_RU: "ru-RU", + # Sinhala + Language.SI: "si-LK", + Language.SI_LK: "si-LK", + # Slovak Language.SK: "sk-SK", - Language.ES: "es-ES", + Language.SK_SK: "sk-SK", + # Slovenian + Language.SL: "sl-SI", + Language.SL_SI: "sl-SI", + # Somali + Language.SO: "so-SO", + Language.SO_SO: "so-SO", + # Albanian + Language.SQ: "sq-AL", + Language.SQ_AL: "sq-AL", + # Serbian + Language.SR: "sr-RS", + Language.SR_RS: "sr-RS", + Language.SR_LATN: "sr-Latn-RS", + Language.SR_LATN_RS: "sr-Latn-RS", + # Sundanese + Language.SU: "su-ID", + Language.SU_ID: "su-ID", + # Swedish Language.SV: "sv-SE", + Language.SV_SE: "sv-SE", + # Swahili + Language.SW: "sw-KE", + Language.SW_KE: "sw-KE", + Language.SW_TZ: "sw-TZ", + # Tamil + Language.TA: "ta-IN", + Language.TA_IN: "ta-IN", + Language.TA_LK: "ta-LK", + Language.TA_MY: "ta-MY", + Language.TA_SG: "ta-SG", + # Telugu + Language.TE: "te-IN", + Language.TE_IN: "te-IN", + # Thai Language.TH: "th-TH", + Language.TH_TH: "th-TH", + # Turkish Language.TR: "tr-TR", + Language.TR_TR: "tr-TR", + # Ukrainian Language.UK: "uk-UA", + Language.UK_UA: "uk-UA", + # Urdu + Language.UR: "ur-IN", + Language.UR_IN: "ur-IN", + Language.UR_PK: "ur-PK", + # Uzbek + Language.UZ: "uz-UZ", + Language.UZ_UZ: "uz-UZ", + # Vietnamese Language.VI: "vi-VN", + Language.VI_VN: "vi-VN", + # Wu Chinese + Language.WUU: "wuu-CN", + Language.WUU_CN: "wuu-CN", + # Yue Chinese + Language.YUE: "yue-CN", + Language.YUE_CN: "yue-CN", + # Chinese + Language.ZH: "zh-CN", + Language.ZH_CN: "zh-CN", + Language.ZH_CN_GUANGXI: "zh-CN-guangxi", + Language.ZH_CN_HENAN: "zh-CN-henan", + Language.ZH_CN_LIAONING: "zh-CN-liaoning", + Language.ZH_CN_SHAANXI: "zh-CN-shaanxi", + Language.ZH_CN_SHANDONG: "zh-CN-shandong", + Language.ZH_CN_SICHUAN: "zh-CN-sichuan", + Language.ZH_HK: "zh-HK", + Language.ZH_TW: "zh-TW", + # Zulu + Language.ZU: "zu-ZA", + Language.ZU_ZA: "zu-ZA", } return language_map.get(language) diff --git a/src/pipecat/services/cartesia.py b/src/pipecat/services/cartesia.py index 0c5102198..ad4636a74 100644 --- a/src/pipecat/services/cartesia.py +++ b/src/pipecat/services/cartesia.py @@ -44,24 +44,27 @@ except ModuleNotFoundError as e: def language_to_cartesia_language(language: Language) -> str | None: - language_map = { + BASE_LANGUAGES = { Language.DE: "de", Language.EN: "en", - Language.EN_US: "en", - Language.EN_GB: "en", - Language.EN_AU: "en", - Language.EN_NZ: "en", - Language.EN_IN: "en", Language.ES: "es", Language.FR: "fr", - Language.FR_CA: "fr", Language.JA: "ja", Language.PT: "pt", - Language.PT_BR: "pt", Language.ZH: "zh", - Language.ZH_TW: "zh", } - return language_map.get(language) + + result = BASE_LANGUAGES.get(language) + + # If not found in base languages, try to find the base language from a variant + if not result: + # Convert enum value to string and get the base language part (e.g. es-ES -> es) + lang_str = str(language.value) + base_code = lang_str.split("-")[0].lower() + # Look up the base code in our supported languages + result = base_code if base_code in BASE_LANGUAGES.values() else None + + return result class CartesiaTTSService(WordTTSService): diff --git a/src/pipecat/services/elevenlabs.py b/src/pipecat/services/elevenlabs.py index d13859af5..2707df92a 100644 --- a/src/pipecat/services/elevenlabs.py +++ b/src/pipecat/services/elevenlabs.py @@ -43,24 +43,16 @@ ElevenLabsOutputFormat = Literal["pcm_16000", "pcm_22050", "pcm_24000", "pcm_441 def language_to_elevenlabs_language(language: Language) -> str | None: - language_map = { + BASE_LANGUAGES = { Language.BG: "bg", - Language.ZH: "zh", Language.CS: "cs", Language.DA: "da", - Language.NL: "nl", + Language.DE: "de", + Language.EL: "el", Language.EN: "en", - Language.EN_US: "en", - Language.EN_AU: "en", - Language.EN_GB: "en", - Language.EN_NZ: "en", - Language.EN_IN: "en", + Language.ES: "es", Language.FI: "fi", Language.FR: "fr", - Language.FR_CA: "fr", - Language.DE: "de", - Language.DE_CH: "de", - Language.EL: "el", Language.HI: "hi", Language.HU: "hu", Language.ID: "id", @@ -68,20 +60,31 @@ def language_to_elevenlabs_language(language: Language) -> str | None: Language.JA: "ja", Language.KO: "ko", Language.MS: "ms", + Language.NL: "nl", Language.NO: "no", Language.PL: "pl", - Language.PT: "pt-PT", - Language.PT_BR: "pt-BR", + Language.PT: "pt", Language.RO: "ro", Language.RU: "ru", Language.SK: "sk", - Language.ES: "es", Language.SV: "sv", Language.TR: "tr", Language.UK: "uk", Language.VI: "vi", + Language.ZH: "zh", } - return language_map.get(language) + + result = BASE_LANGUAGES.get(language) + + # If not found in base languages, try to find the base language from a variant + if not result: + # Convert enum value to string and get the base language part (e.g. es-ES -> es) + lang_str = str(language.value) + base_code = lang_str.split("-")[0].lower() + # Look up the base code in our supported languages + result = base_code if base_code in BASE_LANGUAGES.values() else None + + return result def sample_rate_from_output_format(output_format: str) -> int: diff --git a/src/pipecat/services/gladia.py b/src/pipecat/services/gladia.py index 574cfcb59..c659a20ac 100644 --- a/src/pipecat/services/gladia.py +++ b/src/pipecat/services/gladia.py @@ -35,50 +35,98 @@ except ModuleNotFoundError as e: def language_to_gladia_language(language: Language) -> str | None: - language_map = { + BASE_LANGUAGES = { + Language.AF: "af", + Language.AM: "am", + Language.AR: "ar", + Language.AS: "as", + Language.AZ: "az", Language.BG: "bg", + Language.BN: "bn", + Language.BS: "bs", Language.CA: "ca", - Language.ZH: "zh", Language.CS: "cs", + Language.CY: "cy", Language.DA: "da", - Language.NL: "nl", + Language.DE: "de", + Language.EL: "el", Language.EN: "en", - Language.EN_US: "en", - Language.EN_AU: "en", - Language.EN_GB: "en", - Language.EN_NZ: "en", - Language.EN_IN: "en", + Language.ES: "es", Language.ET: "et", + Language.EU: "eu", + Language.FA: "fa", Language.FI: "fi", Language.FR: "fr", - Language.FR_CA: "fr", - Language.DE: "de", - Language.DE_CH: "de", - Language.EL: "el", + Language.GA: "ga", + Language.GL: "gl", + Language.GU: "gu", + Language.HE: "he", Language.HI: "hi", + Language.HR: "hr", Language.HU: "hu", + Language.HY: "hy", Language.ID: "id", + Language.IS: "is", Language.IT: "it", Language.JA: "ja", + Language.JV: "jv", + Language.KA: "ka", + Language.KK: "kk", + Language.KM: "km", + Language.KN: "kn", Language.KO: "ko", - Language.LV: "lv", + Language.LO: "lo", Language.LT: "lt", + Language.LV: "lv", + Language.MK: "mk", + Language.ML: "ml", + Language.MN: "mn", + Language.MR: "mr", Language.MS: "ms", + Language.MT: "mt", + Language.MY: "my", + Language.NE: "ne", + Language.NL: "nl", Language.NO: "no", + Language.OR: "or", + Language.PA: "pa", Language.PL: "pl", + Language.PS: "ps", Language.PT: "pt", - Language.PT_BR: "pt", Language.RO: "ro", Language.RU: "ru", + Language.SI: "si", Language.SK: "sk", - Language.ES: "es", + Language.SL: "sl", + Language.SO: "so", + Language.SQ: "sq", + Language.SR: "sr", + Language.SU: "su", Language.SV: "sv", + Language.SW: "sw", + Language.TA: "ta", + Language.TE: "te", Language.TH: "th", Language.TR: "tr", Language.UK: "uk", + Language.UR: "ur", + Language.UZ: "uz", Language.VI: "vi", + Language.ZH: "zh", + Language.ZU: "zu", } - return language_map.get(language) + + result = BASE_LANGUAGES.get(language) + + # If not found in base languages, try to find the base language from a variant + if not result: + # Convert enum value to string and get the base language part (e.g. es-ES -> es) + lang_str = str(language.value) + base_code = lang_str.split("-")[0].lower() + # Look up the base code in our supported languages + result = base_code if base_code in BASE_LANGUAGES.values() else None + + return result class GladiaSTTService(STTService): diff --git a/src/pipecat/services/google.py b/src/pipecat/services/google.py index 93766efc9..f945fa53d 100644 --- a/src/pipecat/services/google.py +++ b/src/pipecat/services/google.py @@ -58,48 +58,161 @@ except ModuleNotFoundError as e: def language_to_google_language(language: Language) -> str | None: language_map = { + # Afrikaans + Language.AF: "af-ZA", + Language.AF_ZA: "af-ZA", + # Arabic + Language.AR: "ar-XA", + # Bengali + Language.BN: "bn-IN", + Language.BN_IN: "bn-IN", + # Bulgarian Language.BG: "bg-BG", + Language.BG_BG: "bg-BG", + # Catalan Language.CA: "ca-ES", + Language.CA_ES: "ca-ES", + # Chinese (Mandarin and Cantonese) Language.ZH: "cmn-CN", + Language.ZH_CN: "cmn-CN", Language.ZH_TW: "cmn-TW", + Language.ZH_HK: "yue-HK", + # Czech Language.CS: "cs-CZ", + Language.CS_CZ: "cs-CZ", + # Danish Language.DA: "da-DK", + Language.DA_DK: "da-DK", + # Dutch Language.NL: "nl-NL", + Language.NL_BE: "nl-BE", + Language.NL_NL: "nl-NL", + # English Language.EN: "en-US", Language.EN_US: "en-US", Language.EN_AU: "en-AU", Language.EN_GB: "en-GB", Language.EN_IN: "en-IN", + # Estonian Language.ET: "et-EE", + Language.ET_EE: "et-EE", + # Filipino + Language.FIL: "fil-PH", + Language.FIL_PH: "fil-PH", + # Finnish Language.FI: "fi-FI", - Language.NL_BE: "nl-BE", + Language.FI_FI: "fi-FI", + # French Language.FR: "fr-FR", Language.FR_CA: "fr-CA", + Language.FR_FR: "fr-FR", + # Galician + Language.GL: "gl-ES", + Language.GL_ES: "gl-ES", + # German Language.DE: "de-DE", + Language.DE_DE: "de-DE", + # Greek Language.EL: "el-GR", + Language.EL_GR: "el-GR", + # Gujarati + Language.GU: "gu-IN", + Language.GU_IN: "gu-IN", + # Hebrew + Language.HE: "he-IL", + Language.HE_IL: "he-IL", + # Hindi Language.HI: "hi-IN", + Language.HI_IN: "hi-IN", + # Hungarian Language.HU: "hu-HU", + Language.HU_HU: "hu-HU", + # Icelandic + Language.IS: "is-IS", + Language.IS_IS: "is-IS", + # Indonesian Language.ID: "id-ID", + Language.ID_ID: "id-ID", + # Italian Language.IT: "it-IT", + Language.IT_IT: "it-IT", + # Japanese Language.JA: "ja-JP", + Language.JA_JP: "ja-JP", + # Kannada + Language.KN: "kn-IN", + Language.KN_IN: "kn-IN", + # Korean Language.KO: "ko-KR", + Language.KO_KR: "ko-KR", + # Latvian Language.LV: "lv-LV", + Language.LV_LV: "lv-LV", + # Lithuanian Language.LT: "lt-LT", + Language.LT_LT: "lt-LT", + # Malay Language.MS: "ms-MY", + Language.MS_MY: "ms-MY", + # Malayalam + Language.ML: "ml-IN", + Language.ML_IN: "ml-IN", + # Marathi + Language.MR: "mr-IN", + Language.MR_IN: "mr-IN", + # Norwegian Language.NO: "nb-NO", + Language.NB: "nb-NO", + Language.NB_NO: "nb-NO", + # Polish Language.PL: "pl-PL", + Language.PL_PL: "pl-PL", + # Portuguese Language.PT: "pt-PT", Language.PT_BR: "pt-BR", + Language.PT_PT: "pt-PT", + # Punjabi + Language.PA: "pa-IN", + Language.PA_IN: "pa-IN", + # Romanian Language.RO: "ro-RO", + Language.RO_RO: "ro-RO", + # Russian Language.RU: "ru-RU", + Language.RU_RU: "ru-RU", + # Serbian + Language.SR: "sr-RS", + Language.SR_RS: "sr-RS", + # Slovak Language.SK: "sk-SK", + Language.SK_SK: "sk-SK", + # Spanish Language.ES: "es-ES", + Language.ES_ES: "es-ES", + Language.ES_US: "es-US", + # Swedish Language.SV: "sv-SE", + Language.SV_SE: "sv-SE", + # Tamil + Language.TA: "ta-IN", + Language.TA_IN: "ta-IN", + # Telugu + Language.TE: "te-IN", + Language.TE_IN: "te-IN", + # Thai Language.TH: "th-TH", + Language.TH_TH: "th-TH", + # Turkish Language.TR: "tr-TR", + Language.TR_TR: "tr-TR", + # Ukrainian Language.UK: "uk-UA", + Language.UK_UA: "uk-UA", + # Vietnamese Language.VI: "vi-VN", + Language.VI_VN: "vi-VN", } + return language_map.get(language) diff --git a/src/pipecat/services/lmnt.py b/src/pipecat/services/lmnt.py index 7717358de..a5c929094 100644 --- a/src/pipecat/services/lmnt.py +++ b/src/pipecat/services/lmnt.py @@ -36,24 +36,27 @@ except ModuleNotFoundError as e: def language_to_lmnt_language(language: Language) -> str | None: - language_map = { + BASE_LANGUAGES = { Language.DE: "de", Language.EN: "en", - Language.EN_US: "en", - Language.EN_AU: "en", - Language.EN_GB: "en", - Language.EN_NZ: "en", - Language.EN_IN: "en", Language.ES: "es", Language.FR: "fr", - Language.FR_CA: "fr", - Language.PT: "pt", - Language.PT_BR: "pt", - Language.ZH: "zh", - Language.ZH_TW: "zh", Language.KO: "ko", + Language.PT: "pt", + Language.ZH: "zh", } - return language_map.get(language) + + result = BASE_LANGUAGES.get(language) + + # If not found in base languages, try to find the base language from a variant + if not result: + # Convert enum value to string and get the base language part (e.g. es-ES -> es) + lang_str = str(language.value) + base_code = lang_str.split("-")[0].lower() + # Look up the base code in our supported languages + result = base_code if base_code in BASE_LANGUAGES.values() else None + + return result class LmntTTSService(TTSService): diff --git a/src/pipecat/services/xtts.py b/src/pipecat/services/xtts.py index 97e7ee021..73edb06ff 100644 --- a/src/pipecat/services/xtts.py +++ b/src/pipecat/services/xtts.py @@ -7,6 +7,7 @@ from typing import Any, AsyncGenerator, Dict import aiohttp +from loguru import logger from pipecat.audio.utils import resample_audio from pipecat.frames.frames import ( @@ -20,9 +21,6 @@ from pipecat.frames.frames import ( from pipecat.services.ai_services import TTSService from pipecat.transcriptions.language import Language -from loguru import logger - - # The server below can connect to XTTS through a local running docker # # Docker command: $ docker run --gpus=all -e COQUI_TOS_AGREED=1 --rm -p 8000:80 ghcr.io/coqui-ai/xtts-streaming-server:latest-cuda121 @@ -32,15 +30,10 @@ from loguru import logger def language_to_xtts_language(language: Language) -> str | None: - language_map = { + BASE_LANGUAGES = { Language.CS: "cs", Language.DE: "de", Language.EN: "en", - Language.EN_US: "en", - Language.EN_AU: "en", - Language.EN_GB: "en", - Language.EN_NZ: "en", - Language.EN_IN: "en", Language.ES: "es", Language.FR: "fr", Language.HI: "hi", @@ -51,12 +44,28 @@ def language_to_xtts_language(language: Language) -> str | None: Language.NL: "nl", Language.PL: "pl", Language.PT: "pt", - Language.PT_BR: "pt", Language.RU: "ru", Language.TR: "tr", + # Special case for Chinese base language Language.ZH: "zh-cn", } - return language_map.get(language) + + result = BASE_LANGUAGES.get(language) + + # If not found in base languages, try to find the base language from a variant + if not result: + # Convert enum value to string and get the base language part (e.g. es-ES -> es) + lang_str = str(language.value) + base_code = lang_str.split("-")[0].lower() + + # Special handling for Chinese variants + if base_code == "zh": + result = "zh-cn" + else: + # Look up the base code in our supported languages + result = base_code if base_code in BASE_LANGUAGES.values() else None + + return result class XTTSService(TTSService): diff --git a/src/pipecat/transcriptions/language.py b/src/pipecat/transcriptions/language.py index 2ee3d9e95..ee16c14a7 100644 --- a/src/pipecat/transcriptions/language.py +++ b/src/pipecat/transcriptions/language.py @@ -5,7 +5,6 @@ # import sys - from enum import Enum if sys.version_info < (3, 11): @@ -20,46 +19,411 @@ else: class Language(StrEnum): - BG = "bg" # Bulgarian - CA = "ca" # Catalan - ZH = "zh" # Chinese simplified - ZH_TW = "zh-TW" # Chinese traditional - CS = "cs" # Czech - DA = "da" # Danish - NL = "nl" # Dutch - EN = "en" # English - EN_US = "en-US" # English (USA) - EN_AU = "en-AU" # English (Australia) - EN_GB = "en-GB" # English (Great Britain) - EN_NZ = "en-NZ" # English (New Zealand) - EN_IN = "en-IN" # English (India) - ET = "et" # Estonian - FI = "fi" # Finnish - NL_BE = "nl-BE" # Flemmish - FR = "fr" # French - FR_CA = "fr-CA" # French (Canada) - DE = "de" # German - DE_CH = "de-CH" # German (Switzerland) - EL = "el" # Greek - HI = "hi" # Hindi - HU = "hu" # Hungarian - ID = "id" # Indonesian - IT = "it" # Italian - JA = "ja" # Japanese - KO = "ko" # Korean - LV = "lv" # Latvian - LT = "lt" # Lithuanian - MS = "ms" # Malay - NO = "no" # Norwegian - PL = "pl" # Polish - PT = "pt" # Portuguese - PT_BR = "pt-BR" # Portuguese (Brazil) - RO = "ro" # Romanian - RU = "ru" # Russian - SK = "sk" # Slovak - ES = "es" # Spanish - SV = "sv" # Swedish - TH = "th" # Thai - TR = "tr" # Turkish - UK = "uk" # Ukrainian - VI = "vi" # Vietnamese + # Afrikaans + AF = "af" + AF_ZA = "af-ZA" + + # Amharic + AM = "am" + AM_ET = "am-ET" + + # Arabic + AR = "ar" + AR_AE = "ar-AE" + AR_BH = "ar-BH" + AR_DZ = "ar-DZ" + AR_EG = "ar-EG" + AR_IQ = "ar-IQ" + AR_JO = "ar-JO" + AR_KW = "ar-KW" + AR_LB = "ar-LB" + AR_LY = "ar-LY" + AR_MA = "ar-MA" + AR_OM = "ar-OM" + AR_QA = "ar-QA" + AR_SA = "ar-SA" + AR_SY = "ar-SY" + AR_TN = "ar-TN" + AR_YE = "ar-YE" + + # Assamese + AS = "as" + AS_IN = "as-IN" + + # Azerbaijani + AZ = "az" + AZ_AZ = "az-AZ" + + # Bulgarian + BG = "bg" + BG_BG = "bg-BG" + + # Bengali + BN = "bn" + BN_BD = "bn-BD" + BN_IN = "bn-IN" + + # Bosnian + BS = "bs" + BS_BA = "bs-BA" + + # Catalan + CA = "ca" + CA_ES = "ca-ES" + + # Czech + CS = "cs" + CS_CZ = "cs-CZ" + + # Welsh + CY = "cy" + CY_GB = "cy-GB" + + # Danish + DA = "da" + DA_DK = "da-DK" + + # German + DE = "de" + DE_AT = "de-AT" + DE_CH = "de-CH" + DE_DE = "de-DE" + + # Greek + EL = "el" + EL_GR = "el-GR" + + # English + EN = "en" + EN_AU = "en-AU" + EN_CA = "en-CA" + EN_GB = "en-GB" + EN_HK = "en-HK" + EN_IE = "en-IE" + EN_IN = "en-IN" + EN_KE = "en-KE" + EN_NG = "en-NG" + EN_NZ = "en-NZ" + EN_PH = "en-PH" + EN_SG = "en-SG" + EN_TZ = "en-TZ" + EN_US = "en-US" + EN_ZA = "en-ZA" + + # Spanish + ES = "es" + ES_AR = "es-AR" + ES_BO = "es-BO" + ES_CL = "es-CL" + ES_CO = "es-CO" + ES_CR = "es-CR" + ES_CU = "es-CU" + ES_DO = "es-DO" + ES_EC = "es-EC" + ES_ES = "es-ES" + ES_GQ = "es-GQ" + ES_GT = "es-GT" + ES_HN = "es-HN" + ES_MX = "es-MX" + ES_NI = "es-NI" + ES_PA = "es-PA" + ES_PE = "es-PE" + ES_PR = "es-PR" + ES_PY = "es-PY" + ES_SV = "es-SV" + ES_US = "es-US" + ES_UY = "es-UY" + ES_VE = "es-VE" + + # Estonian + ET = "et" + ET_EE = "et-EE" + + # Basque + EU = "eu" + EU_ES = "eu-ES" + + # Persian + FA = "fa" + FA_IR = "fa-IR" + + # Finnish + FI = "fi" + FI_FI = "fi-FI" + + # Filipino + FIL = "fil" + FIL_PH = "fil-PH" + + # French + FR = "fr" + FR_BE = "fr-BE" + FR_CA = "fr-CA" + FR_CH = "fr-CH" + FR_FR = "fr-FR" + + # Irish + GA = "ga" + GA_IE = "ga-IE" + + # Galician + GL = "gl" + GL_ES = "gl-ES" + + # Gujarati + GU = "gu" + GU_IN = "gu-IN" + + # Hebrew + HE = "he" + HE_IL = "he-IL" + + # Hindi + HI = "hi" + HI_IN = "hi-IN" + + # Croatian + HR = "hr" + HR_HR = "hr-HR" + + # Hungarian + HU = "hu" + HU_HU = "hu-HU" + + # Armenian + HY = "hy" + HY_AM = "hy-AM" + + # Indonesian + ID = "id" + ID_ID = "id-ID" + + # Icelandic + IS = "is" + IS_IS = "is-IS" + + # Italian + IT = "it" + IT_IT = "it-IT" + + # Inuktitut + IU_CANS = "iu-Cans" + IU_CANS_CA = "iu-Cans-CA" + IU_LATN = "iu-Latn" + IU_LATN_CA = "iu-Latn-CA" + + # Japanese + JA = "ja" + JA_JP = "ja-JP" + + # Javanese + JV = "jv" + JV_ID = "jv-ID" + + # Georgian + KA = "ka" + KA_GE = "ka-GE" + + # Kazakh + KK = "kk" + KK_KZ = "kk-KZ" + + # Khmer + KM = "km" + KM_KH = "km-KH" + + # Kannada + KN = "kn" + KN_IN = "kn-IN" + + # Korean + KO = "ko" + KO_KR = "ko-KR" + + # Lao + LO = "lo" + LO_LA = "lo-LA" + + # Lithuanian + LT = "lt" + LT_LT = "lt-LT" + + # Latvian + LV = "lv" + LV_LV = "lv-LV" + + # Macedonian + MK = "mk" + MK_MK = "mk-MK" + + # Malayalam + ML = "ml" + ML_IN = "ml-IN" + + # Mongolian + MN = "mn" + MN_MN = "mn-MN" + + # Marathi + MR = "mr" + MR_IN = "mr-IN" + + # Malay + MS = "ms" + MS_MY = "ms-MY" + + # Maltese + MT = "mt" + MT_MT = "mt-MT" + + # Burmese + MY = "my" + MY_MM = "my-MM" + + # Norwegian + NB = "nb" + NB_NO = "nb-NO" + NO = "no" + + # Nepali + NE = "ne" + NE_NP = "ne-NP" + + # Dutch + NL = "nl" + NL_BE = "nl-BE" + NL_NL = "nl-NL" + + # Odia + OR = "or" + OR_IN = "or-IN" + + # Punjabi + PA = "pa" + PA_IN = "pa-IN" + + # Polish + PL = "pl" + PL_PL = "pl-PL" + + # Pashto + PS = "ps" + PS_AF = "ps-AF" + + # Portuguese + PT = "pt" + PT_BR = "pt-BR" + PT_PT = "pt-PT" + + # Romanian + RO = "ro" + RO_RO = "ro-RO" + + # Russian + RU = "ru" + RU_RU = "ru-RU" + + # Sinhala + SI = "si" + SI_LK = "si-LK" + + # Slovak + SK = "sk" + SK_SK = "sk-SK" + + # Slovenian + SL = "sl" + SL_SI = "sl-SI" + + # Somali + SO = "so" + SO_SO = "so-SO" + + # Albanian + SQ = "sq" + SQ_AL = "sq-AL" + + # Serbian + SR = "sr" + SR_RS = "sr-RS" + SR_LATN = "sr-Latn" + SR_LATN_RS = "sr-Latn-RS" + + # Sundanese + SU = "su" + SU_ID = "su-ID" + + # Swedish + SV = "sv" + SV_SE = "sv-SE" + + # Swahili + SW = "sw" + SW_KE = "sw-KE" + SW_TZ = "sw-TZ" + + # Tagalog + TL = "tl" + + # Tamil + TA = "ta" + TA_IN = "ta-IN" + TA_LK = "ta-LK" + TA_MY = "ta-MY" + TA_SG = "ta-SG" + + # Telugu + TE = "te" + TE_IN = "te-IN" + + # Thai + TH = "th" + TH_TH = "th-TH" + + # Turkish + TR = "tr" + TR_TR = "tr-TR" + + # Ukrainian + UK = "uk" + UK_UA = "uk-UA" + + # Urdu + UR = "ur" + UR_IN = "ur-IN" + UR_PK = "ur-PK" + + # Uzbek + UZ = "uz" + UZ_UZ = "uz-UZ" + + # Vietnamese + VI = "vi" + VI_VN = "vi-VN" + + # Wu Chinese + WUU = "wuu" + WUU_CN = "wuu-CN" + + # Yue Chinese + YUE = "yue" + YUE_CN = "yue-CN" + + # Chinese + ZH = "zh" + ZH_CN = "zh-CN" + ZH_CN_GUANGXI = "zh-CN-guangxi" + ZH_CN_HENAN = "zh-CN-henan" + ZH_CN_LIAONING = "zh-CN-liaoning" + ZH_CN_SHAANXI = "zh-CN-shaanxi" + ZH_CN_SHANDONG = "zh-CN-shandong" + ZH_CN_SICHUAN = "zh-CN-sichuan" + ZH_HK = "zh-HK" + ZH_TW = "zh-TW" + + # Xhosa + XH = "xh" + + # Zulu + ZU = "zu" + ZU_ZA = "zu-ZA"