openspeechapi 0.2.4__tar.gz → 0.2.6__tar.gz
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.
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/PKG-INFO +1 -1
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/__init__.py +1 -1
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/logging_config.py +16 -2
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/iflytek.py +29 -8
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/iflytek.py +59 -22
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/providers.example.yaml +15 -2
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/pyproject.toml +1 -1
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_logging.py +32 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.dockerignore +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.env.example +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.github/workflows/ci.yml +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.gitignore +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/audio/en.aiff +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/audio/en_16k.wav +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/audio/en_16k_pad6.wav +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/audio/en_long.aiff +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/audio/en_long_16k.wav +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/audio/en_mid.aiff +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/audio/en_mid_16k.wav +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/audio/zh.aiff +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/audio/zh_16k.wav +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/openspeech-8600.log +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/openspeech-serve.log +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/webui-server.log +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/webui-server.pid +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/wlk12101.log +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/wlk12101.pid +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/wlk12102.log +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/.tmp/wlk12102.pid +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/AGENTS.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/CLAUDE.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/Dockerfile +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/README.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/aibox-script/aibox-1.0.0-SNAPSHOT-stdout.log +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/aibox-script/aibox.2026-04-02.log +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/aibox-script/com.user.restart-jar.plist +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/aibox-script/restart-jar.sh +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/aibox-script.tar.gz +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docker-compose.yml +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/architecture/local-engine-manager.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/architecture/logging-spec.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/architecture/stt-engineering-optimization-guide.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/architecture/stt-streaming-spec.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/architecture/webui-phase-a.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/engines/fish-speech-docker.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/engines/fish-speech-native.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/engines/stt-native-models.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/superpowers/plans/2026-04-01-phase1-implementation.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/superpowers/plans/2026-04-11-macos-native-tts-stt.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/superpowers/specs/2026-04-01-openspeech-api-design.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/superpowers/specs/2026-04-03-hot-lazy-loading.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/superpowers/specs/2026-04-03-phase2-protocol-layer.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/superpowers/specs/2026-04-03-phase3-production.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/superpowers/specs/2026-04-11-macos-native-tts-stt-design.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/superpowers/specs/2026-04-12-cloud-providers-webui-design.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/superpowers/specs/2026-04-15-streaming-tts-stt-fixes-display-names.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/superpowers/specs/2026-04-16-provider-management-engines-rename.md +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/examples/client_stt.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/examples/client_tts.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/examples/stt_simple.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/examples/tts_simple.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/__main__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/cli.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/client/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/client/client.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/config.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/core/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/core/base.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/core/enums.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/core/models.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/core/registry.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/core/settings.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/demo.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/dispatch/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/dispatch/context.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/dispatch/dispatcher.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/dispatch/executors/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/dispatch/executors/base.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/dispatch/executors/in_process.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/dispatch/executors/remote.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/dispatch/executors/subprocess_exec.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/dispatch/fanout.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/dispatch/filters.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/dispatch/lifecycle.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/dispatch/watcher.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/engine_catalog.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/engine_registry.yaml +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/exceptions.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/factory.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/aim_resolver.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/backends/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/backends/docker_backend.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/backends/native_backend.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/base.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/engines/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/engines/faster_whisper.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/engines/fish_speech.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/engines/sherpa_onnx.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/engines/whisper.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/engines/whisperlivekit.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/manager.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/models.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/progress.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/registry.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/task_store.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/tasks.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/observe/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/observe/base.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/observe/debug.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/observe/latency.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/observe/metrics.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/observe/tracing.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/observe/usage.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/_template.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/alibaba.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/assemblyai.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/azure_speech.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/baidu.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/deepgram.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/elevenlabs.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/faster_whisper.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/google_cloud.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/macos_speech.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/openai.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/sherpa_onnx.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/tencent.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/volcengine.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/whisper.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/whisperlivekit.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/stt/windows_speech.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/alibaba.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/azure_speech.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/baidu.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/coqui.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/cosyvoice.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/deepgram.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/elevenlabs.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/fish_speech.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/google_cloud.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/macos_say.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/minimax.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/openai.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/piper.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/tencent.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/volcengine.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/providers/tts/windows_sapi.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/app.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/auth.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/middleware.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/routes/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/routes/management.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/routes/stt.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/routes/tts.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/routes/webui.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/webui/app.js +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/webui/index.html +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/webui/styles.css +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/ws/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/ws/stt_stream.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/server/ws/tts_stream.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/telemetry/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/telemetry/perf.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/utils/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/utils/audio_converter.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/utils/audio_playback.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/vendor_registry.yaml +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/output/output.wav +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/output.wav +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/scripts/engines/cloud/install.sh +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/scripts/engines/faster-whisper/native/install.sh +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/scripts/engines/fish-speech/native/install.sh +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/scripts/engines/macos-stt/install.sh +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/scripts/engines/macos-stt/macos_stt.swift +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/scripts/engines/macos-stt/request_auth.swift +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/scripts/engines/sherpa-onnx/native/install.sh +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/scripts/engines/sherpa-onnx/native/run_streaming_server.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/scripts/engines/whisper/native/install.sh +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/scripts/engines/whisperlivekit/native/install.sh +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/conftest.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/e2e/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/e2e/conftest.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/e2e/test_fanout_e2e.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/e2e/test_faster_whisper_e2e.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/e2e/test_openai_e2e.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/e2e/test_webui_e2e.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/fixtures/hello.wav +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/integration/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/integration/test_fanout_integration.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/integration/test_in_process_integration.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/integration/test_server_client.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_aim_resolver.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_audio_converter.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_audio_playback.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_base.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_cli.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_cli_engine.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_client.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_config.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_context.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_debug_observer.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_dispatcher.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_docker_backend_progress.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_engine_registry.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_enums.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_executor_base.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_fanout.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_filters.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_hot_reload.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_in_process.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_latency_observer.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_lifecycle.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_local_engine_task_store.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_local_engines_manager.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_metrics_observer.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_models.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_native_backend.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_observer_base.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_plugin_mechanism.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_providers/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_providers/test_cloud_providers.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_providers/test_elevenlabs_stt.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_providers/test_macos_say.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_providers/test_macos_speech.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_providers/test_openai_base_url.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_providers/test_openai_stt.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_providers/test_openai_tts.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_providers/test_sherpa_onnx_stt.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_providers/test_stt_stubs.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_providers/test_tts_stubs.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_providers/test_whisperlivekit_stt.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_registry.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_remote.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_server/__init__.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_server/test_auth.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_server/test_config_api.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_server/test_routes.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_server/test_websocket.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_subprocess.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_usage_observer.py +0 -0
- {openspeechapi-0.2.4 → openspeechapi-0.2.6}/tests/unit/test_watcher.py +0 -0
|
@@ -185,10 +185,24 @@ def bind_context(
|
|
|
185
185
|
if v is not None:
|
|
186
186
|
bindings[k] = v
|
|
187
187
|
|
|
188
|
+
# NOTE: we drive logger.contextualize manually instead of using its
|
|
189
|
+
# ``with`` form so we can swallow the cleanup-time ValueError that
|
|
190
|
+
# loguru raises when bind_context wraps a ``yield`` in an async
|
|
191
|
+
# generator and that generator is closed from a different asyncio
|
|
192
|
+
# Context (e.g. the consumer task gets cancelled). The token loguru
|
|
193
|
+
# tries to reset was set in the original Context and Python forbids
|
|
194
|
+
# cross-context reset. The bindings are scoped to the closing
|
|
195
|
+
# Context anyway, so dropping the reset is harmless — Python GCs the
|
|
196
|
+
# vanishing Context's vars regardless.
|
|
197
|
+
contextualizer = logger.contextualize(**bindings)
|
|
198
|
+
contextualizer.__enter__()
|
|
188
199
|
try:
|
|
189
|
-
|
|
190
|
-
yield bindings
|
|
200
|
+
yield bindings
|
|
191
201
|
finally:
|
|
202
|
+
try:
|
|
203
|
+
contextualizer.__exit__(None, None, None)
|
|
204
|
+
except ValueError:
|
|
205
|
+
pass
|
|
192
206
|
for var, token in reversed(resets):
|
|
193
207
|
try:
|
|
194
208
|
var.reset(token)
|
|
@@ -52,6 +52,26 @@ class IflytekSTTSettings(BaseSettings):
|
|
|
52
52
|
# via ``speech_providers.yaml`` so different sites can pick their
|
|
53
53
|
# own latency-vs-tolerance trade-off.
|
|
54
54
|
vad_eos: int = 2000
|
|
55
|
+
# ``ltc`` — sentence-level timestamp granularity sent in the
|
|
56
|
+
# business block of the IAT request (1 = sentence segments only;
|
|
57
|
+
# 2 = + word boundaries; 3 = + character boundaries). Java's
|
|
58
|
+
# ``AsrConfig.ltc`` defaults to 3; we mirror that so downstream
|
|
59
|
+
# consumers expecting per-character timing offsets keep working.
|
|
60
|
+
# Lower values shave a few bytes per response and slightly reduce
|
|
61
|
+
# post-processing work for callers that don't use the timestamps.
|
|
62
|
+
ltc: int = 3
|
|
63
|
+
# ``ws_host`` / ``ws_path`` — iFlytek IAT WebSocket endpoint. The
|
|
64
|
+
# default ``iat-api.xfyun.cn`` is the global endpoint; multi-region
|
|
65
|
+
# deployments (e.g. directed-domain endpoints such as
|
|
66
|
+
# ``ws-api-dx.xfyun.cn``) override these in yaml or via env var
|
|
67
|
+
# so the WS URL never requires a code change.
|
|
68
|
+
ws_host: str = "iat-api.xfyun.cn"
|
|
69
|
+
ws_path: str = "/v2/iat"
|
|
70
|
+
# ``timeout_secs`` — connect / read timeout for the underlying
|
|
71
|
+
# httpx AsyncClient. Java's AsrConfig defaults to 15s; we mirror
|
|
72
|
+
# that. Lower if the network has aggressive proxies, higher only
|
|
73
|
+
# if the iFlytek endpoint is consistently slow to handshake.
|
|
74
|
+
timeout_secs: int = 15
|
|
55
75
|
|
|
56
76
|
|
|
57
77
|
# iFlytek expects the full locale tag; common ISO short codes need to
|
|
@@ -92,9 +112,6 @@ class IflytekSTT(STTProvider):
|
|
|
92
112
|
"language": ["zh_cn", "en_us", "ja_jp", "ko_kr", "ru-ru"],
|
|
93
113
|
}
|
|
94
114
|
|
|
95
|
-
_WS_HOST = "iat-api.xfyun.cn"
|
|
96
|
-
_WS_PATH = "/v2/iat"
|
|
97
|
-
|
|
98
115
|
def __init__(self, settings: IflytekSTTSettings | None = None) -> None:
|
|
99
116
|
self.settings = settings or IflytekSTTSettings()
|
|
100
117
|
self._client: httpx.AsyncClient | None = None
|
|
@@ -106,7 +123,7 @@ class IflytekSTT(STTProvider):
|
|
|
106
123
|
|
|
107
124
|
async def start(self) -> None:
|
|
108
125
|
if self._client is None:
|
|
109
|
-
self._client = httpx.AsyncClient(timeout=
|
|
126
|
+
self._client = httpx.AsyncClient(timeout=float(self.settings.timeout_secs))
|
|
110
127
|
self._owns_client = True
|
|
111
128
|
# Surface the effective language (after alias mapping) and
|
|
112
129
|
# vad_eos at startup so deployments can verify the iFlytek model
|
|
@@ -142,10 +159,12 @@ class IflytekSTT(STTProvider):
|
|
|
142
159
|
now = datetime.now(tz=timezone.utc)
|
|
143
160
|
date = formatdate(timeval=now.timestamp(), localtime=False, usegmt=True)
|
|
144
161
|
|
|
162
|
+
host = self.settings.ws_host
|
|
163
|
+
path = self.settings.ws_path
|
|
145
164
|
signature_origin = (
|
|
146
|
-
f"host: {
|
|
165
|
+
f"host: {host}\n"
|
|
147
166
|
f"date: {date}\n"
|
|
148
|
-
f"GET {
|
|
167
|
+
f"GET {path} HTTP/1.1"
|
|
149
168
|
)
|
|
150
169
|
signature_sha = hmac.new(
|
|
151
170
|
self.settings.api_secret.encode("utf-8"),
|
|
@@ -165,9 +184,9 @@ class IflytekSTT(STTProvider):
|
|
|
165
184
|
).decode("utf-8")
|
|
166
185
|
|
|
167
186
|
params = urllib.parse.urlencode(
|
|
168
|
-
{"authorization": authorization, "date": date, "host":
|
|
187
|
+
{"authorization": authorization, "date": date, "host": host}
|
|
169
188
|
)
|
|
170
|
-
return f"wss://{
|
|
189
|
+
return f"wss://{host}{path}?{params}"
|
|
171
190
|
|
|
172
191
|
async def transcribe(
|
|
173
192
|
self, audio: AudioData, opts: STTOptions | None = None
|
|
@@ -228,6 +247,7 @@ class IflytekSTT(STTProvider):
|
|
|
228
247
|
"language": canon,
|
|
229
248
|
"domain": "iat",
|
|
230
249
|
"vad_eos": eos,
|
|
250
|
+
"ltc": self.settings.ltc,
|
|
231
251
|
}
|
|
232
252
|
if canon == "zh_cn":
|
|
233
253
|
business["accent"] = "mandarin"
|
|
@@ -364,6 +384,7 @@ class IflytekSTT(STTProvider):
|
|
|
364
384
|
"domain": "iat",
|
|
365
385
|
"dwa": "wpgs",
|
|
366
386
|
"vad_eos": eos,
|
|
387
|
+
"ltc": self.settings.ltc,
|
|
367
388
|
}
|
|
368
389
|
if canon == "zh_cn":
|
|
369
390
|
business["accent"] = "mandarin"
|
|
@@ -29,16 +29,22 @@ class IflytekTTSSettings(BaseSettings):
|
|
|
29
29
|
voice: str = "xiaoyan"
|
|
30
30
|
speed: int = 50
|
|
31
31
|
# Audio output encoding requested from iFlytek.
|
|
32
|
-
# - "lame":
|
|
33
|
-
# - "raw":
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
32
|
+
# - "lame": MP3 frames (default; smaller, but caller must decode)
|
|
33
|
+
# - "raw": 16-bit PCM @ 16 kHz mono, big-endian L16 (drop-in
|
|
34
|
+
# playable as raw PCM; required by callers that wrap the
|
|
35
|
+
# bytes in a fixed-format wire envelope and assume PCM,
|
|
36
|
+
# e.g. wallex's RESP_VOICE which advertises
|
|
37
|
+
# encoding=raw/bitDepth=16/sampleRate=16000 to the
|
|
38
|
+
# panel — feeding MP3 bytes through that envelope plays
|
|
39
|
+
# back as pure noise on the speaker).
|
|
40
|
+
# - "speex"/"speex-wb-7": Speex narrowband / wideband (low-bitrate,
|
|
41
|
+
# used by some embedded Wallex panels with constrained
|
|
42
|
+
# uplink). Requires ``speex_size`` to declare the frame
|
|
43
|
+
# size iFlytek should produce. Caller must run a Speex
|
|
44
|
+
# decoder; not auto-handled by browsers.
|
|
40
45
|
# Default stays "lame" for backward-compat; deployments that need
|
|
41
|
-
# PCM (wallex / direct hardware playback)
|
|
46
|
+
# PCM (wallex / direct hardware playback) or Speex (embedded panels)
|
|
47
|
+
# override via yaml.
|
|
42
48
|
aue: str = "lame"
|
|
43
49
|
# Output sample rate for raw PCM mode (only meaningful when
|
|
44
50
|
# aue="raw"). 16000 matches what the panel and the iFlytek
|
|
@@ -50,6 +56,22 @@ class IflytekTTSSettings(BaseSettings):
|
|
|
50
56
|
volume: int = 50
|
|
51
57
|
# Pitch (0-100). Same rationale as volume.
|
|
52
58
|
pitch: int = 50
|
|
59
|
+
# Speex frame size (only meaningful when aue startswith "speex").
|
|
60
|
+
# iFlytek expects an integer that selects a Speex bitrate / frame
|
|
61
|
+
# mode; ``0`` is "auto-pick by aue tag". Leave 0 unless the client
|
|
62
|
+
# decoder requires a specific frame size. Mirrors Java
|
|
63
|
+
# ``AsrConfig.speex-size`` / ``TtsConfig`` parameter.
|
|
64
|
+
speex_size: int = 0
|
|
65
|
+
# ``ws_host`` / ``ws_path`` — iFlytek TTS WebSocket endpoint.
|
|
66
|
+
# Override in yaml (or via ``OPENSPEECH_IFLYTEK_TTS_HOST`` env var)
|
|
67
|
+
# for region-specific endpoints. Default is the global endpoint.
|
|
68
|
+
ws_host: str = "tts-api.xfyun.cn"
|
|
69
|
+
ws_path: str = "/v2/tts"
|
|
70
|
+
# ``timeout_secs`` — connect / read timeout for the underlying
|
|
71
|
+
# httpx AsyncClient. Java's TtsConfig defaults to 8s; we mirror
|
|
72
|
+
# that for parity. Increase only when the iFlytek endpoint is
|
|
73
|
+
# consistently slow to handshake.
|
|
74
|
+
timeout_secs: int = 8
|
|
53
75
|
|
|
54
76
|
class IflytekTTS(TTSProvider):
|
|
55
77
|
name = "iflytek-tts"
|
|
@@ -66,12 +88,9 @@ class IflytekTTS(TTSProvider):
|
|
|
66
88
|
# English assistant-style voices used by wallex deployments.
|
|
67
89
|
"x4_enuk_ashleigh_assist",
|
|
68
90
|
],
|
|
69
|
-
"aue": ["lame", "raw"],
|
|
91
|
+
"aue": ["lame", "raw", "speex", "speex-wb-7"],
|
|
70
92
|
}
|
|
71
93
|
|
|
72
|
-
_WS_HOST = "tts-api.xfyun.cn"
|
|
73
|
-
_WS_PATH = "/v2/tts"
|
|
74
|
-
|
|
75
94
|
def __init__(self, settings: IflytekTTSSettings | None = None) -> None:
|
|
76
95
|
self.settings = settings or IflytekTTSSettings()
|
|
77
96
|
self._client: httpx.AsyncClient | None = None
|
|
@@ -83,7 +102,7 @@ class IflytekTTS(TTSProvider):
|
|
|
83
102
|
|
|
84
103
|
async def start(self) -> None:
|
|
85
104
|
if self._client is None:
|
|
86
|
-
self._client = httpx.AsyncClient(timeout=
|
|
105
|
+
self._client = httpx.AsyncClient(timeout=float(self.settings.timeout_secs))
|
|
87
106
|
self._owns_client = True
|
|
88
107
|
|
|
89
108
|
async def stop(self) -> None:
|
|
@@ -99,10 +118,12 @@ class IflytekTTS(TTSProvider):
|
|
|
99
118
|
now = datetime.now(tz=timezone.utc)
|
|
100
119
|
date = formatdate(timeval=now.timestamp(), localtime=False, usegmt=True)
|
|
101
120
|
|
|
121
|
+
host = self.settings.ws_host
|
|
122
|
+
path = self.settings.ws_path
|
|
102
123
|
signature_origin = (
|
|
103
|
-
f"host: {
|
|
124
|
+
f"host: {host}\n"
|
|
104
125
|
f"date: {date}\n"
|
|
105
|
-
f"GET {
|
|
126
|
+
f"GET {path} HTTP/1.1"
|
|
106
127
|
)
|
|
107
128
|
signature_sha = hmac.new(
|
|
108
129
|
self.settings.api_secret.encode("utf-8"),
|
|
@@ -122,9 +143,9 @@ class IflytekTTS(TTSProvider):
|
|
|
122
143
|
).decode("utf-8")
|
|
123
144
|
|
|
124
145
|
params = urllib.parse.urlencode(
|
|
125
|
-
{"authorization": authorization, "date": date, "host":
|
|
146
|
+
{"authorization": authorization, "date": date, "host": host}
|
|
126
147
|
)
|
|
127
|
-
return f"wss://{
|
|
148
|
+
return f"wss://{host}{path}?{params}"
|
|
128
149
|
|
|
129
150
|
async def synthesize(
|
|
130
151
|
self, text: str, opts: TTSOptions | None = None
|
|
@@ -138,8 +159,17 @@ class IflytekTTS(TTSProvider):
|
|
|
138
159
|
# callers downstream may set wire-protocol encoding metadata from
|
|
139
160
|
# this field, and a wrong tag on the bytes plays back as noise on
|
|
140
161
|
# raw-PCM consumers.
|
|
141
|
-
|
|
142
|
-
|
|
162
|
+
aue = self.settings.aue
|
|
163
|
+
if aue == "raw":
|
|
164
|
+
fmt = "pcm_s16le"
|
|
165
|
+
sr = self.settings.auf_rate
|
|
166
|
+
elif aue.startswith("speex"):
|
|
167
|
+
# Speex narrowband is 8 kHz, wideband ("speex-wb-*") is 16 kHz.
|
|
168
|
+
fmt = "speex"
|
|
169
|
+
sr = 16000 if "wb" in aue else 8000
|
|
170
|
+
else:
|
|
171
|
+
fmt = "mp3"
|
|
172
|
+
sr = 16000
|
|
143
173
|
logger.info(
|
|
144
174
|
"iFlytek TTS: {} chunks, {} bytes total, format={}, sample_rate={}",
|
|
145
175
|
len(parts), len(audio_bytes), fmt, sr,
|
|
@@ -191,7 +221,8 @@ class IflytekTTS(TTSProvider):
|
|
|
191
221
|
"pitch": self.settings.pitch,
|
|
192
222
|
"tte": "UTF8",
|
|
193
223
|
}
|
|
194
|
-
|
|
224
|
+
aue = self.settings.aue
|
|
225
|
+
if aue == "lame":
|
|
195
226
|
# ``sfl=1`` (stream-frame-length) is an MP3-only knob that
|
|
196
227
|
# tells iFlytek to emit per-frame audio rather than waiting
|
|
197
228
|
# for the whole file. It has no meaning for raw PCM (raw is
|
|
@@ -199,11 +230,17 @@ class IflytekTTS(TTSProvider):
|
|
|
199
230
|
# combo with a code 10005 "invalid parameter" — so we only
|
|
200
231
|
# send it on the lame path.
|
|
201
232
|
business["sfl"] = 1
|
|
202
|
-
|
|
233
|
+
elif aue == "raw":
|
|
203
234
|
# Raw / L16 mode requires ``auf`` to declare the PCM
|
|
204
235
|
# sample-rate iFlytek should produce. Java wallex sends
|
|
205
236
|
# ``audio/L16;rate=16000`` here; we mirror that exactly.
|
|
206
237
|
business["auf"] = f"audio/L16;rate={self.settings.auf_rate}"
|
|
238
|
+
elif aue.startswith("speex"):
|
|
239
|
+
# Speex narrowband / wideband. ``speex_size`` is the iFlytek
|
|
240
|
+
# frame-size selector (0 = engine default; non-zero values
|
|
241
|
+
# match the Java ``TtsConfig.speex-size`` parameter).
|
|
242
|
+
if self.settings.speex_size:
|
|
243
|
+
business["speex_size"] = self.settings.speex_size
|
|
207
244
|
return {
|
|
208
245
|
"common": {"app_id": self.settings.app_id},
|
|
209
246
|
"business": business,
|
|
@@ -123,7 +123,12 @@ engines:
|
|
|
123
123
|
# exec_mode: remote
|
|
124
124
|
# preload: true
|
|
125
125
|
# settings:
|
|
126
|
-
# language: zh_cn
|
|
126
|
+
# language: zh_cn # zh_cn / en_us / ja_jp / ko_kr / ru-ru
|
|
127
|
+
# vad_eos: 2000 # ms of trailing silence before final
|
|
128
|
+
# ltc: 3 # 1 sentence / 2 +word / 3 +char timestamps
|
|
129
|
+
# ws_host: iat-api.xfyun.cn # override for region-specific endpoints
|
|
130
|
+
# ws_path: /v2/iat
|
|
131
|
+
# timeout_secs: 15
|
|
127
132
|
|
|
128
133
|
# # pip install 'openspeechapi[faster-whisper-stt]'
|
|
129
134
|
# faster_whisper_stt:
|
|
@@ -190,7 +195,15 @@ engines:
|
|
|
190
195
|
# exec_mode: remote
|
|
191
196
|
# settings:
|
|
192
197
|
# voice: xiaoyan
|
|
193
|
-
# speed: 50
|
|
198
|
+
# speed: 50 # 0-100
|
|
199
|
+
# volume: 50 # 0-100
|
|
200
|
+
# pitch: 50 # 0-100
|
|
201
|
+
# aue: lame # lame / raw / speex / speex-wb-7
|
|
202
|
+
# auf_rate: 16000 # only used when aue=raw (8000 / 16000 / 24000)
|
|
203
|
+
# speex_size: 0 # only used when aue startswith speex (0 = auto)
|
|
204
|
+
# ws_host: tts-api.xfyun.cn # override for region-specific endpoints
|
|
205
|
+
# ws_path: /v2/tts
|
|
206
|
+
# timeout_secs: 8
|
|
194
207
|
|
|
195
208
|
# # pip install 'openspeechapi[piper-tts]'
|
|
196
209
|
# piper_tts:
|
|
@@ -96,6 +96,38 @@ def test_bind_context_sets_and_resets_request_id() -> None:
|
|
|
96
96
|
assert get_request_id() is None
|
|
97
97
|
|
|
98
98
|
|
|
99
|
+
def test_bind_context_aclose_from_different_asyncio_context_does_not_raise() -> None:
|
|
100
|
+
"""When bind_context wraps a yield in an async generator and the generator
|
|
101
|
+
is later closed from a different asyncio Context, loguru's
|
|
102
|
+
contextualize.__exit__ raises
|
|
103
|
+
``ValueError("<Token ...> was created in a different Context")``.
|
|
104
|
+
|
|
105
|
+
Production trace (2026-05-06): openspeechapi/dispatch/dispatcher.py
|
|
106
|
+
``_synthesize_stream`` holds bind_context across ``yield chunk``; when
|
|
107
|
+
the consumer's task is cancelled, athrow runs the finally in a new
|
|
108
|
+
Context and the unhandled ValueError pollutes the log.
|
|
109
|
+
|
|
110
|
+
bind_context must swallow that cleanup error.
|
|
111
|
+
"""
|
|
112
|
+
import asyncio
|
|
113
|
+
|
|
114
|
+
async def gen():
|
|
115
|
+
with bind_context(request_id="rid", provider="prov"):
|
|
116
|
+
for i in range(3):
|
|
117
|
+
yield i
|
|
118
|
+
|
|
119
|
+
async def driver():
|
|
120
|
+
g = gen()
|
|
121
|
+
first = await g.__anext__()
|
|
122
|
+
assert first == 0
|
|
123
|
+
# Closing from a freshly-created task puts aclose in a different
|
|
124
|
+
# asyncio Context than where bind_context was entered. This is the
|
|
125
|
+
# exact mismatch that production hit.
|
|
126
|
+
await asyncio.create_task(g.aclose())
|
|
127
|
+
|
|
128
|
+
asyncio.run(driver())
|
|
129
|
+
|
|
130
|
+
|
|
99
131
|
def test_bind_context_decorates_log_records(tmp_path: Path) -> None:
|
|
100
132
|
configure_logging(level="DEBUG", format="json", log_dir=str(tmp_path))
|
|
101
133
|
captured: list[dict] = []
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/architecture/stt-engineering-optimization-guide.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/superpowers/specs/2026-04-03-hot-lazy-loading.md
RENAMED
|
File without changes
|
|
File without changes
|
{openspeechapi-0.2.4 → openspeechapi-0.2.6}/docs/superpowers/specs/2026-04-03-phase3-production.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/dispatch/executors/subprocess_exec.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/backends/__init__.py
RENAMED
|
File without changes
|
{openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/backends/docker_backend.py
RENAMED
|
File without changes
|
{openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/backends/native_backend.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/engines/faster_whisper.py
RENAMED
|
File without changes
|
{openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/engines/fish_speech.py
RENAMED
|
File without changes
|
{openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/engines/sherpa_onnx.py
RENAMED
|
File without changes
|
|
File without changes
|
{openspeechapi-0.2.4 → openspeechapi-0.2.6}/openspeechapi/local_engines/engines/whisperlivekit.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|