webscout 8.2.2__py3-none-any.whl → 2026.1.19__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- webscout/AIauto.py +524 -143
- webscout/AIbase.py +247 -123
- webscout/AIutel.py +68 -132
- webscout/Bard.py +1072 -535
- webscout/Extra/GitToolkit/__init__.py +2 -2
- webscout/Extra/GitToolkit/gitapi/__init__.py +20 -12
- webscout/Extra/GitToolkit/gitapi/gist.py +142 -0
- webscout/Extra/GitToolkit/gitapi/organization.py +91 -0
- webscout/Extra/GitToolkit/gitapi/repository.py +308 -195
- webscout/Extra/GitToolkit/gitapi/search.py +162 -0
- webscout/Extra/GitToolkit/gitapi/trending.py +236 -0
- webscout/Extra/GitToolkit/gitapi/user.py +128 -96
- webscout/Extra/GitToolkit/gitapi/utils.py +82 -62
- webscout/Extra/YTToolkit/README.md +443 -0
- webscout/Extra/YTToolkit/YTdownloader.py +953 -957
- webscout/Extra/YTToolkit/__init__.py +3 -3
- webscout/Extra/YTToolkit/transcriber.py +595 -476
- webscout/Extra/YTToolkit/ytapi/README.md +230 -0
- webscout/Extra/YTToolkit/ytapi/__init__.py +22 -6
- webscout/Extra/YTToolkit/ytapi/captions.py +190 -0
- webscout/Extra/YTToolkit/ytapi/channel.py +302 -307
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -13
- webscout/Extra/YTToolkit/ytapi/extras.py +178 -45
- webscout/Extra/YTToolkit/ytapi/hashtag.py +120 -0
- webscout/Extra/YTToolkit/ytapi/https.py +89 -88
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -61
- webscout/Extra/YTToolkit/ytapi/playlist.py +59 -59
- webscout/Extra/YTToolkit/ytapi/pool.py +8 -8
- webscout/Extra/YTToolkit/ytapi/query.py +143 -40
- webscout/Extra/YTToolkit/ytapi/shorts.py +122 -0
- webscout/Extra/YTToolkit/ytapi/stream.py +68 -63
- webscout/Extra/YTToolkit/ytapi/suggestions.py +97 -0
- webscout/Extra/YTToolkit/ytapi/utils.py +66 -62
- webscout/Extra/YTToolkit/ytapi/video.py +189 -18
- webscout/Extra/__init__.py +2 -3
- webscout/Extra/gguf.py +1298 -682
- webscout/Extra/tempmail/README.md +488 -0
- webscout/Extra/tempmail/__init__.py +28 -28
- webscout/Extra/tempmail/async_utils.py +143 -141
- webscout/Extra/tempmail/base.py +172 -161
- webscout/Extra/tempmail/cli.py +191 -187
- webscout/Extra/tempmail/emailnator.py +88 -84
- webscout/Extra/tempmail/mail_tm.py +378 -361
- webscout/Extra/tempmail/temp_mail_io.py +304 -292
- webscout/Extra/weather.py +196 -194
- webscout/Extra/weather_ascii.py +17 -15
- webscout/Provider/AISEARCH/PERPLEXED_search.py +175 -0
- webscout/Provider/AISEARCH/Perplexity.py +237 -304
- webscout/Provider/AISEARCH/README.md +106 -0
- webscout/Provider/AISEARCH/__init__.py +16 -10
- webscout/Provider/AISEARCH/brave_search.py +298 -0
- webscout/Provider/AISEARCH/iask_search.py +130 -209
- webscout/Provider/AISEARCH/monica_search.py +200 -246
- webscout/Provider/AISEARCH/webpilotai_search.py +242 -281
- webscout/Provider/Algion.py +413 -0
- webscout/Provider/Andi.py +74 -69
- webscout/Provider/Apriel.py +313 -0
- webscout/Provider/Ayle.py +323 -0
- webscout/Provider/ChatSandbox.py +329 -0
- webscout/Provider/ClaudeOnline.py +365 -0
- webscout/Provider/Cohere.py +232 -208
- webscout/Provider/DeepAI.py +367 -0
- webscout/Provider/Deepinfra.py +343 -173
- webscout/Provider/EssentialAI.py +217 -0
- webscout/Provider/ExaAI.py +274 -261
- webscout/Provider/Gemini.py +60 -54
- webscout/Provider/GithubChat.py +385 -367
- webscout/Provider/Gradient.py +286 -0
- webscout/Provider/Groq.py +556 -670
- webscout/Provider/HadadXYZ.py +323 -0
- webscout/Provider/HeckAI.py +392 -233
- webscout/Provider/HuggingFace.py +387 -0
- webscout/Provider/IBM.py +340 -0
- webscout/Provider/Jadve.py +317 -266
- webscout/Provider/K2Think.py +306 -0
- webscout/Provider/Koboldai.py +221 -381
- webscout/Provider/Netwrck.py +273 -228
- webscout/Provider/Nvidia.py +310 -0
- webscout/Provider/OPENAI/DeepAI.py +489 -0
- webscout/Provider/OPENAI/K2Think.py +423 -0
- webscout/Provider/OPENAI/PI.py +463 -0
- webscout/Provider/OPENAI/README.md +890 -0
- webscout/Provider/OPENAI/TogetherAI.py +405 -0
- webscout/Provider/OPENAI/TwoAI.py +255 -0
- webscout/Provider/OPENAI/__init__.py +148 -25
- webscout/Provider/OPENAI/ai4chat.py +348 -0
- webscout/Provider/OPENAI/akashgpt.py +436 -0
- webscout/Provider/OPENAI/algion.py +303 -0
- webscout/Provider/OPENAI/ayle.py +365 -0
- webscout/Provider/OPENAI/base.py +253 -46
- webscout/Provider/OPENAI/cerebras.py +296 -0
- webscout/Provider/OPENAI/chatgpt.py +514 -193
- webscout/Provider/OPENAI/chatsandbox.py +233 -0
- webscout/Provider/OPENAI/deepinfra.py +403 -272
- webscout/Provider/OPENAI/e2b.py +2370 -1350
- webscout/Provider/OPENAI/elmo.py +278 -0
- webscout/Provider/OPENAI/exaai.py +186 -138
- webscout/Provider/OPENAI/freeassist.py +446 -0
- webscout/Provider/OPENAI/gradient.py +448 -0
- webscout/Provider/OPENAI/groq.py +380 -0
- webscout/Provider/OPENAI/hadadxyz.py +292 -0
- webscout/Provider/OPENAI/heckai.py +100 -104
- webscout/Provider/OPENAI/huggingface.py +321 -0
- webscout/Provider/OPENAI/ibm.py +425 -0
- webscout/Provider/OPENAI/llmchat.py +253 -0
- webscout/Provider/OPENAI/llmchatco.py +378 -327
- webscout/Provider/OPENAI/meta.py +541 -0
- webscout/Provider/OPENAI/netwrck.py +110 -84
- webscout/Provider/OPENAI/nvidia.py +317 -0
- webscout/Provider/OPENAI/oivscode.py +348 -0
- webscout/Provider/OPENAI/openrouter.py +328 -0
- webscout/Provider/OPENAI/pydantic_imports.py +1 -0
- webscout/Provider/OPENAI/sambanova.py +397 -0
- webscout/Provider/OPENAI/sonus.py +126 -115
- webscout/Provider/OPENAI/textpollinations.py +218 -133
- webscout/Provider/OPENAI/toolbaz.py +136 -166
- webscout/Provider/OPENAI/typefully.py +419 -0
- webscout/Provider/OPENAI/typliai.py +279 -0
- webscout/Provider/OPENAI/utils.py +314 -211
- webscout/Provider/OPENAI/wisecat.py +103 -125
- webscout/Provider/OPENAI/writecream.py +185 -156
- webscout/Provider/OPENAI/x0gpt.py +227 -136
- webscout/Provider/OPENAI/zenmux.py +380 -0
- webscout/Provider/OpenRouter.py +386 -0
- webscout/Provider/Openai.py +337 -496
- webscout/Provider/PI.py +443 -344
- webscout/Provider/QwenLM.py +346 -254
- webscout/Provider/STT/__init__.py +28 -0
- webscout/Provider/STT/base.py +303 -0
- webscout/Provider/STT/elevenlabs.py +264 -0
- webscout/Provider/Sambanova.py +317 -0
- webscout/Provider/TTI/README.md +69 -0
- webscout/Provider/TTI/__init__.py +37 -12
- webscout/Provider/TTI/base.py +147 -0
- webscout/Provider/TTI/claudeonline.py +393 -0
- webscout/Provider/TTI/magicstudio.py +292 -0
- webscout/Provider/TTI/miragic.py +180 -0
- webscout/Provider/TTI/pollinations.py +331 -0
- webscout/Provider/TTI/together.py +334 -0
- webscout/Provider/TTI/utils.py +14 -0
- webscout/Provider/TTS/README.md +186 -0
- webscout/Provider/TTS/__init__.py +43 -7
- webscout/Provider/TTS/base.py +523 -0
- webscout/Provider/TTS/deepgram.py +286 -156
- webscout/Provider/TTS/elevenlabs.py +189 -111
- webscout/Provider/TTS/freetts.py +218 -0
- webscout/Provider/TTS/murfai.py +288 -113
- webscout/Provider/TTS/openai_fm.py +364 -0
- webscout/Provider/TTS/parler.py +203 -111
- webscout/Provider/TTS/qwen.py +334 -0
- webscout/Provider/TTS/sherpa.py +286 -0
- webscout/Provider/TTS/speechma.py +693 -180
- webscout/Provider/TTS/streamElements.py +275 -333
- webscout/Provider/TTS/utils.py +280 -280
- webscout/Provider/TextPollinationsAI.py +221 -121
- webscout/Provider/TogetherAI.py +450 -0
- webscout/Provider/TwoAI.py +309 -199
- webscout/Provider/TypliAI.py +311 -0
- webscout/Provider/UNFINISHED/ChatHub.py +219 -0
- webscout/Provider/{OPENAI/glider.py → UNFINISHED/ChutesAI.py} +160 -145
- webscout/Provider/UNFINISHED/GizAI.py +300 -0
- webscout/Provider/UNFINISHED/Marcus.py +218 -0
- webscout/Provider/UNFINISHED/Qodo.py +481 -0
- webscout/Provider/UNFINISHED/XenAI.py +330 -0
- webscout/Provider/{Youchat.py → UNFINISHED/Youchat.py} +64 -47
- webscout/Provider/UNFINISHED/aihumanizer.py +41 -0
- webscout/Provider/UNFINISHED/grammerchecker.py +37 -0
- webscout/Provider/UNFINISHED/liner.py +342 -0
- webscout/Provider/UNFINISHED/liner_api_request.py +246 -0
- webscout/Provider/UNFINISHED/samurai.py +231 -0
- webscout/Provider/WiseCat.py +256 -196
- webscout/Provider/WrDoChat.py +390 -0
- webscout/Provider/__init__.py +115 -198
- webscout/Provider/ai4chat.py +181 -202
- webscout/Provider/akashgpt.py +330 -342
- webscout/Provider/cerebras.py +397 -242
- webscout/Provider/cleeai.py +236 -213
- webscout/Provider/elmo.py +291 -234
- webscout/Provider/geminiapi.py +343 -208
- webscout/Provider/julius.py +245 -223
- webscout/Provider/learnfastai.py +333 -266
- webscout/Provider/llama3mitril.py +230 -180
- webscout/Provider/llmchat.py +308 -213
- webscout/Provider/llmchatco.py +321 -311
- webscout/Provider/meta.py +996 -794
- webscout/Provider/oivscode.py +332 -0
- webscout/Provider/searchchat.py +316 -293
- webscout/Provider/sonus.py +264 -208
- webscout/Provider/toolbaz.py +359 -320
- webscout/Provider/turboseek.py +332 -219
- webscout/Provider/typefully.py +262 -280
- webscout/Provider/x0gpt.py +332 -256
- webscout/__init__.py +31 -38
- webscout/__main__.py +5 -5
- webscout/cli.py +585 -293
- webscout/client.py +1497 -0
- webscout/conversation.py +140 -565
- webscout/exceptions.py +383 -339
- webscout/litagent/__init__.py +29 -29
- webscout/litagent/agent.py +492 -455
- webscout/litagent/constants.py +60 -60
- webscout/models.py +505 -181
- webscout/optimizers.py +32 -378
- webscout/prompt_manager.py +376 -274
- webscout/sanitize.py +1514 -0
- webscout/scout/README.md +452 -0
- webscout/scout/__init__.py +8 -8
- webscout/scout/core/__init__.py +7 -7
- webscout/scout/core/crawler.py +330 -140
- webscout/scout/core/scout.py +800 -568
- webscout/scout/core/search_result.py +51 -96
- webscout/scout/core/text_analyzer.py +64 -63
- webscout/scout/core/text_utils.py +412 -277
- webscout/scout/core/web_analyzer.py +54 -52
- webscout/scout/element.py +872 -460
- webscout/scout/parsers/__init__.py +70 -69
- webscout/scout/parsers/html5lib_parser.py +182 -172
- webscout/scout/parsers/html_parser.py +238 -236
- webscout/scout/parsers/lxml_parser.py +203 -178
- webscout/scout/utils.py +38 -37
- webscout/search/__init__.py +47 -0
- webscout/search/base.py +201 -0
- webscout/search/bing_main.py +45 -0
- webscout/search/brave_main.py +92 -0
- webscout/search/duckduckgo_main.py +57 -0
- webscout/search/engines/__init__.py +127 -0
- webscout/search/engines/bing/__init__.py +15 -0
- webscout/search/engines/bing/base.py +35 -0
- webscout/search/engines/bing/images.py +114 -0
- webscout/search/engines/bing/news.py +96 -0
- webscout/search/engines/bing/suggestions.py +36 -0
- webscout/search/engines/bing/text.py +109 -0
- webscout/search/engines/brave/__init__.py +19 -0
- webscout/search/engines/brave/base.py +47 -0
- webscout/search/engines/brave/images.py +213 -0
- webscout/search/engines/brave/news.py +353 -0
- webscout/search/engines/brave/suggestions.py +318 -0
- webscout/search/engines/brave/text.py +167 -0
- webscout/search/engines/brave/videos.py +364 -0
- webscout/search/engines/duckduckgo/__init__.py +25 -0
- webscout/search/engines/duckduckgo/answers.py +80 -0
- webscout/search/engines/duckduckgo/base.py +189 -0
- webscout/search/engines/duckduckgo/images.py +100 -0
- webscout/search/engines/duckduckgo/maps.py +183 -0
- webscout/search/engines/duckduckgo/news.py +70 -0
- webscout/search/engines/duckduckgo/suggestions.py +22 -0
- webscout/search/engines/duckduckgo/text.py +221 -0
- webscout/search/engines/duckduckgo/translate.py +48 -0
- webscout/search/engines/duckduckgo/videos.py +80 -0
- webscout/search/engines/duckduckgo/weather.py +84 -0
- webscout/search/engines/mojeek.py +61 -0
- webscout/search/engines/wikipedia.py +77 -0
- webscout/search/engines/yahoo/__init__.py +41 -0
- webscout/search/engines/yahoo/answers.py +19 -0
- webscout/search/engines/yahoo/base.py +34 -0
- webscout/search/engines/yahoo/images.py +323 -0
- webscout/search/engines/yahoo/maps.py +19 -0
- webscout/search/engines/yahoo/news.py +258 -0
- webscout/search/engines/yahoo/suggestions.py +140 -0
- webscout/search/engines/yahoo/text.py +273 -0
- webscout/search/engines/yahoo/translate.py +19 -0
- webscout/search/engines/yahoo/videos.py +302 -0
- webscout/search/engines/yahoo/weather.py +220 -0
- webscout/search/engines/yandex.py +67 -0
- webscout/search/engines/yep/__init__.py +13 -0
- webscout/search/engines/yep/base.py +34 -0
- webscout/search/engines/yep/images.py +101 -0
- webscout/search/engines/yep/suggestions.py +38 -0
- webscout/search/engines/yep/text.py +99 -0
- webscout/search/http_client.py +172 -0
- webscout/search/results.py +141 -0
- webscout/search/yahoo_main.py +57 -0
- webscout/search/yep_main.py +48 -0
- webscout/server/__init__.py +48 -0
- webscout/server/config.py +78 -0
- webscout/server/exceptions.py +69 -0
- webscout/server/providers.py +286 -0
- webscout/server/request_models.py +131 -0
- webscout/server/request_processing.py +404 -0
- webscout/server/routes.py +642 -0
- webscout/server/server.py +351 -0
- webscout/server/ui_templates.py +1171 -0
- webscout/swiftcli/__init__.py +79 -809
- webscout/swiftcli/core/__init__.py +7 -0
- webscout/swiftcli/core/cli.py +574 -0
- webscout/swiftcli/core/context.py +98 -0
- webscout/swiftcli/core/group.py +268 -0
- webscout/swiftcli/decorators/__init__.py +28 -0
- webscout/swiftcli/decorators/command.py +243 -0
- webscout/swiftcli/decorators/options.py +247 -0
- webscout/swiftcli/decorators/output.py +392 -0
- webscout/swiftcli/exceptions.py +21 -0
- webscout/swiftcli/plugins/__init__.py +9 -0
- webscout/swiftcli/plugins/base.py +134 -0
- webscout/swiftcli/plugins/manager.py +269 -0
- webscout/swiftcli/utils/__init__.py +58 -0
- webscout/swiftcli/utils/formatting.py +251 -0
- webscout/swiftcli/utils/parsing.py +368 -0
- webscout/update_checker.py +280 -136
- webscout/utils.py +28 -14
- webscout/version.py +2 -1
- webscout/version.py.bak +3 -0
- webscout/zeroart/__init__.py +218 -55
- webscout/zeroart/base.py +70 -60
- webscout/zeroart/effects.py +155 -99
- webscout/zeroart/fonts.py +1799 -816
- webscout-2026.1.19.dist-info/METADATA +638 -0
- webscout-2026.1.19.dist-info/RECORD +312 -0
- {webscout-8.2.2.dist-info → webscout-2026.1.19.dist-info}/WHEEL +1 -1
- webscout-2026.1.19.dist-info/entry_points.txt +4 -0
- webscout-2026.1.19.dist-info/top_level.txt +1 -0
- inferno/__init__.py +0 -6
- inferno/__main__.py +0 -9
- inferno/cli.py +0 -6
- webscout/DWEBS.py +0 -477
- webscout/Extra/autocoder/__init__.py +0 -9
- webscout/Extra/autocoder/autocoder.py +0 -849
- webscout/Extra/autocoder/autocoder_utiles.py +0 -332
- webscout/LLM.py +0 -442
- webscout/Litlogger/__init__.py +0 -67
- webscout/Litlogger/core/__init__.py +0 -6
- webscout/Litlogger/core/level.py +0 -23
- webscout/Litlogger/core/logger.py +0 -165
- webscout/Litlogger/handlers/__init__.py +0 -12
- webscout/Litlogger/handlers/console.py +0 -33
- webscout/Litlogger/handlers/file.py +0 -143
- webscout/Litlogger/handlers/network.py +0 -173
- webscout/Litlogger/styles/__init__.py +0 -7
- webscout/Litlogger/styles/colors.py +0 -249
- webscout/Litlogger/styles/formats.py +0 -458
- webscout/Litlogger/styles/text.py +0 -87
- webscout/Litlogger/utils/__init__.py +0 -6
- webscout/Litlogger/utils/detectors.py +0 -153
- webscout/Litlogger/utils/formatters.py +0 -200
- webscout/Local/__init__.py +0 -12
- webscout/Local/__main__.py +0 -9
- webscout/Local/api.py +0 -576
- webscout/Local/cli.py +0 -516
- webscout/Local/config.py +0 -75
- webscout/Local/llm.py +0 -287
- webscout/Local/model_manager.py +0 -253
- webscout/Local/server.py +0 -721
- webscout/Local/utils.py +0 -93
- webscout/Provider/AI21.py +0 -177
- webscout/Provider/AISEARCH/DeepFind.py +0 -250
- webscout/Provider/AISEARCH/ISou.py +0 -256
- webscout/Provider/AISEARCH/felo_search.py +0 -228
- webscout/Provider/AISEARCH/genspark_search.py +0 -208
- webscout/Provider/AISEARCH/hika_search.py +0 -194
- webscout/Provider/AISEARCH/scira_search.py +0 -324
- webscout/Provider/Aitopia.py +0 -292
- webscout/Provider/AllenAI.py +0 -413
- webscout/Provider/Blackboxai.py +0 -229
- webscout/Provider/C4ai.py +0 -432
- webscout/Provider/ChatGPTClone.py +0 -226
- webscout/Provider/ChatGPTES.py +0 -237
- webscout/Provider/ChatGPTGratis.py +0 -194
- webscout/Provider/Chatify.py +0 -175
- webscout/Provider/Cloudflare.py +0 -273
- webscout/Provider/DeepSeek.py +0 -196
- webscout/Provider/ElectronHub.py +0 -709
- webscout/Provider/ExaChat.py +0 -342
- webscout/Provider/Free2GPT.py +0 -241
- webscout/Provider/GPTWeb.py +0 -193
- webscout/Provider/Glider.py +0 -211
- webscout/Provider/HF_space/__init__.py +0 -0
- webscout/Provider/HF_space/qwen_qwen2.py +0 -206
- webscout/Provider/HuggingFaceChat.py +0 -462
- webscout/Provider/Hunyuan.py +0 -272
- webscout/Provider/LambdaChat.py +0 -392
- webscout/Provider/Llama.py +0 -200
- webscout/Provider/Llama3.py +0 -204
- webscout/Provider/Marcus.py +0 -148
- webscout/Provider/OLLAMA.py +0 -396
- webscout/Provider/OPENAI/c4ai.py +0 -367
- webscout/Provider/OPENAI/chatgptclone.py +0 -460
- webscout/Provider/OPENAI/exachat.py +0 -433
- webscout/Provider/OPENAI/freeaichat.py +0 -352
- webscout/Provider/OPENAI/opkfc.py +0 -488
- webscout/Provider/OPENAI/scirachat.py +0 -463
- webscout/Provider/OPENAI/standardinput.py +0 -425
- webscout/Provider/OPENAI/typegpt.py +0 -346
- webscout/Provider/OPENAI/uncovrAI.py +0 -455
- webscout/Provider/OPENAI/venice.py +0 -413
- webscout/Provider/OPENAI/yep.py +0 -327
- webscout/Provider/OpenGPT.py +0 -199
- webscout/Provider/Perplexitylabs.py +0 -415
- webscout/Provider/Phind.py +0 -535
- webscout/Provider/PizzaGPT.py +0 -198
- webscout/Provider/Reka.py +0 -214
- webscout/Provider/StandardInput.py +0 -278
- webscout/Provider/TTI/AiForce/__init__.py +0 -22
- webscout/Provider/TTI/AiForce/async_aiforce.py +0 -224
- webscout/Provider/TTI/AiForce/sync_aiforce.py +0 -245
- webscout/Provider/TTI/FreeAIPlayground/__init__.py +0 -9
- webscout/Provider/TTI/FreeAIPlayground/async_freeaiplayground.py +0 -181
- webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +0 -180
- webscout/Provider/TTI/ImgSys/__init__.py +0 -23
- webscout/Provider/TTI/ImgSys/async_imgsys.py +0 -202
- webscout/Provider/TTI/ImgSys/sync_imgsys.py +0 -195
- webscout/Provider/TTI/MagicStudio/__init__.py +0 -2
- webscout/Provider/TTI/MagicStudio/async_magicstudio.py +0 -111
- webscout/Provider/TTI/MagicStudio/sync_magicstudio.py +0 -109
- webscout/Provider/TTI/Nexra/__init__.py +0 -22
- webscout/Provider/TTI/Nexra/async_nexra.py +0 -286
- webscout/Provider/TTI/Nexra/sync_nexra.py +0 -258
- webscout/Provider/TTI/PollinationsAI/__init__.py +0 -23
- webscout/Provider/TTI/PollinationsAI/async_pollinations.py +0 -311
- webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +0 -265
- webscout/Provider/TTI/aiarta/__init__.py +0 -2
- webscout/Provider/TTI/aiarta/async_aiarta.py +0 -482
- webscout/Provider/TTI/aiarta/sync_aiarta.py +0 -440
- webscout/Provider/TTI/artbit/__init__.py +0 -22
- webscout/Provider/TTI/artbit/async_artbit.py +0 -155
- webscout/Provider/TTI/artbit/sync_artbit.py +0 -148
- webscout/Provider/TTI/fastflux/__init__.py +0 -22
- webscout/Provider/TTI/fastflux/async_fastflux.py +0 -261
- webscout/Provider/TTI/fastflux/sync_fastflux.py +0 -252
- webscout/Provider/TTI/huggingface/__init__.py +0 -22
- webscout/Provider/TTI/huggingface/async_huggingface.py +0 -199
- webscout/Provider/TTI/huggingface/sync_huggingface.py +0 -195
- webscout/Provider/TTI/piclumen/__init__.py +0 -23
- webscout/Provider/TTI/piclumen/async_piclumen.py +0 -268
- webscout/Provider/TTI/piclumen/sync_piclumen.py +0 -233
- webscout/Provider/TTI/pixelmuse/__init__.py +0 -4
- webscout/Provider/TTI/pixelmuse/async_pixelmuse.py +0 -249
- webscout/Provider/TTI/pixelmuse/sync_pixelmuse.py +0 -182
- webscout/Provider/TTI/talkai/__init__.py +0 -4
- webscout/Provider/TTI/talkai/async_talkai.py +0 -229
- webscout/Provider/TTI/talkai/sync_talkai.py +0 -207
- webscout/Provider/TTS/gesserit.py +0 -127
- webscout/Provider/TeachAnything.py +0 -187
- webscout/Provider/Venice.py +0 -219
- webscout/Provider/VercelAI.py +0 -234
- webscout/Provider/WebSim.py +0 -228
- webscout/Provider/Writecream.py +0 -211
- webscout/Provider/WritingMate.py +0 -197
- webscout/Provider/aimathgpt.py +0 -189
- webscout/Provider/askmyai.py +0 -158
- webscout/Provider/asksteve.py +0 -203
- webscout/Provider/bagoodex.py +0 -145
- webscout/Provider/chatglm.py +0 -205
- webscout/Provider/copilot.py +0 -428
- webscout/Provider/freeaichat.py +0 -271
- webscout/Provider/gaurish.py +0 -244
- webscout/Provider/geminiprorealtime.py +0 -160
- webscout/Provider/granite.py +0 -187
- webscout/Provider/hermes.py +0 -219
- webscout/Provider/koala.py +0 -268
- webscout/Provider/labyrinth.py +0 -340
- webscout/Provider/lepton.py +0 -194
- webscout/Provider/llamatutor.py +0 -192
- webscout/Provider/multichat.py +0 -325
- webscout/Provider/promptrefine.py +0 -193
- webscout/Provider/scira_chat.py +0 -277
- webscout/Provider/scnet.py +0 -187
- webscout/Provider/talkai.py +0 -194
- webscout/Provider/tutorai.py +0 -252
- webscout/Provider/typegpt.py +0 -232
- webscout/Provider/uncovr.py +0 -312
- webscout/Provider/yep.py +0 -376
- webscout/litprinter/__init__.py +0 -59
- webscout/scout/core.py +0 -881
- webscout/tempid.py +0 -128
- webscout/webscout_search.py +0 -1346
- webscout/webscout_search_async.py +0 -877
- webscout/yep_search.py +0 -297
- webscout-8.2.2.dist-info/METADATA +0 -734
- webscout-8.2.2.dist-info/RECORD +0 -309
- webscout-8.2.2.dist-info/entry_points.txt +0 -5
- webscout-8.2.2.dist-info/top_level.txt +0 -3
- webstoken/__init__.py +0 -30
- webstoken/classifier.py +0 -189
- webstoken/keywords.py +0 -216
- webstoken/language.py +0 -128
- webstoken/ner.py +0 -164
- webstoken/normalizer.py +0 -35
- webstoken/processor.py +0 -77
- webstoken/sentiment.py +0 -206
- webstoken/stemmer.py +0 -73
- webstoken/tagger.py +0 -60
- webstoken/tokenizer.py +0 -158
- {webscout-8.2.2.dist-info → webscout-2026.1.19.dist-info/licenses}/LICENSE.md +0 -0
|
@@ -1,180 +1,693 @@
|
|
|
1
|
-
##################################################################################
|
|
2
|
-
## Modified version of code written by t.me/infip1217 ##
|
|
3
|
-
##################################################################################
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
from io import BytesIO
|
|
9
|
-
from
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
from
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"""
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
""
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
1
|
+
##################################################################################
|
|
2
|
+
## Modified version of code written by t.me/infip1217 ##
|
|
3
|
+
##################################################################################
|
|
4
|
+
import pathlib
|
|
5
|
+
import tempfile
|
|
6
|
+
import time
|
|
7
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
8
|
+
from io import BytesIO
|
|
9
|
+
from typing import Any, Generator, Optional, Union, cast
|
|
10
|
+
|
|
11
|
+
import requests
|
|
12
|
+
from litprinter import ic
|
|
13
|
+
|
|
14
|
+
from webscout import exceptions
|
|
15
|
+
from webscout.litagent import LitAgent
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
from . import utils
|
|
19
|
+
from .base import BaseTTSProvider
|
|
20
|
+
except ImportError:
|
|
21
|
+
# Handle direct execution
|
|
22
|
+
import os
|
|
23
|
+
import sys
|
|
24
|
+
|
|
25
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", ".."))
|
|
26
|
+
from webscout.Provider.TTS import utils
|
|
27
|
+
from webscout.Provider.TTS.base import BaseTTSProvider
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class SpeechMaTTS(BaseTTSProvider):
|
|
31
|
+
"""
|
|
32
|
+
Text-to-speech provider using the SpeechMa API with OpenAI-compatible interface.
|
|
33
|
+
|
|
34
|
+
This provider follows the OpenAI TTS API structure with support for:
|
|
35
|
+
- Multiple TTS models (gpt-4o-mini-tts, tts-1, tts-1-hd)
|
|
36
|
+
- Multilingual voices with pitch and rate control
|
|
37
|
+
- Voice instructions for controlling speech aspects
|
|
38
|
+
- Multiple output formats
|
|
39
|
+
- Streaming support
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
required_auth = False
|
|
43
|
+
|
|
44
|
+
# Request headers
|
|
45
|
+
headers = {
|
|
46
|
+
"authority": "speechma.com",
|
|
47
|
+
"origin": "https://speechma.com",
|
|
48
|
+
"referer": "https://speechma.com/",
|
|
49
|
+
"content-type": "application/json",
|
|
50
|
+
**LitAgent().generate_fingerprint(),
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# SpeechMa doesn't support different models - set to None
|
|
54
|
+
SUPPORTED_MODELS = None
|
|
55
|
+
|
|
56
|
+
# All supported voices from SpeechMa API
|
|
57
|
+
SUPPORTED_VOICES = [
|
|
58
|
+
"aditi",
|
|
59
|
+
"amy",
|
|
60
|
+
"astrid",
|
|
61
|
+
"bianca",
|
|
62
|
+
"carla",
|
|
63
|
+
"carmen",
|
|
64
|
+
"celine",
|
|
65
|
+
"chant",
|
|
66
|
+
"conchita",
|
|
67
|
+
"cristiano",
|
|
68
|
+
"dora",
|
|
69
|
+
"enrique",
|
|
70
|
+
"ewa",
|
|
71
|
+
"filiz",
|
|
72
|
+
"geraint",
|
|
73
|
+
"giorgio",
|
|
74
|
+
"gwyneth",
|
|
75
|
+
"hans",
|
|
76
|
+
"ines",
|
|
77
|
+
"ivy",
|
|
78
|
+
"jacek",
|
|
79
|
+
"jan",
|
|
80
|
+
"joanna",
|
|
81
|
+
"joey",
|
|
82
|
+
"justin",
|
|
83
|
+
"karl",
|
|
84
|
+
"kendra",
|
|
85
|
+
"kimberly",
|
|
86
|
+
"lea",
|
|
87
|
+
"liv",
|
|
88
|
+
"lotte",
|
|
89
|
+
"lucia",
|
|
90
|
+
"lupe",
|
|
91
|
+
"mads",
|
|
92
|
+
"maja",
|
|
93
|
+
"marlene",
|
|
94
|
+
"mathieu",
|
|
95
|
+
"matthew",
|
|
96
|
+
"maxim",
|
|
97
|
+
"mia",
|
|
98
|
+
"miguel",
|
|
99
|
+
"mizuki",
|
|
100
|
+
"naja",
|
|
101
|
+
"nicole",
|
|
102
|
+
"penelope",
|
|
103
|
+
"raveena",
|
|
104
|
+
"ricardo",
|
|
105
|
+
"ruben",
|
|
106
|
+
"russell",
|
|
107
|
+
"salli",
|
|
108
|
+
"seoyeon",
|
|
109
|
+
"takumi",
|
|
110
|
+
"tatyana",
|
|
111
|
+
"vicki",
|
|
112
|
+
"vitoria",
|
|
113
|
+
"zeina",
|
|
114
|
+
"zhiyu",
|
|
115
|
+
"aditi-neural",
|
|
116
|
+
"amy-neural",
|
|
117
|
+
"aria-neural",
|
|
118
|
+
"ayanda-neural",
|
|
119
|
+
"brian-neural",
|
|
120
|
+
"emma-neural",
|
|
121
|
+
"jenny-neural",
|
|
122
|
+
"joey-neural",
|
|
123
|
+
"justin-neural",
|
|
124
|
+
"kendra-neural",
|
|
125
|
+
"kimberly-neural",
|
|
126
|
+
"matthew-neural",
|
|
127
|
+
"olivia-neural",
|
|
128
|
+
"ruth-neural",
|
|
129
|
+
"salli-neural",
|
|
130
|
+
"stephen-neural",
|
|
131
|
+
"suvi-neural",
|
|
132
|
+
"camila-neural",
|
|
133
|
+
"lupe-neural",
|
|
134
|
+
"pedro-neural",
|
|
135
|
+
"natasha-neural",
|
|
136
|
+
"william-neural",
|
|
137
|
+
"clara-neural",
|
|
138
|
+
"liam-neural",
|
|
139
|
+
"libby-neural",
|
|
140
|
+
"maisie-neural",
|
|
141
|
+
"ryan-neural",
|
|
142
|
+
"sonia-neural",
|
|
143
|
+
"thomas-neural",
|
|
144
|
+
"aria-multilingual",
|
|
145
|
+
"andrew-multilingual",
|
|
146
|
+
"brian-multilingual",
|
|
147
|
+
"emma-multilingual",
|
|
148
|
+
"jenny-multilingual",
|
|
149
|
+
"ryan-multilingual",
|
|
150
|
+
"adam-multilingual",
|
|
151
|
+
"liam-multilingual",
|
|
152
|
+
"aria-turbo",
|
|
153
|
+
"andrew-turbo",
|
|
154
|
+
"brian-turbo",
|
|
155
|
+
"emma-turbo",
|
|
156
|
+
"jenny-turbo",
|
|
157
|
+
"ryan-turbo",
|
|
158
|
+
"adam-turbo",
|
|
159
|
+
"liam-turbo",
|
|
160
|
+
"aria-hd",
|
|
161
|
+
"andrew-hd",
|
|
162
|
+
"brian-hd",
|
|
163
|
+
"emma-hd",
|
|
164
|
+
"jenny-hd",
|
|
165
|
+
"andrew-hd-2",
|
|
166
|
+
"aria-hd-2",
|
|
167
|
+
"adam-hd",
|
|
168
|
+
"ava-hd",
|
|
169
|
+
"davis-hd",
|
|
170
|
+
"brian-hd-2",
|
|
171
|
+
"christopher-hd",
|
|
172
|
+
"coral-hd",
|
|
173
|
+
"emma-hd-2",
|
|
174
|
+
"eric-hd",
|
|
175
|
+
"fable-hd",
|
|
176
|
+
"jenny-hd-2",
|
|
177
|
+
"michelle-hd",
|
|
178
|
+
"roger-hd",
|
|
179
|
+
"sage-hd",
|
|
180
|
+
"vale-hd",
|
|
181
|
+
"verse-hd",
|
|
182
|
+
# Legacy voice names for backward compatibility
|
|
183
|
+
"emma",
|
|
184
|
+
"ava",
|
|
185
|
+
"brian",
|
|
186
|
+
"andrew",
|
|
187
|
+
"aria",
|
|
188
|
+
"christopher",
|
|
189
|
+
"eric",
|
|
190
|
+
"jenny",
|
|
191
|
+
"michelle",
|
|
192
|
+
"roger",
|
|
193
|
+
"libby",
|
|
194
|
+
"ryan",
|
|
195
|
+
"sonia",
|
|
196
|
+
"thomas",
|
|
197
|
+
"natasha",
|
|
198
|
+
"william",
|
|
199
|
+
"clara",
|
|
200
|
+
"liam",
|
|
201
|
+
]
|
|
202
|
+
|
|
203
|
+
# Voice mapping for SpeechMa API compatibility (lowercase keys for all voices)
|
|
204
|
+
voice_mapping = {
|
|
205
|
+
# Standard voices
|
|
206
|
+
"aditi": "voice-1",
|
|
207
|
+
"amy": "voice-2",
|
|
208
|
+
"astrid": "voice-3",
|
|
209
|
+
"bianca": "voice-4",
|
|
210
|
+
"carla": "voice-5",
|
|
211
|
+
"carmen": "voice-6",
|
|
212
|
+
"celine": "voice-7",
|
|
213
|
+
"chant": "voice-8",
|
|
214
|
+
"conchita": "voice-9",
|
|
215
|
+
"cristiano": "voice-10",
|
|
216
|
+
"dora": "voice-11",
|
|
217
|
+
"enrique": "voice-12",
|
|
218
|
+
"ewa": "voice-13",
|
|
219
|
+
"filiz": "voice-14",
|
|
220
|
+
"geraint": "voice-15",
|
|
221
|
+
"giorgio": "voice-16",
|
|
222
|
+
"gwyneth": "voice-17",
|
|
223
|
+
"hans": "voice-18",
|
|
224
|
+
"ines": "voice-19",
|
|
225
|
+
"ivy": "voice-20",
|
|
226
|
+
"jacek": "voice-21",
|
|
227
|
+
"jan": "voice-22",
|
|
228
|
+
"joanna": "voice-23",
|
|
229
|
+
"joey": "voice-24",
|
|
230
|
+
"justin": "voice-25",
|
|
231
|
+
"karl": "voice-26",
|
|
232
|
+
"kendra": "voice-27",
|
|
233
|
+
"kimberly": "voice-28",
|
|
234
|
+
"lea": "voice-29",
|
|
235
|
+
"liv": "voice-30",
|
|
236
|
+
"lotte": "voice-31",
|
|
237
|
+
"lucia": "voice-32",
|
|
238
|
+
"lupe": "voice-33",
|
|
239
|
+
"mads": "voice-34",
|
|
240
|
+
"maja": "voice-35",
|
|
241
|
+
"marlene": "voice-36",
|
|
242
|
+
"mathieu": "voice-37",
|
|
243
|
+
"matthew": "voice-38",
|
|
244
|
+
"maxim": "voice-39",
|
|
245
|
+
"mia": "voice-40",
|
|
246
|
+
"miguel": "voice-41",
|
|
247
|
+
"mizuki": "voice-42",
|
|
248
|
+
"naja": "voice-43",
|
|
249
|
+
"nicole": "voice-44",
|
|
250
|
+
"penelope": "voice-45",
|
|
251
|
+
"raveena": "voice-46",
|
|
252
|
+
"ricardo": "voice-47",
|
|
253
|
+
"ruben": "voice-48",
|
|
254
|
+
"russell": "voice-49",
|
|
255
|
+
"salli": "voice-50",
|
|
256
|
+
"seoyeon": "voice-51",
|
|
257
|
+
"takumi": "voice-52",
|
|
258
|
+
"tatyana": "voice-53",
|
|
259
|
+
"vicki": "voice-54",
|
|
260
|
+
"vitoria": "voice-55",
|
|
261
|
+
"zeina": "voice-56",
|
|
262
|
+
"zhiyu": "voice-57",
|
|
263
|
+
# Neural voices
|
|
264
|
+
"aditi-neural": "voice-58",
|
|
265
|
+
"amy-neural": "voice-59",
|
|
266
|
+
"aria-neural": "voice-60",
|
|
267
|
+
"ayanda-neural": "voice-61",
|
|
268
|
+
"brian-neural": "voice-62",
|
|
269
|
+
"emma-neural": "voice-63",
|
|
270
|
+
"jenny-neural": "voice-64",
|
|
271
|
+
"joey-neural": "voice-65",
|
|
272
|
+
"justin-neural": "voice-66",
|
|
273
|
+
"kendra-neural": "voice-67",
|
|
274
|
+
"kimberly-neural": "voice-68",
|
|
275
|
+
"matthew-neural": "voice-69",
|
|
276
|
+
"olivia-neural": "voice-70",
|
|
277
|
+
"ruth-neural": "voice-71",
|
|
278
|
+
"salli-neural": "voice-72",
|
|
279
|
+
"stephen-neural": "voice-73",
|
|
280
|
+
"suvi-neural": "voice-74",
|
|
281
|
+
"camila-neural": "voice-75",
|
|
282
|
+
"lupe-neural": "voice-76",
|
|
283
|
+
"pedro-neural": "voice-77",
|
|
284
|
+
"natasha-neural": "voice-78",
|
|
285
|
+
"william-neural": "voice-79",
|
|
286
|
+
"clara-neural": "voice-80",
|
|
287
|
+
"liam-neural": "voice-81",
|
|
288
|
+
"libby-neural": "voice-82",
|
|
289
|
+
"maisie-neural": "voice-83",
|
|
290
|
+
"ryan-neural": "voice-84",
|
|
291
|
+
"sonia-neural": "voice-85",
|
|
292
|
+
"thomas-neural": "voice-86",
|
|
293
|
+
# Multilingual voices
|
|
294
|
+
"aria-multilingual": "voice-87",
|
|
295
|
+
"andrew-multilingual": "voice-88",
|
|
296
|
+
"brian-multilingual": "voice-89",
|
|
297
|
+
"emma-multilingual": "voice-90",
|
|
298
|
+
"jenny-multilingual": "voice-91",
|
|
299
|
+
"ryan-multilingual": "voice-92",
|
|
300
|
+
"adam-multilingual": "voice-93",
|
|
301
|
+
"liam-multilingual": "voice-94",
|
|
302
|
+
# Turbo voices
|
|
303
|
+
"aria-turbo": "voice-95",
|
|
304
|
+
"andrew-turbo": "voice-96",
|
|
305
|
+
"brian-turbo": "voice-97",
|
|
306
|
+
"emma-turbo": "voice-98",
|
|
307
|
+
"jenny-turbo": "voice-99",
|
|
308
|
+
"ryan-turbo": "voice-100",
|
|
309
|
+
"adam-turbo": "voice-101",
|
|
310
|
+
"liam-turbo": "voice-102",
|
|
311
|
+
# HD voices
|
|
312
|
+
"aria-hd": "voice-103",
|
|
313
|
+
"andrew-hd": "voice-104",
|
|
314
|
+
"brian-hd": "voice-105",
|
|
315
|
+
"emma-hd": "voice-106",
|
|
316
|
+
"jenny-hd": "voice-107",
|
|
317
|
+
"andrew-hd-2": "voice-108",
|
|
318
|
+
"aria-hd-2": "voice-109",
|
|
319
|
+
"adam-hd": "voice-110",
|
|
320
|
+
"ava-hd": "voice-111",
|
|
321
|
+
"davis-hd": "voice-112",
|
|
322
|
+
"brian-hd-2": "voice-113",
|
|
323
|
+
"christopher-hd": "voice-114",
|
|
324
|
+
"coral-hd": "voice-115",
|
|
325
|
+
"emma-hd-2": "voice-116",
|
|
326
|
+
"eric-hd": "voice-117",
|
|
327
|
+
"fable-hd": "voice-118",
|
|
328
|
+
"jenny-hd-2": "voice-119",
|
|
329
|
+
"michelle-hd": "voice-120",
|
|
330
|
+
"roger-hd": "voice-121",
|
|
331
|
+
"sage-hd": "voice-122",
|
|
332
|
+
"vale-hd": "voice-123",
|
|
333
|
+
"verse-hd": "voice-124",
|
|
334
|
+
# Legacy compatibility mappings (lowercase)
|
|
335
|
+
"emma": "voice-116",
|
|
336
|
+
"ava": "voice-111",
|
|
337
|
+
"brian": "voice-113",
|
|
338
|
+
"andrew": "voice-108",
|
|
339
|
+
"aria": "voice-109",
|
|
340
|
+
"christopher": "voice-114",
|
|
341
|
+
"eric": "voice-117",
|
|
342
|
+
"jenny": "voice-119",
|
|
343
|
+
"michelle": "voice-120",
|
|
344
|
+
"roger": "voice-121",
|
|
345
|
+
"libby": "voice-82",
|
|
346
|
+
"ryan": "voice-84",
|
|
347
|
+
"sonia": "voice-85",
|
|
348
|
+
"thomas": "voice-86",
|
|
349
|
+
"natasha": "voice-78",
|
|
350
|
+
"william": "voice-79",
|
|
351
|
+
"clara": "voice-80",
|
|
352
|
+
"liam": "voice-81",
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
# Legacy voice mapping for backward compatibility
|
|
356
|
+
all_voices = voice_mapping
|
|
357
|
+
|
|
358
|
+
def __init__(self, timeout: int = 20, proxies: Optional[dict] = None):
|
|
359
|
+
"""
|
|
360
|
+
Initialize the SpeechMa TTS client.
|
|
361
|
+
|
|
362
|
+
Args:
|
|
363
|
+
timeout (int): Request timeout in seconds
|
|
364
|
+
proxies (dict): Proxy configuration
|
|
365
|
+
"""
|
|
366
|
+
super().__init__()
|
|
367
|
+
self.api_url = "https://speechma.com/com.api/tts-api.php"
|
|
368
|
+
self.session = requests.Session()
|
|
369
|
+
self.session.headers.update(self.headers)
|
|
370
|
+
if proxies:
|
|
371
|
+
self.session.proxies.update(proxies)
|
|
372
|
+
self.timeout = timeout
|
|
373
|
+
# Override defaults for SpeechMa
|
|
374
|
+
self.default_voice = "emma"
|
|
375
|
+
self.default_model = "gpt-4o-mini-tts"
|
|
376
|
+
|
|
377
|
+
def create_speech(
|
|
378
|
+
self,
|
|
379
|
+
input_text: str,
|
|
380
|
+
model: Optional[str] = "gpt-4o-mini-tts",
|
|
381
|
+
voice: Optional[str] = "emma",
|
|
382
|
+
response_format: Optional[str] = "mp3",
|
|
383
|
+
instructions: Optional[str] = None,
|
|
384
|
+
verbose: bool = False,
|
|
385
|
+
) -> str:
|
|
386
|
+
"""
|
|
387
|
+
Create speech from text using OpenAI-compatible interface.
|
|
388
|
+
|
|
389
|
+
Args:
|
|
390
|
+
input_text (str): The text to convert to speech
|
|
391
|
+
voice (str): Voice to use for generation
|
|
392
|
+
model (str): TTS model to use
|
|
393
|
+
response_format (str): Audio format (mp3, opus, aac, flac, wav, pcm)
|
|
394
|
+
instructions (str): Voice instructions (not used by SpeechMa)
|
|
395
|
+
verbose (bool): Whether to print debug information
|
|
396
|
+
|
|
397
|
+
Returns:
|
|
398
|
+
str: Path to the generated audio file
|
|
399
|
+
|
|
400
|
+
Raises:
|
|
401
|
+
ValueError: If input parameters are invalid
|
|
402
|
+
exceptions.FailedToGenerateResponseError: If generation fails
|
|
403
|
+
"""
|
|
404
|
+
return self.tts(
|
|
405
|
+
text=input_text,
|
|
406
|
+
voice=voice or "emma",
|
|
407
|
+
model=model or "gpt-4o-mini-tts",
|
|
408
|
+
response_format=response_format or "mp3",
|
|
409
|
+
instructions=instructions,
|
|
410
|
+
verbose=verbose,
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
def with_streaming_response(self):
|
|
414
|
+
"""
|
|
415
|
+
Return a context manager for streaming responses.
|
|
416
|
+
|
|
417
|
+
Returns:
|
|
418
|
+
SpeechMaStreamingResponse: Context manager for streaming
|
|
419
|
+
"""
|
|
420
|
+
return SpeechMaStreamingResponse(self)
|
|
421
|
+
|
|
422
|
+
def tts(self, text: str, voice: Optional[str] = None, verbose: bool = False, **kwargs) -> str:
|
|
423
|
+
"""
|
|
424
|
+
Convert text to speech using SpeechMa API with OpenAI-compatible parameters.
|
|
425
|
+
|
|
426
|
+
Args:
|
|
427
|
+
text (str): The text to convert to speech (max 10,000 characters)
|
|
428
|
+
**kwargs: Additional parameters (model, voice, response_format, instructions, pitch, rate, verbose)
|
|
429
|
+
"""
|
|
430
|
+
# Extract parameters from kwargs with defaults
|
|
431
|
+
model = kwargs.get("model", self.default_model)
|
|
432
|
+
voice = voice or kwargs.get("voice", "emma")
|
|
433
|
+
response_format = kwargs.get("response_format", "mp3")
|
|
434
|
+
pitch = kwargs.get("pitch", 0)
|
|
435
|
+
rate = kwargs.get("rate", 0)
|
|
436
|
+
verbose = verbose if verbose is not None else kwargs.get("verbose", True)
|
|
437
|
+
# Validate input parameters
|
|
438
|
+
if not text or not isinstance(text, str):
|
|
439
|
+
raise ValueError("Input text must be a non-empty string")
|
|
440
|
+
if len(text) > 10000:
|
|
441
|
+
raise ValueError("Input text exceeds maximum allowed length of 10,000 characters")
|
|
442
|
+
|
|
443
|
+
# Validate model, voice, and format using base class methods
|
|
444
|
+
model = self.validate_model(model)
|
|
445
|
+
voice = self.validate_voice(voice)
|
|
446
|
+
response_format = self.validate_format(response_format)
|
|
447
|
+
|
|
448
|
+
# Map voice to SpeechMa API format
|
|
449
|
+
speechma_voice = self.voice_mapping.get(voice, voice)
|
|
450
|
+
if speechma_voice not in self.all_voices.values():
|
|
451
|
+
# Fallback to legacy voice mapping
|
|
452
|
+
speechma_voice = self.all_voices.get(
|
|
453
|
+
voice.title(), self.all_voices.get("Emma", "voice-116")
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
# Create temporary file with appropriate extension
|
|
457
|
+
file_extension = f".{response_format}" if response_format != "pcm" else ".wav"
|
|
458
|
+
filename = pathlib.Path(
|
|
459
|
+
tempfile.NamedTemporaryFile(suffix=file_extension, dir=self.temp_dir, delete=False).name
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
# Split text into sentences using the utils module for better processing
|
|
463
|
+
sentences = utils.split_sentences(text)
|
|
464
|
+
if verbose:
|
|
465
|
+
ic.configureOutput(prefix="DEBUG| ")
|
|
466
|
+
ic(f"Processing {len(sentences)} sentences")
|
|
467
|
+
ic.configureOutput(prefix="DEBUG| ")
|
|
468
|
+
ic(f"Model: {model}")
|
|
469
|
+
ic.configureOutput(prefix="DEBUG| ")
|
|
470
|
+
ic(f"Voice: {voice} -> {speechma_voice}")
|
|
471
|
+
ic.configureOutput(prefix="DEBUG| ")
|
|
472
|
+
ic(f"Format: {response_format}")
|
|
473
|
+
|
|
474
|
+
def generate_audio_for_chunk(part_text: str, part_number: int):
|
|
475
|
+
"""
|
|
476
|
+
Generate audio for a single chunk of text.
|
|
477
|
+
|
|
478
|
+
Args:
|
|
479
|
+
part_text (str): The text chunk to convert
|
|
480
|
+
part_number (int): The chunk number for ordering
|
|
481
|
+
|
|
482
|
+
Returns:
|
|
483
|
+
tuple: (part_number, audio_data)
|
|
484
|
+
|
|
485
|
+
Raises:
|
|
486
|
+
requests.RequestException: If there's an API error
|
|
487
|
+
"""
|
|
488
|
+
max_retries = 3
|
|
489
|
+
retry_count = 0
|
|
490
|
+
|
|
491
|
+
while retry_count < max_retries:
|
|
492
|
+
try:
|
|
493
|
+
payload = {
|
|
494
|
+
"text": part_text,
|
|
495
|
+
"voice": speechma_voice,
|
|
496
|
+
"pitch": pitch,
|
|
497
|
+
"rate": rate,
|
|
498
|
+
"volume": 100,
|
|
499
|
+
# Add model parameter for future SpeechMa API compatibility
|
|
500
|
+
"tts_model": model,
|
|
501
|
+
}
|
|
502
|
+
response = self.session.post(
|
|
503
|
+
url=self.api_url, headers=self.headers, json=payload, timeout=self.timeout
|
|
504
|
+
)
|
|
505
|
+
response.raise_for_status()
|
|
506
|
+
|
|
507
|
+
# Check if response is audio data
|
|
508
|
+
content_type = response.headers.get("content-type", "").lower()
|
|
509
|
+
if (
|
|
510
|
+
"audio" in content_type
|
|
511
|
+
or response.content.startswith(b"\xff\xfb")
|
|
512
|
+
or response.content.startswith(b"ID3")
|
|
513
|
+
or b"LAME" in response.content[:100]
|
|
514
|
+
):
|
|
515
|
+
if verbose:
|
|
516
|
+
ic.configureOutput(prefix="DEBUG| ")
|
|
517
|
+
ic(f"Chunk {part_number} processed successfully")
|
|
518
|
+
return part_number, response.content
|
|
519
|
+
else:
|
|
520
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
521
|
+
f"Unexpected response format. Content-Type: {content_type}"
|
|
522
|
+
)
|
|
523
|
+
|
|
524
|
+
except requests.exceptions.RequestException as e:
|
|
525
|
+
retry_count += 1
|
|
526
|
+
if retry_count >= max_retries:
|
|
527
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
528
|
+
f"Failed to generate audio for chunk {part_number} after {max_retries} retries: {e}"
|
|
529
|
+
)
|
|
530
|
+
if verbose:
|
|
531
|
+
ic.configureOutput(prefix="DEBUG| ")
|
|
532
|
+
ic(f"Retrying chunk {part_number} (attempt {retry_count + 1})")
|
|
533
|
+
time.sleep(1) # Brief delay before retry
|
|
534
|
+
|
|
535
|
+
# Process chunks concurrently for better performance
|
|
536
|
+
audio_chunks = []
|
|
537
|
+
if len(sentences) > 1:
|
|
538
|
+
with ThreadPoolExecutor(max_workers=3) as executor:
|
|
539
|
+
future_to_chunk = {
|
|
540
|
+
executor.submit(generate_audio_for_chunk, sentence, i): i
|
|
541
|
+
for i, sentence in enumerate(sentences)
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
for future in as_completed(future_to_chunk):
|
|
545
|
+
try:
|
|
546
|
+
chunk_number, audio_data = future.result()
|
|
547
|
+
audio_chunks.append((chunk_number, audio_data))
|
|
548
|
+
except Exception as e:
|
|
549
|
+
if verbose:
|
|
550
|
+
ic.configureOutput(prefix="DEBUG| ")
|
|
551
|
+
ic(f"Error processing chunk: {e}")
|
|
552
|
+
raise
|
|
553
|
+
else:
|
|
554
|
+
# Single sentence, process directly
|
|
555
|
+
chunk_number, audio_data = generate_audio_for_chunk(sentences[0], 0)
|
|
556
|
+
audio_chunks.append((chunk_number, audio_data))
|
|
557
|
+
|
|
558
|
+
# Sort chunks by their original order and combine
|
|
559
|
+
audio_chunks.sort(key=lambda x: x[0])
|
|
560
|
+
combined_audio = b"".join([chunk[1] for chunk in audio_chunks])
|
|
561
|
+
|
|
562
|
+
# Save combined audio to file
|
|
563
|
+
try:
|
|
564
|
+
with open(filename, "wb") as f:
|
|
565
|
+
f.write(combined_audio)
|
|
566
|
+
if verbose:
|
|
567
|
+
ic.configureOutput(prefix="DEBUG| ")
|
|
568
|
+
ic(f"Audio saved to: {filename}")
|
|
569
|
+
return filename.as_posix()
|
|
570
|
+
except IOError as e:
|
|
571
|
+
raise exceptions.FailedToGenerateResponseError(f"Failed to save audio file: {e}")
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
class SpeechMaStreamingResponse:
|
|
575
|
+
"""Context manager for streaming SpeechMa TTS responses."""
|
|
576
|
+
|
|
577
|
+
def __init__(self, client: SpeechMaTTS):
|
|
578
|
+
self.client = client
|
|
579
|
+
|
|
580
|
+
def __enter__(self):
|
|
581
|
+
return self
|
|
582
|
+
|
|
583
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
584
|
+
pass
|
|
585
|
+
|
|
586
|
+
def create_speech(
|
|
587
|
+
self,
|
|
588
|
+
input_text: str,
|
|
589
|
+
voice: Optional[str] = "emma",
|
|
590
|
+
model: Optional[str] = "gpt-4o-mini-tts",
|
|
591
|
+
response_format: Optional[str] = "mp3",
|
|
592
|
+
instructions: Optional[str] = None,
|
|
593
|
+
verbose: bool = False,
|
|
594
|
+
):
|
|
595
|
+
"""
|
|
596
|
+
Create speech with streaming response simulation.
|
|
597
|
+
|
|
598
|
+
Note: SpeechMa doesn't support true streaming, so this returns
|
|
599
|
+
the complete audio data wrapped in a BytesIO object.
|
|
600
|
+
|
|
601
|
+
Args:
|
|
602
|
+
input_text (str): Text to convert to speech
|
|
603
|
+
voice (str): Voice to use
|
|
604
|
+
model (str): TTS model
|
|
605
|
+
response_format (str): Audio format
|
|
606
|
+
instructions (str): Voice instructions
|
|
607
|
+
verbose (bool): Whether to print debug information
|
|
608
|
+
|
|
609
|
+
Returns:
|
|
610
|
+
BytesIO: Audio data stream
|
|
611
|
+
"""
|
|
612
|
+
audio_file = self.client.create_speech(
|
|
613
|
+
input_text=input_text,
|
|
614
|
+
voice=voice,
|
|
615
|
+
model=model,
|
|
616
|
+
response_format=response_format,
|
|
617
|
+
instructions=instructions,
|
|
618
|
+
verbose=verbose,
|
|
619
|
+
)
|
|
620
|
+
with open(audio_file, "rb") as f:
|
|
621
|
+
return BytesIO(f.read())
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
# Example usage and testing
|
|
625
|
+
if __name__ == "__main__":
|
|
626
|
+
# Initialize the SpeechMa TTS client
|
|
627
|
+
speechma = SpeechMaTTS()
|
|
628
|
+
|
|
629
|
+
# Example 1: Basic usage with legacy method
|
|
630
|
+
print("=== Example 1: Basic TTS ===")
|
|
631
|
+
text = "Hello, this is a test of the SpeechMa text-to-speech API."
|
|
632
|
+
try:
|
|
633
|
+
audio_file = speechma.tts(text, voice="emma", verbose=True)
|
|
634
|
+
print(f"Audio saved to: {audio_file}")
|
|
635
|
+
except Exception as e:
|
|
636
|
+
print(f"Error: {e}")
|
|
637
|
+
|
|
638
|
+
# Example 2: OpenAI-compatible interface
|
|
639
|
+
print("\n=== Example 2: OpenAI-compatible interface ===")
|
|
640
|
+
try:
|
|
641
|
+
audio_file_path = speechma.create_speech(
|
|
642
|
+
input_text="This demonstrates the OpenAI-compatible interface.",
|
|
643
|
+
voice="brian",
|
|
644
|
+
model="tts-1-hd",
|
|
645
|
+
response_format="mp3",
|
|
646
|
+
)
|
|
647
|
+
print(f"Generated audio file at: {audio_file_path}")
|
|
648
|
+
|
|
649
|
+
# Read the file to get bytes for the example
|
|
650
|
+
with open(audio_file_path, "rb") as f:
|
|
651
|
+
audio_data = f.read()
|
|
652
|
+
print(f"Generated {len(audio_data)} bytes of audio data")
|
|
653
|
+
|
|
654
|
+
# Save to file
|
|
655
|
+
with open("openai_compatible_test.mp3", "wb") as f:
|
|
656
|
+
f.write(audio_data)
|
|
657
|
+
print("Audio saved to: openai_compatible_test.mp3")
|
|
658
|
+
except Exception as e:
|
|
659
|
+
print(f"Error: {e}")
|
|
660
|
+
|
|
661
|
+
# Example 3: Streaming response context manager
|
|
662
|
+
print("\n=== Example 3: Streaming response ===")
|
|
663
|
+
try:
|
|
664
|
+
with speechma.with_streaming_response() as streaming:
|
|
665
|
+
audio_stream = streaming.create_speech(
|
|
666
|
+
input_text="This demonstrates streaming response handling.",
|
|
667
|
+
voice="aria",
|
|
668
|
+
model="gpt-4o-mini-tts",
|
|
669
|
+
)
|
|
670
|
+
audio_data = audio_stream.read()
|
|
671
|
+
print(f"Streamed {len(audio_data)} bytes of audio data")
|
|
672
|
+
except Exception as e:
|
|
673
|
+
print(f"Error: {e}")
|
|
674
|
+
|
|
675
|
+
# Example 4: Voice and model validation
|
|
676
|
+
print("\n=== Example 4: Parameter validation ===")
|
|
677
|
+
try:
|
|
678
|
+
# Test supported voices
|
|
679
|
+
print("Supported voices:", speechma.SUPPORTED_VOICES[:5], "...")
|
|
680
|
+
print("Supported models:", speechma.SUPPORTED_MODELS)
|
|
681
|
+
|
|
682
|
+
# Test with different parameters
|
|
683
|
+
audio_file = speechma.tts(
|
|
684
|
+
text="Testing different voice parameters.",
|
|
685
|
+
voice="christopher",
|
|
686
|
+
model="tts-1",
|
|
687
|
+
pitch=2,
|
|
688
|
+
rate=-1,
|
|
689
|
+
verbose=True,
|
|
690
|
+
)
|
|
691
|
+
print(f"Audio with custom parameters saved to: {audio_file}")
|
|
692
|
+
except Exception as e:
|
|
693
|
+
print(f"Error: {e}")
|