├── .YANDEX_PRIVATE_KEY.txt.gpg ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── publish-to-pypi.yml │ └── python-package.yml ├── .gitignore ├── .pyup.yml ├── .readthedocs.yaml ├── LICENSE.txt ├── README.md ├── docs ├── Makefile ├── make.bat ├── requirements.txt └── source │ ├── auth.rst │ ├── conf.py │ ├── exceptions.rst │ ├── index.rst │ ├── speechkit.rst │ └── utils.rst ├── examples ├── long_audio_recognition.py └── streaming_recognize.py ├── pyproject.toml ├── requirements.txt ├── setup.cfg └── src ├── speechkit ├── __init__.py ├── _auth.py ├── _recognition │ ├── __init__.py │ ├── google │ │ ├── __init__.py │ │ ├── api │ │ │ ├── __init__.py │ │ │ ├── annotations_pb2.py │ │ │ ├── annotations_pb2_grpc.py │ │ │ ├── http_pb2.py │ │ │ └── http_pb2_grpc.py │ │ └── rpc │ │ │ ├── __init__.py │ │ │ ├── status_pb2.py │ │ │ └── status_pb2_grpc.py │ ├── streaming_recognition.py │ ├── sync_recognition.py │ └── yandex │ │ ├── __init__.py │ │ └── cloud │ │ ├── __init__.py │ │ ├── ai │ │ ├── __init__.py │ │ └── stt │ │ │ ├── __init__.py │ │ │ └── v2 │ │ │ ├── __init__.py │ │ │ ├── stt_service_pb2.py │ │ │ └── stt_service_pb2_grpc.py │ │ ├── api │ │ ├── __init__.py │ │ ├── operation_pb2.py │ │ └── operation_pb2_grpc.py │ │ └── operation │ │ ├── __init__.py │ │ ├── operation_pb2.py │ │ └── operation_pb2_grpc.py ├── _synthesis.py ├── auth.py ├── exceptions.py └── utils.py └── tests ├── __init__.py ├── test_auth.py ├── test_exceptions.py ├── test_long_audio_recognition.py ├── test_short_audio_recognition.py ├── test_speech_synthesis.py ├── test_streaming_recognition.py └── test_utils.py /.YANDEX_PRIVATE_KEY.txt.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikhonp/yandex-speechkit-lib-python/3376c02ed42870c0ad741b52067b5c9941ec84b5/.YANDEX_PRIVATE_KEY.txt.gpg -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/publish-to-pypi.yml: -------------------------------------------------------------------------------- 1 | name: Publish Python 🐍 distributions 📦 to PyPI 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | build-n-publish: 12 | name: Build and publish Python 🐍 distributions 📦 to PyPI 13 | 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | 19 | - name: Set up Python 20 | uses: actions/setup-python@v4 21 | with: 22 | python-version: "3.x" 23 | 24 | - name: Install pypa/build 25 | run: >- 26 | python -m 27 | pip install 28 | build 29 | --user 30 | 31 | - name: Build a binary wheel and a source tarball 32 | run: >- 33 | python -m 34 | build 35 | --sdist 36 | --wheel 37 | --outdir dist/ 38 | . 39 | 40 | - name: Publish distribution 📦 to PyPI 41 | uses: pypa/gh-action-pypi-publish@release/v1 42 | with: 43 | password: ${{ secrets.PYPI_API_TOKEN }} 44 | -------------------------------------------------------------------------------- /.github/workflows/python-package.yml: -------------------------------------------------------------------------------- 1 | name: Speechkit python package 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | -master 10 | 11 | jobs: 12 | build: 13 | name: Build and test Python 🐍 package 14 | 15 | runs-on: ubuntu-latest 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | python-version: [ "3.8", "3.9", "3.10" ] 20 | 21 | steps: 22 | - uses: actions/checkout@v3 23 | 24 | - name: Set up Python ${{ matrix.python-version }} 25 | uses: actions/setup-python@v3 26 | with: 27 | python-version: ${{ matrix.python-version }} 28 | 29 | - name: Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | python -m pip install flake8 codecov 33 | pip install -r requirements.txt 34 | 35 | - name: Install package 36 | run: | 37 | pip install ".[test]" . 38 | 39 | - name: Lint with flake8 40 | run: | 41 | # stop the build if there are Python syntax errors or undefined names 42 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 43 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 44 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 45 | 46 | - name: Test with unittest 47 | run: | 48 | gpg --quiet --batch --yes --decrypt --passphrase="$YANDEX_PRIVATE_KEY_PASSPHRASE" \ 49 | --output .YANDEX_PRIVATE_KEY.txt .YANDEX_PRIVATE_KEY.txt.gpg 50 | cd src 51 | coverage run -m unittest discover && coverage report 52 | codecov 53 | env: 54 | BUCKET_NAME: ${{ secrets.BUCKET_NAME }} 55 | CATALOG: ${{ secrets.CATALOG }} 56 | SERVICE_ACCOUNT_ID: ${{ secrets.SERVICE_ACCOUNT_ID }} 57 | SERVICE_API_KEY: ${{ secrets.SERVICE_API_KEY }} 58 | YANDEX_KEY_ID: ${{ secrets.YANDEX_KEY_ID }} 59 | YANDEX_OAUTH: ${{ secrets.YANDEX_OAUTH }} 60 | YANDEX_PRIVATE_KEY_PASSPHRASE: ${{ secrets.YANDEX_PRIVATE_KEY_PASSPHRASE }} 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | 132 | *.DS_Store 133 | *.swp 134 | .idea/ 135 | bash_profile 136 | /.YANDEX_PRIVATE_KEY.txt 137 | /src/tests/test_rec.wav 138 | /src/tests/test_synth.wav 139 | -------------------------------------------------------------------------------- /.pyup.yml: -------------------------------------------------------------------------------- 1 | # autogenerated pyup.io config file 2 | # see https://pyup.io/docs/configuration/ for all available options 3 | 4 | schedule: '' 5 | update: false 6 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | build: 4 | os: "ubuntu-22.04" 5 | tools: 6 | python: "3.10" 7 | 8 | sphinx: 9 | builder: html 10 | configuration: docs/source/conf.py 11 | fail_on_warning: true 12 | 13 | formats: 14 | - pdf 15 | 16 | python: 17 | install: 18 | - requirements: docs/requirements.txt 19 | - requirements: requirements.txt 20 | - method: pip 21 | path: . 22 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Tikhon Petrishchev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |

🎙 Yandex SpeechKit Python SDK

4 | 5 | ![PyPI](https://img.shields.io/pypi/v/speechkit) 6 | ![GitHub](https://img.shields.io/github/license/tikhonp/yandex-speechkit-lib-python) 7 | ![build and test](https://github.com/TikhonP/yandex-speechkit-lib-python/actions/workflows/python-package.yml/badge.svg) 8 | [![codecov](https://codecov.io/gh/tikhonp/yandex-speechkit-lib-python/branch/master/graph/badge.svg?token=NRNV9E36I4)](https://codecov.io/gh/tikhonp/yandex-speechkit-lib-python) 9 | [![Documentation Status](https://readthedocs.org/projects/yandex-speechkit-lib-python/badge/?version=latest)](https://pip.pypa.io/en/stable/?badge=stable) 10 | [![Downloads](https://pepy.tech/badge/speechkit)](https://pepy.tech/project/speechkit) 11 |
12 | 13 | Python SDK for Yandex SpeechKit API. This SDK allows you to use the cloud API for speech recognition and synthesis from Yandex. 14 | 15 | For more information please visit [Yandex Speechkit API Docs](https://cloud.yandex.com/en/docs/speechkit/). This lib 16 | supports short and long audio recognition with speechkit 17 | 18 | ## 🛠 Getting Started 19 | 20 | Assuming that you have Python and `virtualenv` installed, set up your environment and install the required dependencies 21 | like this, or you can install the library using `pip`: 22 | 23 | ```sh 24 | $ git clone https://github.com/TikhonP/yandex-speechkit-lib-python.git 25 | $ cd yandex-speechkit-lib-python 26 | $ virtualenv venv 27 | ... 28 | $ . venv/bin/activate 29 | $ python -m pip install -r requirements.txt 30 | $ python -m pip install . 31 | ``` 32 | 33 | ```sh 34 | python -m pip install speechkit 35 | ``` 36 | 37 | ## 📑 Speechkit documentation 38 | 39 | Check out [speechkit docs](https://yandex-speechkit-lib-python.readthedocs.io/en/latest/index.html) for more 40 | info. [PDF docs](https://yandex-speechkit-lib-python.readthedocs.io/_/downloads/en/latest/pdf/) 41 | 42 | ## 🔮 Using speechkit 43 | 44 | There are support of recognizing long and short audio and synthesis. For more information please read docs below. 45 | 46 | First you need create session for authorisation: 47 | 48 | ```python3 49 | from speechkit import Session 50 | 51 | oauth_token = str('') 52 | folder_id = str('') 53 | api_key = str('') 54 | jwt_token = str('') 55 | 56 | oauth_session = Session.from_yandex_passport_oauth_token(oauth_token, folder_id) 57 | api_key_session = Session.from_api_key(api_key, x_client_request_id_header=True, x_data_logging_enabled=True) 58 | # You can use `x_client_request_id_header` and `x_data_logging_enabled` params to troubleshoot yandex recognition 59 | # Use `Session.get_x_client_request_id()` method to get x_client_request_id value. 60 | jwt_session = Session.from_jwt(jwt_token) 61 | ``` 62 | 63 | Use created session to make other requests. 64 | 65 | There are also functions for getting credentials (read [Documentation](https://yandex-speechkit-lib-python.readthedocs.io/en/latest/index.html) for more info): 66 | `Speechkit.auth.generate_jwt`, `speechkit.auth.get_iam_token`, `speechkit.auth.get_api_key` 67 | 68 | ### For audio recognition 69 | 70 | Short audio: 71 | 72 | ```python3 73 | from speechkit import ShortAudioRecognition 74 | 75 | recognizeShortAudio = ShortAudioRecognition(session) 76 | with open(str('/Users/tikhon/Desktop/out.wav'), str('rb')) as f: 77 | data = f.read() 78 | 79 | print(recognizeShortAudio.recognize(data, format='lpcm', sampleRateHertz='48000')) 80 | 81 | # Will be printed: 'text that need to be recognized' 82 | ``` 83 | 84 | Look at example with long 85 | audio [long_audio_recognition.py](https://github.com/TikhonP/yandex-speechkit-lib-python/blob/master/examples/long_audio_recognition.py) 86 | . 87 | 88 | Look at example with streaming 89 | audio [streaming_recognize.py](https://github.com/TikhonP/yandex-speechkit-lib-python/blob/master/examples/streaming_recognize.py) 90 | 91 | ### For synthesis 92 | 93 | ```python3 94 | from speechkit import SpeechSynthesis 95 | 96 | synthesizeAudio = SpeechSynthesis(session) 97 | synthesizeAudio.synthesize( 98 | str('/Users/tikhon/Desktop/out.wav'), text='Text that will be synthesised', 99 | voice='oksana', format='lpcm', sampleRateHertz='16000' 100 | ) 101 | ``` 102 | 103 | ## 🔗 Links 104 | 105 | - [Readthedocs Documentation for this package](https://yandex-speechkit-lib-python.readthedocs.io/en/latest/index.html) 106 | - [Yandex Speechkit Documentation](https://cloud.yandex.com/en/docs/speechkit/) 107 | - [Статья на хабре](https://habr.com/ru/post/681566/) 108 | 109 | ## 💼 License 110 | 111 | [MIT](LICENSE) 112 | 113 | In other words, you can use the code for private and commercial purposes with an author attribution (by including the original license file). 114 | 115 | ❤️ 116 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx>=4.1.2 2 | sphinx_markdown_builder>=0.5.4 3 | sphinx-rtd-theme>=0.5.2 4 | -------------------------------------------------------------------------------- /docs/source/auth.rst: -------------------------------------------------------------------------------- 1 | speechkit.auth module 2 | --------------------- 3 | 4 | .. automodule:: speechkit.auth 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | import sys 15 | 16 | sys.path.insert(0, os.path.abspath('../../src')) 17 | 18 | 19 | # -- Project information ----------------------------------------------------- 20 | 21 | project = 'Yandex Speechkit SDK' 22 | copyright = '2021, Tikhon Petrishchev' 23 | author = 'Tikhon Petrishchev' 24 | 25 | # The full version, including alpha/beta/rc tags 26 | release = '1.3.0' 27 | 28 | 29 | # -- General configuration --------------------------------------------------- 30 | 31 | # Add any Sphinx extension module names here, as strings. They can be 32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 33 | # ones. 34 | extensions = [ 35 | 'sphinx.ext.autodoc', 36 | 'sphinx.ext.viewcode', 37 | 'sphinx_markdown_builder' 38 | ] 39 | 40 | # Add any paths that contain templates here, relative to this directory. 41 | templates_path = ['_templates'] 42 | autoclass_content = 'both' 43 | 44 | # List of patterns, relative to source directory, that match files and 45 | # directories to ignore when looking for source files. 46 | # This pattern also affects html_static_path and html_extra_path. 47 | exclude_patterns = [] 48 | 49 | 50 | # -- Options for HTML _recognition ------------------------------------------------- 51 | 52 | # The theme to use for HTML and HTML Help pages. See the documentation for 53 | # a list of builtin themes. 54 | # 55 | html_theme = "sphinx_rtd_theme" 56 | 57 | # Add any paths that contain custom static files (such as style sheets) here, 58 | # relative to this directory. They are copied after the builtin static files, 59 | # so a file named "default.css" will overwrite the builtin "default.css". 60 | html_static_path = [] 61 | -------------------------------------------------------------------------------- /docs/source/exceptions.rst: -------------------------------------------------------------------------------- 1 | speechkit.exceptions module 2 | --------------------------- 3 | 4 | .. automodule:: speechkit.exceptions 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. speechkit documentation master file, created by 2 | sphinx-quickstart on Tue Jul 20 03:54:03 2021. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to speechkit's documentation! 7 | ===================================== 8 | 9 | Speechkit is python SDK for Yandex SpeechKit API. 10 | 11 | Installation 12 | ------------ 13 | 14 | Assuming that you have Python and virtualenv installed, set up your environment and install the required dependencies 15 | like this:: 16 | 17 | 18 | $ git clone https://github.com/TikhonP/yandex-speechkit-lib-python.git 19 | $ cd yandex-speechkit-lib-python 20 | $ virtualenv venv 21 | ... 22 | $ . venv/bin/activate 23 | $ python -m pip install -r requirements.txt 24 | $ python -m pip install . 25 | 26 | Or you can install the library using pip:: 27 | 28 | python -m pip install speechkit 29 | 30 | Api Reference 31 | ------------- 32 | 33 | .. toctree:: 34 | :maxdepth: 2 35 | :caption: Contents: 36 | 37 | speechkit 38 | 39 | auth 40 | 41 | utils 42 | 43 | exceptions 44 | 45 | Some Shortcuts dor YC console tool 46 | ---------------------------------- 47 | 48 | Get FOLDER_ID: FOLDER_ID=$(yc config get folder-id) 49 | 50 | Create service-account: yc iam service-account create --name admin 51 | 52 | Get id of service-account: SA_ID=$(yc iam service-account get --name admin --format json | jq .id -r) 53 | 54 | Assign a role to the admin service account using its ID: yc resource-manager folder add-access-binding --id $FOLDER_ID --role admin --subject serviceAccount:$SA_ID 55 | 56 | Indices and tables 57 | ================== 58 | 59 | * :ref:`genindex` 60 | * :ref:`modindex` 61 | * :ref:`search` 62 | -------------------------------------------------------------------------------- /docs/source/speechkit.rst: -------------------------------------------------------------------------------- 1 | speechkit package 2 | ================= 3 | 4 | .. automodule:: speechkit 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/utils.rst: -------------------------------------------------------------------------------- 1 | speechkit.utils module 2 | ---------------------- 3 | 4 | .. automodule:: speechkit.utils 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: -------------------------------------------------------------------------------- /examples/long_audio_recognition.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | from sys import argv 4 | 5 | from speechkit import RecognitionLongAudio, Session 6 | from speechkit.auth import generate_jwt 7 | 8 | _, filename = argv 9 | 10 | bucket_name = os.environ.get('BUCKET_NAME') 11 | service_account_id = os.environ.get('SERVICE_ACCOUNT_ID') 12 | key_id = os.environ.get('YANDEX_KEY_ID') 13 | private_key = os.environ.get('YANDEX_PRIVATE_KEY').replace('\\n', '\n').encode() 14 | 15 | if not key_id or not service_account_id or not bucket_name or not private_key: 16 | print("Specify `YANDEX_KEY_ID`, `SERVICE_ACCOUNT_ID`, `BUCKET_NAME`, `private_key` environment variables.") 17 | exit() 18 | 19 | jwt = generate_jwt(service_account_id, key_id, private_key) 20 | session = Session.from_jwt(jwt) 21 | 22 | # Maybe you want to create aws s3 key only once 23 | # In that case from version 2.2.0 you can do: 24 | access_key_id, secret = RecognitionLongAudio.get_aws_credentials(session, service_account_id) 25 | 26 | # And then use it: 27 | recognize_long_audio = RecognitionLongAudio(session, service_account_id, bucket_name, aws_access_key_id=access_key_id, 28 | aws_secret=secret) 29 | 30 | # Or you can do it automatically 31 | # recognize_long_audio = RecognitionLongAudio(session, service_account_id, bucket_name) 32 | 33 | print("Sending file for recognition...") 34 | recognize_long_audio.send_for_recognition( 35 | filename, audioEncoding='LINEAR16_PCM', sampleRateHertz='48000', 36 | audioChannelCount=1, rawResults=False 37 | ) 38 | while True: 39 | time.sleep(2) 40 | if recognize_long_audio.get_recognition_results(): 41 | break 42 | print("Recognizing...") 43 | 44 | data = recognize_long_audio.get_data() 45 | print("DATA:\n\n", data) 46 | 47 | text = recognize_long_audio.get_raw_text() 48 | print("TEXT:\n\n", text) 49 | -------------------------------------------------------------------------------- /examples/streaming_recognize.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | import pyaudio 5 | from iterators import TimeoutIterator 6 | 7 | from speechkit import DataStreamingRecognition, Session 8 | from speechkit.auth import generate_jwt 9 | 10 | CHUNK_SIZE = 4000 11 | 12 | service_account_id = os.environ.get('SERVICE_ACCOUNT_ID') 13 | key_id = os.environ.get('YANDEX_KEY_ID') 14 | private_key = os.environ.get('YANDEX_PRIVATE_KEY').replace('\\n', '\n').encode() 15 | 16 | jwt = generate_jwt(service_account_id, key_id, private_key) 17 | session = Session.from_jwt(jwt) 18 | data_streaming_recognition = DataStreamingRecognition( 19 | session, 20 | language_code='ru-RU', 21 | audio_encoding='LINEAR16_PCM', 22 | sample_rate_hertz=8000, 23 | partial_results=False, 24 | single_utterance=True, 25 | ) 26 | 27 | 28 | def gen_audio_from_file_function(): 29 | with open('/Users/tikhon/Downloads/speech.pcm', 'rb') as f: 30 | data = f.read(CHUNK_SIZE) 31 | while data != b'': 32 | yield data 33 | data = f.read(CHUNK_SIZE) 34 | 35 | 36 | def gen_audio_capture_function(chunk_size=1024): 37 | p = pyaudio.PyAudio() 38 | stream = p.open( 39 | format=pyaudio.paInt16, 40 | channels=1, 41 | rate=8000, 42 | input=True, 43 | frames_per_buffer=chunk_size 44 | ) 45 | try: 46 | while True: 47 | yield stream.read(chunk_size) 48 | finally: 49 | stream.stop_stream() 50 | stream.close() 51 | p.terminate() 52 | 53 | 54 | for text, final, end_of_utterance in data_streaming_recognition.recognize( 55 | gen_audio_capture_function, chunk_size=CHUNK_SIZE 56 | ): 57 | print(text[0]) # text is list of alternatives 58 | 59 | if final: # Stop when final_flag set 60 | break 61 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools>=42", 4 | "wheel" 5 | ] 6 | build-backend = "setuptools.build_meta" 7 | 8 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | boto3 2 | requests 3 | grpcio-tools>=1.39.0 4 | protobuf~=3.19.6 5 | pyjwt>=2.1.0 6 | cryptography 7 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = speechkit 3 | version = 2.2.3 4 | author = Tikhon Petrishchev 5 | author_email = tikhon.petrishchev@gmail.com 6 | description = Python SDK for Yandex Speechkit API. 7 | long_description = file: README.md 8 | long_description_content_type = text/markdown 9 | url = https://github.com/TikhonP/yandex-speechkit-lib-python 10 | project_urls = 11 | Bug Tracker = https://github.com/TikhonP/yandex-speechkit-lib-python/issues 12 | Documentation = https://yandex-speechkit-lib-python.readthedocs.io/en/latest/index.html 13 | GitHub = https://github.com/TikhonP/yandex-speechkit-lib-python 14 | classifiers = 15 | Development Status :: 5 - Production/Stable 16 | Intended Audience :: Developers 17 | Natural Language :: English 18 | Programming Language :: Python 19 | Programming Language :: Python :: 3 20 | Programming Language :: Python :: 3.6 21 | Programming Language :: Python :: 3.7 22 | Programming Language :: Python :: 3.8 23 | Programming Language :: Python :: 3.9 24 | Programming Language :: Python :: 3.10 25 | License :: OSI Approved :: MIT License 26 | Operating System :: OS Independent 27 | 28 | [options] 29 | packages = find: 30 | install_requires = 31 | boto3 32 | requests 33 | grpcio-tools >=1.39.0 34 | protobuf ~=3.19.6 35 | pyjwt >=2.1.0 36 | cryptography 37 | package_dir = 38 | =src 39 | python_requires = >=3.6 40 | 41 | [options.packages.find] 42 | where = src 43 | -------------------------------------------------------------------------------- /src/speechkit/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | speechkit 3 | Python SDK for using Yandex Speech recognition and synthesis. 4 | """ 5 | 6 | __author__ = 'Tikhon Petrishchev' 7 | __version__ = '2.2.3' 8 | 9 | from speechkit._auth import Session 10 | from speechkit._recognition.streaming_recognition import DataStreamingRecognition 11 | from speechkit._recognition.sync_recognition import ShortAudioRecognition, RecognitionLongAudio 12 | from speechkit._synthesis import SpeechSynthesis 13 | 14 | __all__ = ['Session', 'SpeechSynthesis', 'ShortAudioRecognition', 'RecognitionLongAudio', 'DataStreamingRecognition'] 15 | -------------------------------------------------------------------------------- /src/speechkit/_auth.py: -------------------------------------------------------------------------------- 1 | import time 2 | import uuid 3 | 4 | import jwt 5 | import requests 6 | 7 | from speechkit.exceptions import RequestError 8 | 9 | 10 | def generate_jwt(service_account_id, key_id, private_key, exp_time=360): 11 | """ 12 | Generating JWT token for authorisation 13 | 14 | :param string service_account_id: The ID of the service account whose key the JWT is signed with. 15 | :param string key_id: The ID of the Key resource belonging to the service account. 16 | :param bytes private_key: Private key given from Yandex Cloud console in bytes 17 | :param integer exp_time: Optional. The token expiration time delta in seconds. The expiration 18 | time must not exceed the issue time by more than one hour, meaning exp_time ≤ 3600. Default 360 19 | :return: JWT token 20 | :rtype: string 21 | """ 22 | if not isinstance(service_account_id, str) or not isinstance(key_id, str): 23 | raise ValueError("service_account_id, key_id, must be strings.") 24 | if 0 in (len(service_account_id), len(key_id)): 25 | raise ValueError("service_account_id, key_id, can't be empty.") 26 | if not isinstance(private_key, bytes): 27 | raise ValueError("private_key must be bytes string, but got {}".format(type(private_key))) 28 | if not isinstance(exp_time, int): 29 | raise ValueError("exp_time must be int, but got {}".format(type(exp_time))) 30 | if exp_time > 3600: 31 | raise ValueError("exp_time ≤ 3600, but got {}".format(exp_time)) 32 | 33 | now = int(time.time()) 34 | payload = { 35 | 'aud': 'https://iam.api.cloud.yandex.net/iam/v1/tokens', 36 | 'iss': service_account_id, 37 | 'iat': now, 38 | 'exp': now + exp_time 39 | } 40 | return jwt.encode( 41 | payload, 42 | private_key, 43 | algorithm='PS256', 44 | headers={'kid': key_id} 45 | ) 46 | 47 | 48 | def get_iam_token(yandex_passport_oauth_token=None, jwt_token=None): 49 | """ 50 | Creates an IAM token for the specified identity. 51 | `Getting IAM for Yandex account `_ 52 | 53 | :param string yandex_passport_oauth_token: OAuth token from Yandex OAuth 54 | :param string jwt_token: Json Web Token, can be generated by :py:meth:`speechkit.generate_jwt` 55 | :return: IAM token 56 | :rtype: string 57 | """ 58 | if not type(yandex_passport_oauth_token) in (str, type(None)): 59 | raise TypeError("__init__() yandex_passport_oauth_token: got {} but expected \ 60 | type is str or None".format(type(yandex_passport_oauth_token).__name__)) 61 | 62 | if not type(jwt_token) in (str, type(None)): 63 | raise TypeError("__init__() jwt_token: got {} but expected \ 64 | type is str or None".format(type(jwt_token).__name__)) 65 | 66 | if (not yandex_passport_oauth_token and not jwt_token) or (yandex_passport_oauth_token and jwt_token): 67 | raise ValueError("Includes only one of the fields `yandex_passport_oauth_token`, `jwt_token`") 68 | 69 | if yandex_passport_oauth_token: 70 | data = {'yandexPassportOauthToken': str(yandex_passport_oauth_token)} 71 | else: 72 | data = {'jwt': str(jwt_token)} 73 | 74 | url = "https://iam.api.cloud.yandex.net/iam/v1/tokens" 75 | answer = requests.post(url, json=data) 76 | 77 | if answer.ok: 78 | return answer.json().get('iamToken') 79 | else: 80 | raise RequestError(answer.json()) 81 | 82 | 83 | def get_api_key(yandex_passport_oauth_token=None, service_account_id=None, 84 | description='Default Api-Key created by `speechkit` python SDK'): 85 | """ 86 | Creates an API key for the specified service account. 87 | 88 | :param string yandex_passport_oauth_token: OAuth token from Yandex OAuth 89 | :param string service_account_id: The ID of the service account whose key the Api-Key is signed with. 90 | :param string description: Description for api-key. Optional. 91 | :return: Api-Key 92 | :rtype: string 93 | """ 94 | if not yandex_passport_oauth_token or not service_account_id: 95 | raise ValueError("`yandex_passport_oauth_token` and `service_account_id` required.") 96 | 97 | url = 'https://iam.api.cloud.yandex.net/iam/v1/apiKeys' 98 | headers = { 99 | 'Authorization': 'Bearer {}'.format(get_iam_token(yandex_passport_oauth_token=yandex_passport_oauth_token)) 100 | } 101 | data = {'serviceAccountId': service_account_id, 'description': description} 102 | 103 | answer = requests.post(url, headers=headers, json=data) 104 | if answer.ok: 105 | return answer.json().get('secret') 106 | else: 107 | raise RequestError(answer.json()) 108 | 109 | 110 | class Session: 111 | """Class provides yandex API authentication.""" 112 | 113 | IAM_TOKEN = 'iam_token' 114 | """Iam_token if iam auth, value: 'iam_token'""" 115 | 116 | API_KEY = 'api_key' 117 | """Api key if api-key auth, value: 'api_key'""" 118 | 119 | def __init__(self, auth_type, credential, folder_id, x_client_request_id_header=False, 120 | x_data_logging_enabled=False): 121 | """ 122 | Stores credentials for given auth method 123 | 124 | :param string auth_type: Type of auth may be :py:meth:`Session.IAM_TOKEN` or :py:meth:`Session.API_KEY` 125 | :param string | None folder_id: Id of the folder that you have access to. Don't specify this field if 126 | you make a request on behalf of a service account. 127 | :param string credential: Auth key iam or api key 128 | :param boolean x_client_request_id_header: include x-client-request-id. `x-client-request-id` is a unique 129 | request ID. It is generated using uuid. Send this ID to the technical support team to help us find 130 | a specific request in the system and assist you. To get x_client_request_id_header use 131 | `Session.get_x_client_request_id()` method. 132 | :param boolean x_data_logging_enabled: A flag that allows data passed by the user in the request to be saved. 133 | By default, we do not save any audio or text that you send. If you pass the true value in this header, 134 | your data is saved. This data, along with the request ID, will help the Yandex technical support team solve 135 | your problem. 136 | """ 137 | if auth_type not in (self.IAM_TOKEN, self.API_KEY): 138 | raise ValueError( 139 | "auth_type must be `Session.IAM_TOKEN` or `Session.API_KEY`, but given {}".format(auth_type) 140 | ) 141 | 142 | self._auth_method = auth_type 143 | 144 | if not isinstance(credential, str): 145 | raise ValueError("_credential must be string, but got {}".format(type(credential))) 146 | 147 | self._credential = credential 148 | self.folder_id = folder_id 149 | 150 | self._x_client_request_id = str(uuid.uuid4()) if x_client_request_id_header else None 151 | self._x_data_logging_enabled = x_data_logging_enabled 152 | 153 | @classmethod 154 | def from_api_key(cls, api_key, folder_id=None, x_client_request_id_header=False, x_data_logging_enabled=False): 155 | """ 156 | Creates session from api key 157 | 158 | :param string api_key: Yandex Cloud Api-Key 159 | :param string | None folder_id: Id of the folder that you have access to. Don't specify this field if 160 | you make a request on behalf of a service account. 161 | :param boolean x_client_request_id_header: include x-client-request-id. `x-client-request-id` is a unique 162 | request ID. It is generated using uuid. Send this ID to the technical support team to help us find 163 | a specific request in the system and assist you. To get x_client_request_id_header use 164 | `Session.get_x_client_request_id()` method. 165 | :param boolean x_data_logging_enabled: A flag that allows data passed by the user in the request to be saved. 166 | By default, we do not save any audio or text that you send. If you pass the true value in this header, 167 | your data is saved. This data, along with the request ID, will help the Yandex technical support team solve 168 | your problem. 169 | :return: Session instance 170 | :rtype: Session 171 | """ 172 | if not isinstance(api_key, str): 173 | raise ValueError("Api-Key must be string, but got {}".format(type(api_key))) 174 | if len(api_key) == 0: 175 | raise ValueError("Api-Key can not be empty.") 176 | 177 | if folder_id: 178 | if not isinstance(folder_id, str): 179 | raise ValueError("folder_id must be string, but got {}".format(type(folder_id))) 180 | if len(folder_id) == 0: 181 | raise ValueError("folder_id must not be empty.") 182 | 183 | return cls(cls.API_KEY, api_key, folder_id=folder_id, x_client_request_id_header=x_client_request_id_header, 184 | x_data_logging_enabled=x_data_logging_enabled) 185 | 186 | @classmethod 187 | def from_yandex_passport_oauth_token(cls, yandex_passport_oauth_token, folder_id, x_client_request_id_header=False, 188 | x_data_logging_enabled=False): 189 | """ 190 | Creates Session from oauth token Yandex account 191 | 192 | :param string yandex_passport_oauth_token: OAuth token from Yandex.OAuth 193 | :param string folder_id: Id of the folder that you have access to. Don't specify this field if 194 | you make a request on behalf of a service account. 195 | :param boolean x_client_request_id_header: include x-client-request-id. `x-client-request-id` is a unique 196 | request ID. It is generated using uuid. Send this ID to the technical support team to help us find 197 | a specific request in the system and assist you. To get x_client_request_id_header use 198 | `Session.get_x_client_request_id()` method. 199 | :param boolean x_data_logging_enabled: A flag that allows data passed by the user in the request to be saved. 200 | By default, we do not save any audio or text that you send. If you pass the true value in this header, 201 | your data is saved. This data, along with the request ID, will help the Yandex technical support team solve 202 | your problem. 203 | :return: Session instance 204 | :rtype: Session 205 | """ 206 | if not isinstance(yandex_passport_oauth_token, str): 207 | raise ValueError( 208 | "yandex_passport_oauth_token must be string, but got {}".format(type(yandex_passport_oauth_token)) 209 | ) 210 | if len(yandex_passport_oauth_token) == 0: 211 | raise ValueError("yandex_passport_oauth_token can not be empty.") 212 | 213 | if not isinstance(folder_id, str): 214 | raise ValueError("folder_id must be string, but got {}".format(type(folder_id))) 215 | if len(folder_id) == 0: 216 | raise ValueError("folder_id must not be empty.") 217 | 218 | iam_token = get_iam_token(yandex_passport_oauth_token=yandex_passport_oauth_token) 219 | 220 | return cls(cls.IAM_TOKEN, iam_token, folder_id=folder_id, x_client_request_id_header=x_client_request_id_header, 221 | x_data_logging_enabled=x_data_logging_enabled) 222 | 223 | @classmethod 224 | def from_jwt(cls, jwt_token, folder_id=None, x_client_request_id_header=False, x_data_logging_enabled=False): 225 | """ 226 | Creates Session from JWT token 227 | 228 | :param string jwt_token: JWT 229 | :param string | None folder_id: Id of the folder that you have access to. Don't specify this field if 230 | you make a request on behalf of a service account. 231 | :param boolean x_client_request_id_header: include x-client-request-id. `x-client-request-id` is a unique 232 | request ID. It is generated using uuid. Send this ID to the technical support team to help us find 233 | a specific request in the system and assist you. To get x_client_request_id_header use 234 | `Session.get_x_client_request_id()` method. 235 | :param boolean x_data_logging_enabled: A flag that allows data passed by the user in the request to be saved. 236 | By default, we do not save any audio or text that you send. If you pass the true value in this header, 237 | your data is saved. This data, along with the request ID, will help the Yandex technical support team solve 238 | your problem. 239 | :return: Session instance 240 | :rtype: Session 241 | """ 242 | if not isinstance(jwt_token, str): 243 | raise ValueError("jwt_token must be string, but got {}".format(type(jwt_token))) 244 | if len(jwt_token) == 0: 245 | raise ValueError("jwt_token can not be empty.") 246 | 247 | if folder_id: 248 | if not isinstance(folder_id, str): 249 | raise ValueError("folder_id must be string, but got {}".format(type(folder_id))) 250 | if len(folder_id) == 0: 251 | raise ValueError("folder_id must not be empty.") 252 | 253 | iam_token = get_iam_token(jwt_token=jwt_token) 254 | 255 | return cls(cls.IAM_TOKEN, iam_token, folder_id=folder_id, x_client_request_id_header=x_client_request_id_header, 256 | x_data_logging_enabled=x_data_logging_enabled) 257 | 258 | @property 259 | def header(self): 260 | """ 261 | Authentication header. 262 | 263 | :return: Dict in format `{'Authorization': 'Bearer or Api-Key {iam or api_key}'}` 264 | :rtype: dict 265 | """ 266 | if self._auth_method == self.IAM_TOKEN: 267 | h = {'Authorization': 'Bearer {iam}'.format(iam=self._credential)} 268 | elif self._auth_method == self.API_KEY: 269 | h = {'Authorization': 'Api-Key {api_key}'.format(api_key=self._credential)} 270 | else: 271 | return 272 | if self._x_client_request_id is not None: 273 | h.update({'x-client-request-id': self._x_client_request_id}) 274 | if self._x_data_logging_enabled: 275 | h.update({'x-data-logging-enabled': 'true'}) 276 | return h 277 | 278 | @property 279 | def streaming_recognition_header(self): 280 | """ 281 | Authentication header for streaming recognition 282 | 283 | :return: Tuple in format `('authorization', 'Bearer or Api-Key {iam or api_key}')` 284 | :rtype: tuple 285 | """ 286 | 287 | if self._auth_method == self.IAM_TOKEN: 288 | h = tuple(('authorization', 'Bearer {iam}'.format(iam=self._credential),)) 289 | elif self._auth_method == self.API_KEY: 290 | h = tuple(('authorization', 'Api-Key {api_key}'.format(api_key=self._credential),)) 291 | else: 292 | return 293 | 294 | if self._x_client_request_id is not None: 295 | h = h + tuple(('x-client-request-id', self._x_client_request_id,)) 296 | if self._x_data_logging_enabled: 297 | h = h + tuple(('x-data-logging-enabled', 'true',)) 298 | return h 299 | 300 | @property 301 | def auth_method(self): 302 | """Get auth method it may be `Session.IAM_TOKEN` or `Session.API_KEY`""" 303 | 304 | return self._auth_method 305 | 306 | def get_x_client_request_id(self): 307 | """Get generated x_client_request_id value, if enabled on init, else `None`""" 308 | 309 | return self._x_client_request_id 310 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikhonp/yandex-speechkit-lib-python/3376c02ed42870c0ad741b52067b5c9941ec84b5/src/speechkit/_recognition/__init__.py -------------------------------------------------------------------------------- /src/speechkit/_recognition/google/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikhonp/yandex-speechkit-lib-python/3376c02ed42870c0ad741b52067b5c9941ec84b5/src/speechkit/_recognition/google/__init__.py -------------------------------------------------------------------------------- /src/speechkit/_recognition/google/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikhonp/yandex-speechkit-lib-python/3376c02ed42870c0ad741b52067b5c9941ec84b5/src/speechkit/_recognition/google/api/__init__.py -------------------------------------------------------------------------------- /src/speechkit/_recognition/google/api/annotations_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: google/api/annotations.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from speechkit._recognition.google.api import http_pb2 as google_dot_api_dot_http__pb2 15 | from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 16 | 17 | 18 | DESCRIPTOR = _descriptor.FileDescriptor( 19 | name='google/api/annotations.proto', 20 | package='google.api', 21 | syntax='proto3', 22 | serialized_options=b'\n\016com.google.apiB\020AnnotationsProtoP\001ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\242\002\004GAPI', 23 | create_key=_descriptor._internal_create_key, 24 | serialized_pb=b'\n\x1cgoogle/api/annotations.proto\x12\ngoogle.api\x1a\x15google/api/http.proto\x1a google/protobuf/descriptor.proto:E\n\x04http\x12\x1e.google.protobuf.MethodOptions\x18\xb0\xca\xbc\" \x01(\x0b\x32\x14.google.api.HttpRuleBn\n\x0e\x63om.google.apiB\x10\x41nnotationsProtoP\x01ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\xa2\x02\x04GAPIb\x06proto3' 25 | , 26 | dependencies=[google_dot_api_dot_http__pb2.DESCRIPTOR,google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,]) 27 | 28 | 29 | HTTP_FIELD_NUMBER = 72295728 30 | http = _descriptor.FieldDescriptor( 31 | name='http', full_name='google.api.http', index=0, 32 | number=72295728, type=11, cpp_type=10, label=1, 33 | has_default_value=False, default_value=None, 34 | message_type=None, enum_type=None, containing_type=None, 35 | is_extension=True, extension_scope=None, 36 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key) 37 | 38 | DESCRIPTOR.extensions_by_name['http'] = http 39 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 40 | 41 | http.message_type = google_dot_api_dot_http__pb2._HTTPRULE 42 | google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(http) 43 | 44 | DESCRIPTOR._options = None 45 | # @@protoc_insertion_point(module_scope) 46 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/google/api/annotations_pb2_grpc.py: -------------------------------------------------------------------------------- 1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! 2 | """Client and server classes corresponding to protobuf-defined services.""" 3 | import grpc 4 | 5 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/google/api/http_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: google/api/http.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor.FileDescriptor( 17 | name='google/api/http.proto', 18 | package='google.api', 19 | syntax='proto3', 20 | serialized_options=b'\n\016com.google.apiB\tHttpProtoP\001ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\370\001\001\242\002\004GAPI', 21 | create_key=_descriptor._internal_create_key, 22 | serialized_pb=b'\n\x15google/api/http.proto\x12\ngoogle.api\"+\n\x04Http\x12#\n\x05rules\x18\x01 \x03(\x0b\x32\x14.google.api.HttpRule\"\xea\x01\n\x08HttpRule\x12\x10\n\x08selector\x18\x01 \x01(\t\x12\r\n\x03get\x18\x02 \x01(\tH\x00\x12\r\n\x03put\x18\x03 \x01(\tH\x00\x12\x0e\n\x04post\x18\x04 \x01(\tH\x00\x12\x10\n\x06\x64\x65lete\x18\x05 \x01(\tH\x00\x12\x0f\n\x05patch\x18\x06 \x01(\tH\x00\x12/\n\x06\x63ustom\x18\x08 \x01(\x0b\x32\x1d.google.api.CustomHttpPatternH\x00\x12\x0c\n\x04\x62ody\x18\x07 \x01(\t\x12\x31\n\x13\x61\x64\x64itional_bindings\x18\x0b \x03(\x0b\x32\x14.google.api.HttpRuleB\t\n\x07pattern\"/\n\x11\x43ustomHttpPattern\x12\x0c\n\x04kind\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\tBj\n\x0e\x63om.google.apiB\tHttpProtoP\x01ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\xf8\x01\x01\xa2\x02\x04GAPIb\x06proto3' 23 | ) 24 | 25 | 26 | 27 | 28 | _HTTP = _descriptor.Descriptor( 29 | name='Http', 30 | full_name='google.api.Http', 31 | filename=None, 32 | file=DESCRIPTOR, 33 | containing_type=None, 34 | create_key=_descriptor._internal_create_key, 35 | fields=[ 36 | _descriptor.FieldDescriptor( 37 | name='rules', full_name='google.api.Http.rules', index=0, 38 | number=1, type=11, cpp_type=10, label=3, 39 | has_default_value=False, default_value=[], 40 | message_type=None, enum_type=None, containing_type=None, 41 | is_extension=False, extension_scope=None, 42 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 43 | ], 44 | extensions=[ 45 | ], 46 | nested_types=[], 47 | enum_types=[ 48 | ], 49 | serialized_options=None, 50 | is_extendable=False, 51 | syntax='proto3', 52 | extension_ranges=[], 53 | oneofs=[ 54 | ], 55 | serialized_start=37, 56 | serialized_end=80, 57 | ) 58 | 59 | 60 | _HTTPRULE = _descriptor.Descriptor( 61 | name='HttpRule', 62 | full_name='google.api.HttpRule', 63 | filename=None, 64 | file=DESCRIPTOR, 65 | containing_type=None, 66 | create_key=_descriptor._internal_create_key, 67 | fields=[ 68 | _descriptor.FieldDescriptor( 69 | name='selector', full_name='google.api.HttpRule.selector', index=0, 70 | number=1, type=9, cpp_type=9, label=1, 71 | has_default_value=False, default_value=b"".decode('utf-8'), 72 | message_type=None, enum_type=None, containing_type=None, 73 | is_extension=False, extension_scope=None, 74 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 75 | _descriptor.FieldDescriptor( 76 | name='get', full_name='google.api.HttpRule.get', index=1, 77 | number=2, type=9, cpp_type=9, label=1, 78 | has_default_value=False, default_value=b"".decode('utf-8'), 79 | message_type=None, enum_type=None, containing_type=None, 80 | is_extension=False, extension_scope=None, 81 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 82 | _descriptor.FieldDescriptor( 83 | name='put', full_name='google.api.HttpRule.put', index=2, 84 | number=3, type=9, cpp_type=9, label=1, 85 | has_default_value=False, default_value=b"".decode('utf-8'), 86 | message_type=None, enum_type=None, containing_type=None, 87 | is_extension=False, extension_scope=None, 88 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 89 | _descriptor.FieldDescriptor( 90 | name='post', full_name='google.api.HttpRule.post', index=3, 91 | number=4, type=9, cpp_type=9, label=1, 92 | has_default_value=False, default_value=b"".decode('utf-8'), 93 | message_type=None, enum_type=None, containing_type=None, 94 | is_extension=False, extension_scope=None, 95 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 96 | _descriptor.FieldDescriptor( 97 | name='delete', full_name='google.api.HttpRule.delete', index=4, 98 | number=5, type=9, cpp_type=9, label=1, 99 | has_default_value=False, default_value=b"".decode('utf-8'), 100 | message_type=None, enum_type=None, containing_type=None, 101 | is_extension=False, extension_scope=None, 102 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 103 | _descriptor.FieldDescriptor( 104 | name='patch', full_name='google.api.HttpRule.patch', index=5, 105 | number=6, type=9, cpp_type=9, label=1, 106 | has_default_value=False, default_value=b"".decode('utf-8'), 107 | message_type=None, enum_type=None, containing_type=None, 108 | is_extension=False, extension_scope=None, 109 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 110 | _descriptor.FieldDescriptor( 111 | name='custom', full_name='google.api.HttpRule.custom', index=6, 112 | number=8, type=11, cpp_type=10, label=1, 113 | has_default_value=False, default_value=None, 114 | message_type=None, enum_type=None, containing_type=None, 115 | is_extension=False, extension_scope=None, 116 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 117 | _descriptor.FieldDescriptor( 118 | name='body', full_name='google.api.HttpRule.body', index=7, 119 | number=7, type=9, cpp_type=9, label=1, 120 | has_default_value=False, default_value=b"".decode('utf-8'), 121 | message_type=None, enum_type=None, containing_type=None, 122 | is_extension=False, extension_scope=None, 123 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 124 | _descriptor.FieldDescriptor( 125 | name='additional_bindings', full_name='google.api.HttpRule.additional_bindings', index=8, 126 | number=11, type=11, cpp_type=10, label=3, 127 | has_default_value=False, default_value=[], 128 | message_type=None, enum_type=None, containing_type=None, 129 | is_extension=False, extension_scope=None, 130 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 131 | ], 132 | extensions=[ 133 | ], 134 | nested_types=[], 135 | enum_types=[ 136 | ], 137 | serialized_options=None, 138 | is_extendable=False, 139 | syntax='proto3', 140 | extension_ranges=[], 141 | oneofs=[ 142 | _descriptor.OneofDescriptor( 143 | name='pattern', full_name='google.api.HttpRule.pattern', 144 | index=0, containing_type=None, 145 | create_key=_descriptor._internal_create_key, 146 | fields=[]), 147 | ], 148 | serialized_start=83, 149 | serialized_end=317, 150 | ) 151 | 152 | 153 | _CUSTOMHTTPPATTERN = _descriptor.Descriptor( 154 | name='CustomHttpPattern', 155 | full_name='google.api.CustomHttpPattern', 156 | filename=None, 157 | file=DESCRIPTOR, 158 | containing_type=None, 159 | create_key=_descriptor._internal_create_key, 160 | fields=[ 161 | _descriptor.FieldDescriptor( 162 | name='kind', full_name='google.api.CustomHttpPattern.kind', index=0, 163 | number=1, type=9, cpp_type=9, label=1, 164 | has_default_value=False, default_value=b"".decode('utf-8'), 165 | message_type=None, enum_type=None, containing_type=None, 166 | is_extension=False, extension_scope=None, 167 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 168 | _descriptor.FieldDescriptor( 169 | name='path', full_name='google.api.CustomHttpPattern.path', index=1, 170 | number=2, type=9, cpp_type=9, label=1, 171 | has_default_value=False, default_value=b"".decode('utf-8'), 172 | message_type=None, enum_type=None, containing_type=None, 173 | is_extension=False, extension_scope=None, 174 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 175 | ], 176 | extensions=[ 177 | ], 178 | nested_types=[], 179 | enum_types=[ 180 | ], 181 | serialized_options=None, 182 | is_extendable=False, 183 | syntax='proto3', 184 | extension_ranges=[], 185 | oneofs=[ 186 | ], 187 | serialized_start=319, 188 | serialized_end=366, 189 | ) 190 | 191 | _HTTP.fields_by_name['rules'].message_type = _HTTPRULE 192 | _HTTPRULE.fields_by_name['custom'].message_type = _CUSTOMHTTPPATTERN 193 | _HTTPRULE.fields_by_name['additional_bindings'].message_type = _HTTPRULE 194 | _HTTPRULE.oneofs_by_name['pattern'].fields.append( 195 | _HTTPRULE.fields_by_name['get']) 196 | _HTTPRULE.fields_by_name['get'].containing_oneof = _HTTPRULE.oneofs_by_name['pattern'] 197 | _HTTPRULE.oneofs_by_name['pattern'].fields.append( 198 | _HTTPRULE.fields_by_name['put']) 199 | _HTTPRULE.fields_by_name['put'].containing_oneof = _HTTPRULE.oneofs_by_name['pattern'] 200 | _HTTPRULE.oneofs_by_name['pattern'].fields.append( 201 | _HTTPRULE.fields_by_name['post']) 202 | _HTTPRULE.fields_by_name['post'].containing_oneof = _HTTPRULE.oneofs_by_name['pattern'] 203 | _HTTPRULE.oneofs_by_name['pattern'].fields.append( 204 | _HTTPRULE.fields_by_name['delete']) 205 | _HTTPRULE.fields_by_name['delete'].containing_oneof = _HTTPRULE.oneofs_by_name['pattern'] 206 | _HTTPRULE.oneofs_by_name['pattern'].fields.append( 207 | _HTTPRULE.fields_by_name['patch']) 208 | _HTTPRULE.fields_by_name['patch'].containing_oneof = _HTTPRULE.oneofs_by_name['pattern'] 209 | _HTTPRULE.oneofs_by_name['pattern'].fields.append( 210 | _HTTPRULE.fields_by_name['custom']) 211 | _HTTPRULE.fields_by_name['custom'].containing_oneof = _HTTPRULE.oneofs_by_name['pattern'] 212 | DESCRIPTOR.message_types_by_name['Http'] = _HTTP 213 | DESCRIPTOR.message_types_by_name['HttpRule'] = _HTTPRULE 214 | DESCRIPTOR.message_types_by_name['CustomHttpPattern'] = _CUSTOMHTTPPATTERN 215 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 216 | 217 | Http = _reflection.GeneratedProtocolMessageType('Http', (_message.Message,), { 218 | 'DESCRIPTOR' : _HTTP, 219 | '__module__' : 'google.api.http_pb2' 220 | # @@protoc_insertion_point(class_scope:google.api.Http) 221 | }) 222 | _sym_db.RegisterMessage(Http) 223 | 224 | HttpRule = _reflection.GeneratedProtocolMessageType('HttpRule', (_message.Message,), { 225 | 'DESCRIPTOR' : _HTTPRULE, 226 | '__module__' : 'google.api.http_pb2' 227 | # @@protoc_insertion_point(class_scope:google.api.HttpRule) 228 | }) 229 | _sym_db.RegisterMessage(HttpRule) 230 | 231 | CustomHttpPattern = _reflection.GeneratedProtocolMessageType('CustomHttpPattern', (_message.Message,), { 232 | 'DESCRIPTOR' : _CUSTOMHTTPPATTERN, 233 | '__module__' : 'google.api.http_pb2' 234 | # @@protoc_insertion_point(class_scope:google.api.CustomHttpPattern) 235 | }) 236 | _sym_db.RegisterMessage(CustomHttpPattern) 237 | 238 | 239 | DESCRIPTOR._options = None 240 | # @@protoc_insertion_point(module_scope) 241 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/google/api/http_pb2_grpc.py: -------------------------------------------------------------------------------- 1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! 2 | """Client and server classes corresponding to protobuf-defined services.""" 3 | import grpc 4 | 5 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/google/rpc/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikhonp/yandex-speechkit-lib-python/3376c02ed42870c0ad741b52067b5c9941ec84b5/src/speechkit/_recognition/google/rpc/__init__.py -------------------------------------------------------------------------------- /src/speechkit/_recognition/google/rpc/status_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: google/rpc/status.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 15 | 16 | 17 | DESCRIPTOR = _descriptor.FileDescriptor( 18 | name='google/rpc/status.proto', 19 | package='google.rpc', 20 | syntax='proto3', 21 | serialized_options=b'\n\016com.google.rpcB\013StatusProtoP\001Z7google.golang.org/genproto/googleapis/rpc/status;status\242\002\003RPC', 22 | create_key=_descriptor._internal_create_key, 23 | serialized_pb=b'\n\x17google/rpc/status.proto\x12\ngoogle.rpc\x1a\x19google/protobuf/any.proto\"N\n\x06Status\x12\x0c\n\x04\x63ode\x18\x01 \x01(\x05\x12\x0f\n\x07message\x18\x02 \x01(\t\x12%\n\x07\x64\x65tails\x18\x03 \x03(\x0b\x32\x14.google.protobuf.AnyB^\n\x0e\x63om.google.rpcB\x0bStatusProtoP\x01Z7google.golang.org/genproto/googleapis/rpc/status;status\xa2\x02\x03RPCb\x06proto3' 24 | , 25 | dependencies=[google_dot_protobuf_dot_any__pb2.DESCRIPTOR,]) 26 | 27 | 28 | 29 | 30 | _STATUS = _descriptor.Descriptor( 31 | name='Status', 32 | full_name='google.rpc.Status', 33 | filename=None, 34 | file=DESCRIPTOR, 35 | containing_type=None, 36 | create_key=_descriptor._internal_create_key, 37 | fields=[ 38 | _descriptor.FieldDescriptor( 39 | name='code', full_name='google.rpc.Status.code', index=0, 40 | number=1, type=5, cpp_type=1, label=1, 41 | has_default_value=False, default_value=0, 42 | message_type=None, enum_type=None, containing_type=None, 43 | is_extension=False, extension_scope=None, 44 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 45 | _descriptor.FieldDescriptor( 46 | name='message', full_name='google.rpc.Status.message', index=1, 47 | number=2, type=9, cpp_type=9, label=1, 48 | has_default_value=False, default_value=b"".decode('utf-8'), 49 | message_type=None, enum_type=None, containing_type=None, 50 | is_extension=False, extension_scope=None, 51 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 52 | _descriptor.FieldDescriptor( 53 | name='details', full_name='google.rpc.Status.details', index=2, 54 | number=3, type=11, cpp_type=10, label=3, 55 | has_default_value=False, default_value=[], 56 | message_type=None, enum_type=None, containing_type=None, 57 | is_extension=False, extension_scope=None, 58 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 59 | ], 60 | extensions=[ 61 | ], 62 | nested_types=[], 63 | enum_types=[ 64 | ], 65 | serialized_options=None, 66 | is_extendable=False, 67 | syntax='proto3', 68 | extension_ranges=[], 69 | oneofs=[ 70 | ], 71 | serialized_start=66, 72 | serialized_end=144, 73 | ) 74 | 75 | _STATUS.fields_by_name['details'].message_type = google_dot_protobuf_dot_any__pb2._ANY 76 | DESCRIPTOR.message_types_by_name['Status'] = _STATUS 77 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 78 | 79 | Status = _reflection.GeneratedProtocolMessageType('Status', (_message.Message,), { 80 | 'DESCRIPTOR' : _STATUS, 81 | '__module__' : 'google.rpc.status_pb2' 82 | # @@protoc_insertion_point(class_scope:google.rpc.Status) 83 | }) 84 | _sym_db.RegisterMessage(Status) 85 | 86 | 87 | DESCRIPTOR._options = None 88 | # @@protoc_insertion_point(module_scope) 89 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/google/rpc/status_pb2_grpc.py: -------------------------------------------------------------------------------- 1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! 2 | """Client and server classes corresponding to protobuf-defined services.""" 3 | import grpc 4 | 5 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/streaming_recognition.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | import grpc 4 | 5 | import speechkit._recognition.yandex.cloud.ai.stt.v2.stt_service_pb2 as stt_service_pb2 6 | import speechkit._recognition.yandex.cloud.ai.stt.v2.stt_service_pb2_grpc as stt_service_pb2_grpc 7 | 8 | 9 | class DataStreamingRecognition: 10 | """ 11 | Data streaming mode allows you to simultaneously send audio for recognition and 12 | get recognition results over the same connection. 13 | 14 | Unlike other recognition methods, you can get intermediate results while speech 15 | is in progress. After a pause, the service returns final results and starts recognizing the next utterance. 16 | 17 | After receiving the message with the recognition settings, the service starts a recognition session. 18 | The following limitations apply to each session: 19 | 20 | 1. You can't send audio fragments too often or too rarely. The time between messages to the service should be 21 | approximately the same as the duration of the audio fragments you send, but no more than 5 seconds. 22 | For example, send 400 ms of audio for recognition every 400 ms. 23 | 24 | 2. Maximum duration of transmitted audio for the entire session: 5 minutes. 25 | 26 | 3. Maximum size of transmitted audio data: 10 MB. 27 | 28 | To use this type of recognition, you need to create function that yields bytes data 29 | 30 | :Example: 31 | 32 | >>> chunk_size = 4000 33 | >>> session = Session.from_jwt("jwt") 34 | >>> data_streaming_recognition = DataStreamingRecognition( 35 | ... session, 36 | ... language_code='ru-RU', 37 | ... audio_encoding='LINEAR16_PCM', 38 | ... session=8000, 39 | ... partial_results=False, 40 | ... single_utterance=True, 41 | ... ) 42 | ... 43 | >>> def gen_audio_from_file_function(): 44 | ... with open('/path/to/pcm_data/speech.pcm', 'rb') as f: 45 | ... data = f.read(chunk_size) 46 | ... while data != b'': 47 | ... yield data 48 | ... data = f.read(chunk_size) 49 | ... 50 | >>> for i in data_streaming_recognition.recognize(gen_audio_capture_function): 51 | ... print(i) # (['text'], final_flag, end_of_utterance_flag) 52 | ... 53 | 54 | Read more about streaming recognition in 55 | `Yandex streaming recognition docs `_ 56 | """ 57 | 58 | def __init__( 59 | self, session, language_code=None, model=None, profanity_filter=None, partial_results=None, 60 | single_utterance=None, audio_encoding=None, sample_rate_hertz=None, raw_results=None 61 | ): 62 | """ 63 | Initialize :py:class:`speechkit.DataStreamingRecognition` 64 | 65 | :param speechkit._auth.Session session: Session instance for auth 66 | 67 | :param string | None language_code: The language to use for recognition. Acceptable values: 68 | `ru-ru` (case-insensitive, used by default): Russian, `en-us` (case-insensitive): English, 69 | `tr-tr` (case-insensitive): Turkish. 70 | 71 | :param string | None model: The language model to be used for recognition. The closer the model is matched, 72 | the better the recognition result. You can only specify one model per request. Default value: `general`. 73 | 74 | :param boolean | None profanity_filter: The profanity filter. Acceptable values: 75 | `true`: Exclude profanity from recognition results, 76 | `false` (default): Do not exclude profanity from recognition results. 77 | 78 | :param boolean | None partial_results: The intermediate results filter. Acceptable values: 79 | `true`: Return intermediate results (part of the recognized utterance). 80 | For intermediate results, final is set to false, 81 | `false` (default): Return only the final results (the entire recognized utterance). 82 | 83 | :param boolean | None single_utterance: Flag that disables recognition after the first utterance. 84 | Acceptable values: `true`: Recognize only the first utterance, stop recognition, and wait for the user 85 | to disconnect, `false` (default): Continue recognition until the end of the session. 86 | 87 | :param string | None audio_encoding: The format of the submitted audio. Acceptable values: 88 | `LINEAR16_PCM`: LPCM with no WAV header, `OGG_OPUS` (default): OggOpus format. 89 | 90 | :param integer | None sample_rate_hertz: (int64) The sampling frequency of the submitted audio. 91 | Required if format is set to LINEAR16_PCM. Acceptable values: `48000` (default): Sampling rate of 48 kHz, 92 | `16000`: Sampling rate of 16 kHz, `8000`: Sampling rate of 8 kHz. 93 | 94 | :param boolean | None raw_results: Flag that indicates how to write numbers. `true`: In words. 95 | `false` (default): In figures. 96 | """ 97 | self._headers = session.streaming_recognition_header 98 | self._folder_id = session.folder_id 99 | 100 | specification_options = {k: v for k, v in { 101 | 'language_code': language_code, 'model': model, 'profanity_filter': profanity_filter, 102 | 'partial_results': partial_results, 'single_utterance': single_utterance, 103 | 'audio_encoding': audio_encoding, 'sample_rate_hertz': sample_rate_hertz, 'raw_results': raw_results 104 | }.items() if v is not None} 105 | 106 | config = {'specification': stt_service_pb2.RecognitionSpec(**specification_options)} 107 | if self._folder_id: 108 | config['folder_id'] = self._folder_id 109 | 110 | self._streaming_config = stt_service_pb2.RecognitionConfig(**config) 111 | 112 | def _gen(self, gen_audio_function, *args, **kwargs): 113 | """ 114 | Generate audio fragments. Pass args and kwargs to pass it into :py:meth:`gen_audio_function`. 115 | 116 | :param function gen_audio_function: Function generates audio data 117 | :return: Serialized data for sending 118 | """ 119 | try: 120 | if not callable(gen_audio_function): 121 | raise RuntimeError("`self._gen_audio_function` must be callable.") 122 | 123 | yield stt_service_pb2.StreamingRecognitionRequest(config=self._streaming_config) 124 | 125 | for data in gen_audio_function(*args, **kwargs): 126 | yield stt_service_pb2.StreamingRecognitionRequest(audio_content=data) 127 | 128 | except Exception as e: 129 | logging.error(e) 130 | raise e 131 | 132 | def recognize_raw(self, gen_audio_function, *args, **kwargs): 133 | """ 134 | Recognize streaming data, gen_audio_function must yield audio data with parameters given in init. 135 | Answer type read in `Yandex Docs `_. 136 | Pass args and kwargs to pass it into :py:meth:`gen_audio_function`. 137 | 138 | :param function gen_audio_function: Function generates audio data 139 | :return: Yields recognized data in raw format 140 | :rtype: speechkit._recognition.yandex.cloud.ai.stt.v2.stt_service_pb2.StreamingRecognitionResponse 141 | """ 142 | if not callable(gen_audio_function): 143 | raise RuntimeError("`gen_audio_function` must be callable.") 144 | 145 | cred = grpc.ssl_channel_credentials() 146 | channel = grpc.secure_channel('stt.api.cloud.yandex.net:443', cred) 147 | stub = stt_service_pb2_grpc.SttServiceStub(channel) 148 | 149 | it = stub.StreamingRecognize(self._gen(gen_audio_function, *args, **kwargs), metadata=(self._headers,)) 150 | 151 | for chunk in it: 152 | yield chunk 153 | 154 | def recognize(self, gen_audio_function, *args, **kwargs): 155 | """ 156 | Recognize streaming data, gen_audio_function must yield audio data with parameters given in init. 157 | Pass args and kwargs to pass it into :py:meth:`gen_audio_function`. 158 | 159 | :param function gen_audio_function: Function generates audio data 160 | :return: yields tuple, where first element is list of alternatives text, second final (boolean) flag, 161 | third endOfUtterance (boolean) flag, ex. (['text'], False, False) 162 | :rtype: tuple 163 | """ 164 | for item in self.recognize_raw(gen_audio_function, *args, **kwargs): 165 | alternatives = [i.text for i in item.chunks[0].alternatives] 166 | final = item.chunks[0].final 167 | end_of_utterance = item.chunks[0].end_of_utterance 168 | yield alternatives, final, end_of_utterance 169 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/sync_recognition.py: -------------------------------------------------------------------------------- 1 | import io 2 | import sys 3 | import uuid 4 | from pathlib import Path 5 | 6 | import boto3 7 | import requests 8 | 9 | from speechkit.exceptions import RequestError 10 | 11 | 12 | class ShortAudioRecognition: 13 | """ 14 | Short audio recognition ensures fast response time and is suitable for single-channel audio of small length. 15 | 16 | Audio requirements: 17 | 1. Maximum file size: 1 MB. 18 | 2. Maximum length: 30 seconds. 19 | 3. Maximum number of audio channels: 1. 20 | 21 | If your file is larger, longer, or has more audio channels, use :py:class:`speechkit.RecognitionLongAudio`. 22 | """ 23 | 24 | def __init__(self, session): 25 | """ 26 | Initialization :py:class:`speechkit.ShortAudioRecognition` 27 | 28 | :param speechkit.Session session: Session instance for auth 29 | """ 30 | self._headers = session.header 31 | self._folder_id = session.folder_id 32 | 33 | def recognize(self, data, **kwargs): 34 | """ 35 | Recognize text from BytesIO data given, which is audio 36 | 37 | :type data: io.BytesIO, bytes 38 | :param data: Data with audio samples to recognize 39 | 40 | :type lang: string 41 | :param lang: The language to use for recognition. Acceptable values: 42 | 43 | * `ru-RU` (by default) — Russian. 44 | 45 | * `en-US` — English. 46 | 47 | * `tr-TR` — Turkish. 48 | 49 | :type topic: string 50 | :param topic: The language model to be used for recognition. Default value: `general`. 51 | 52 | :type profanityFilter: boolean 53 | :param profanityFilter: This parameter controls the profanity filter in recognized speech. 54 | 55 | :type format: string 56 | :param format: The format of the submitted audio. Acceptable values: 57 | 58 | * `lpcm` — LPCM with no WAV _header. 59 | 60 | * `oggopus` (default) — OggOpus. 61 | 62 | :param string sampleRateHertz: The sampling frequency of the submitted audio. 63 | Used if format is set to lpcm. Acceptable values: 64 | 65 | * `48000` (default) — Sampling rate of 48 kHz. 66 | 67 | * `16000` — Sampling rate of 16 kHz. 68 | 69 | * `8000` — Sampling rate of 8 kHz. 70 | 71 | :param string folderId: ID of the folder that you have access to. Don't specify this field if 72 | you make a request on behalf of a service account. 73 | 74 | :return: The recognized text 75 | :rtype: string 76 | """ 77 | if not isinstance(data, (io.BytesIO, bytes)): 78 | raise ValueError("Data must be bytes io or bytes.") 79 | 80 | if 'lang' in kwargs: 81 | if not type(kwargs['lang']) is str: 82 | raise TypeError("__init__() kwargs['lang']: got {} but expected \ 83 | type is str".format(type(kwargs["lang"]).__name__)) 84 | 85 | if self._headers is None: 86 | raise RuntimeError("You must call `ShortAudioRecognition.__init__()` first.") 87 | 88 | if sys.getsizeof(data) > 1024 * 1024: 89 | raise ValueError("Maximum file size: 1 MB. Got {} bytes.".format(sys.getsizeof(data))) 90 | 91 | if kwargs.get('format') == 'lpcm': 92 | sample_rate_hertz = int(kwargs.get('sample_rate_hertz', '48000')) 93 | seconds_duration = (sys.getsizeof(data) * 8) / (sample_rate_hertz * 1 * 16) 94 | 95 | if seconds_duration > 30: 96 | raise ValueError( 97 | "Maximum length: 30 seconds. Maximum number of audio channels: 1. Calculated length - {}".format( 98 | seconds_duration)) 99 | 100 | params = {'folderId': self._folder_id} if self._folder_id else {} 101 | params.update(kwargs) 102 | url = 'https://stt.api.cloud.yandex.net/speech/v1/stt:recognize' 103 | answer = requests.post(url, params=params, data=data, headers=self._headers) 104 | 105 | if answer.ok: 106 | return answer.json().get('result') 107 | else: 108 | raise RequestError(answer.json()) 109 | 110 | 111 | class RecognitionLongAudio: 112 | """ 113 | Long audio fragment recognition can be used for multi-channel audio files up to 1 GB. 114 | To recognize long audio fragments, you need to execute 2 requests: 115 | 116 | * Send a file for recognition. 117 | 118 | * Get recognition results. 119 | 120 | :Example: 121 | 122 | >>> recognizeLongAudio = RecognitionLongAudio(session, '') 123 | >>> recognizeLongAudio.send_for_recognition('file/path') 124 | >>> if recognizeLongAudio.get_recognition_results(): 125 | ... data = recognizeLongAudio.get_data() 126 | ... 127 | >>> recognizeLongAudio.get_raw_text() 128 | ...'raw recognized text' 129 | """ 130 | 131 | def __init__(self, session, service_account_id, aws_bucket_name=None, 132 | aws_credentials_description='Default AWS credentials created by `speechkit` python SDK', 133 | aws_region_name='ru-central1', aws_access_key_id=None, aws_secret=None): 134 | """ 135 | Initialize :py:class:`speechkit.RecognitionLongAudio` 136 | 137 | :param speechkit.Session session: Session instance for auth 138 | :param string service_account_id: Yandex Cloud Service account ID 139 | :param string aws_bucket_name: Optional AWS bucket name 140 | :param string aws_credentials_description: AWS credentials description 141 | :param string aws_region_name: AWS region name 142 | :param string aws_access_key_id: Optional AWS access key. Can be got by `.get_aws_credentials`. 143 | If None will be generated automatically 144 | :param string aws_secret: Optional AWS secret. Can be got by `.get_aws_credentials`. 145 | If None will be generated automatically 146 | """ 147 | self._id = None 148 | self._answer_data = None 149 | self._aws_file_name = None 150 | 151 | self._headers = session.header 152 | if session.folder_id: 153 | raise ValueError("folder_id specify is not supported, use jwt.") 154 | if session.auth_method == session.API_KEY: 155 | raise ValueError("Only jwt method supported") 156 | 157 | if aws_access_key_id and aws_secret: 158 | self._s3 = self._init_aws( 159 | aws_access_key_id=aws_access_key_id, 160 | aws_secret_access_key=aws_secret, 161 | region_name=aws_region_name, 162 | ) 163 | else: 164 | access_key_id, secret = self.get_aws_credentials(session, service_account_id, aws_credentials_description) 165 | self._s3 = self._init_aws( 166 | aws_access_key_id=access_key_id, 167 | aws_secret_access_key=secret, 168 | region_name=aws_region_name, 169 | ) 170 | 171 | if aws_bucket_name: 172 | self._aws_bucket_name = aws_bucket_name 173 | else: 174 | self._aws_bucket_name = 'py_speechkit_' + str(uuid.uuid4()) 175 | self._s3.create_bucket(Bucket=self._aws_bucket_name) 176 | 177 | @staticmethod 178 | def _init_aws(**kwargs): 179 | """Get s3 session 180 | 181 | :param string aws_access_key_id: The access key to use when creating the client. This is entirely optional, 182 | and if not provided, the credentials configured for the session will automatically be used. You only need to 183 | provide this argument if you want to override the credentials used for this specific client. 184 | 185 | :param string aws_secret_access_key: The secret key to use when creating the client. Same semantics as 186 | aws_access_key_id above. 187 | 188 | :param string region_name: The name of the region associated with the client. 189 | A client is associated with a single region. 190 | """ 191 | 192 | session = boto3.session.Session() 193 | return session.client( 194 | service_name='s3', 195 | endpoint_url='https://storage.yandexcloud.net', 196 | **kwargs 197 | ) 198 | 199 | @staticmethod 200 | def get_aws_credentials(session, service_account_id, 201 | aws_credentials_description='Default AWS credentials created by `speechkit` python SDK'): 202 | """ 203 | Get AWS credentials from yandex cloud 204 | 205 | :type session: speechkit.Session 206 | :param session: Session instance for auth 207 | 208 | :type service_account_id: string 209 | :param service_account_id: Yandex Cloud Service account ID 210 | 211 | :type aws_credentials_description: string 212 | :param aws_credentials_description: AWS credentials description 213 | 214 | :return: tuple with strings (access_key_id, secret) 215 | """ 216 | 217 | if len(aws_credentials_description) > 256: 218 | raise ValueError("The maximum `description` string length in characters is 256.") 219 | 220 | url_aws_credentials = 'https://iam.api.cloud.yandex.net/iam/aws-compatibility/v1/accessKeys' 221 | data_aws_credentials = {'description': aws_credentials_description, 'serviceAccountId': service_account_id} 222 | answer = requests.post(url_aws_credentials, headers=session.header, json=data_aws_credentials) 223 | 224 | if not answer.ok: 225 | raise RequestError(answer.json()) 226 | 227 | answer = answer.json() 228 | access_key_id = answer.get('accessKey', {}).get('keyId') 229 | secret = answer.get('secret') 230 | return access_key_id, secret 231 | 232 | def _aws_upload_file(self, file_path, baket_name, aws_file_name): 233 | """ 234 | Upload a file to object storage 235 | 236 | :type file_path: string 237 | :param file_path: Path to input file 238 | 239 | :type baket_name: string 240 | :param baket_name: 241 | 242 | :type aws_file_name: string 243 | :param aws_file_name: Name of file in object storage 244 | """ 245 | 246 | self._s3.upload_file(file_path, baket_name, aws_file_name) 247 | 248 | def _create_presigned_url(self, bucket_name, aws_file_name, 249 | expiration=3600): 250 | """Generate a presigned URL to share an S3 object 251 | 252 | :type bucket_name: string 253 | 254 | :type aws_file_name: string 255 | :param aws_file_name: Name of file in object storage 256 | 257 | :type expiration: integer 258 | :param expiration: Time in seconds for the presigned URL to remain valid 259 | 260 | :return: Resigned URL as string. 261 | :rtype: string 262 | """ 263 | 264 | return self._s3.generate_presigned_url( 265 | 'get_object', 266 | Params={'Bucket': bucket_name, 'Key': aws_file_name}, 267 | ExpiresIn=expiration 268 | ) 269 | 270 | def _delete_object(self, bucket_name, aws_file_name): 271 | """Delete object in bucket 272 | 273 | :param string aws_file_name: Name of file in object storage 274 | :type bucket_name: string 275 | """ 276 | return self._s3.delete_objects( 277 | Bucket=bucket_name, Delete={'Objects': [{'Key': aws_file_name}]}) 278 | 279 | def send_for_recognition(self, file_path, **kwargs): 280 | """ 281 | Send a file for recognition 282 | 283 | :param string file_path: Path to input file 284 | 285 | :param string folder_id: ID of the folder that you have access to. Don't specify this field if 286 | you make a request on behalf of a service account. 287 | 288 | :param string languageCode: The language that recognition will be performed for. 289 | Only Russian is currently supported (`ru-RU`). 290 | 291 | :param string model: The language model to be used for recognition. 292 | Default value: `general`. 293 | 294 | :param boolean profanityFilter: The profanity filters. 295 | 296 | :param string audioEncoding: The format of the submitted audio. 297 | Acceptable values: 298 | 299 | * `LINEAR16_PCM`: LPCM with no WAV _header. 300 | 301 | * `OGG_OPUS` (default): OggOpus format. 302 | 303 | :param integer sampleRateHertz: The sampling frequency of the submitted audio. 304 | Required if format is set to LINEAR16_PCM. Acceptable values: 305 | 306 | * `48000` (default): Sampling rate of 48 kHz. 307 | 308 | * `16000`: Sampling rate of 16 kHz. 309 | 310 | * `8000`: Sampling rate of 8 kHz. 311 | 312 | :param integer audioChannelCount: The number of channels in LPCM files. 313 | By default, `1`. Don't use this field for OggOpus files. 314 | 315 | :param boolean rawResults: Flag that indicates how to write numbers. 316 | `true`: In words. `false` (default): In figures. 317 | 318 | :rtype: None 319 | """ 320 | self._aws_file_name = Path(file_path).name + str(uuid.uuid4()) 321 | self._aws_upload_file(file_path, self._aws_bucket_name, self._aws_file_name) 322 | aws_presigned_url = self._create_presigned_url(self._aws_bucket_name, self._aws_file_name) 323 | 324 | url = "https://transcribe.api.cloud.yandex.net/" \ 325 | "speech/stt/v2/longRunningRecognize" 326 | 327 | data = { 328 | 329 | "config": { 330 | "specification": { 331 | **kwargs 332 | } 333 | }, 334 | "audio": { 335 | "uri": aws_presigned_url 336 | } 337 | } 338 | answer = requests.post(url, headers=self._headers, json=data) 339 | if answer.ok: 340 | self._id = answer.json().get('id') 341 | else: 342 | raise RequestError(answer.json()) 343 | 344 | def get_recognition_results(self): 345 | """ 346 | Monitor the recognition results using the received ID. The number of result monitoring requests is limited, 347 | so consider the recognition speed: it takes about 10 seconds to recognize 1 minute of single-channel audio. 348 | 349 | :return: State of recognition is done or not 350 | :rtype: boolean 351 | """ 352 | if self._id is None: 353 | raise RuntimeError("You must send for recognition first.") 354 | 355 | url = "https://operation.api.cloud.yandex.net/operations/{id}".format(id=self._id) 356 | self._answer_data = requests.get(url, headers=self._headers) 357 | if self._answer_data.ok: 358 | self._answer_data = self._answer_data.json() 359 | done = self._answer_data.get('done') 360 | if done: 361 | self._delete_object(self._aws_bucket_name, self._aws_file_name) 362 | 363 | return done 364 | else: 365 | raise RequestError(self._answer_data.json()) 366 | 367 | def get_data(self): 368 | """ 369 | Get the response. 370 | Use :py:meth:`speechkit.RecognitionLongAudio.get_recognition_results` first to store _answer_data 371 | 372 | Contain a list of recognition results (`chunks[]`). 373 | 374 | :return: `None` if text not found ot Each result in the chunks[] list contains the following fields: 375 | 376 | * `alternatives[]`: List of recognized text alternatives. Each alternative contains the following fields: 377 | 378 | * `words[]`: List of recognized words: 379 | 380 | * `startTime`: Time stamp of the beginning of the word in the recording. An error of 1-2 seconds 381 | is possible. 382 | 383 | * `endTime`: Time stamp of the end of the word. An error of 1-2 seconds is possible. 384 | 385 | * `word`: Recognized word. Recognized numbers are written in words (for example, twelve rather 386 | than 12). 387 | 388 | * `confidence`: This field currently isn't supported. Don't use it. 389 | 390 | * `text`: Full recognized text. By default, numbers are written in figures. To recognition 391 | the entire text in words, specify true in the raw_results field. 392 | 393 | * `confidence`: This field currently isn't supported. Don't use it. 394 | 395 | * `channelTag`: Audio channel that recognition was performed for. 396 | :rtype: list | None 397 | """ 398 | 399 | if self._answer_data is None: 400 | raise ValueError("You must call `RecognitionLongAudio.get_recognition_results` first") 401 | return self._answer_data.get('response', {}).get('chunks', []) 402 | 403 | def get_raw_text(self): 404 | """ 405 | Get raw text from _answer_data data 406 | 407 | :return: Text 408 | :rtype: string 409 | """ 410 | if self._answer_data is None: 411 | raise ValueError("You must call 'get_recognition_results' first") 412 | 413 | text = '' 414 | for chunk in self._answer_data.get('response', {}).get('chunks', []): 415 | if chunk['channelTag'] == '1': 416 | text += f"{chunk['alternatives'][0]['text'].strip()} " 417 | return text 418 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/yandex/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikhonp/yandex-speechkit-lib-python/3376c02ed42870c0ad741b52067b5c9941ec84b5/src/speechkit/_recognition/yandex/__init__.py -------------------------------------------------------------------------------- /src/speechkit/_recognition/yandex/cloud/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikhonp/yandex-speechkit-lib-python/3376c02ed42870c0ad741b52067b5c9941ec84b5/src/speechkit/_recognition/yandex/cloud/__init__.py -------------------------------------------------------------------------------- /src/speechkit/_recognition/yandex/cloud/ai/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikhonp/yandex-speechkit-lib-python/3376c02ed42870c0ad741b52067b5c9941ec84b5/src/speechkit/_recognition/yandex/cloud/ai/__init__.py -------------------------------------------------------------------------------- /src/speechkit/_recognition/yandex/cloud/ai/stt/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikhonp/yandex-speechkit-lib-python/3376c02ed42870c0ad741b52067b5c9941ec84b5/src/speechkit/_recognition/yandex/cloud/ai/stt/__init__.py -------------------------------------------------------------------------------- /src/speechkit/_recognition/yandex/cloud/ai/stt/v2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikhonp/yandex-speechkit-lib-python/3376c02ed42870c0ad741b52067b5c9941ec84b5/src/speechkit/_recognition/yandex/cloud/ai/stt/v2/__init__.py -------------------------------------------------------------------------------- /src/speechkit/_recognition/yandex/cloud/ai/stt/v2/stt_service_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: yandex/cloud/ai/stt/v2/stt_service.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from speechkit._recognition.google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 15 | from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 16 | from speechkit._recognition.yandex.cloud.api import operation_pb2 as yandex_dot_cloud_dot_api_dot_operation__pb2 17 | from speechkit._recognition.yandex.cloud.operation import operation_pb2 as yandex_dot_cloud_dot_operation_dot_operation__pb2 18 | 19 | 20 | DESCRIPTOR = _descriptor.FileDescriptor( 21 | name='yandex/cloud/ai/stt/v2/stt_service.proto', 22 | package='yandex.cloud.ai.stt.v2', 23 | syntax='proto3', 24 | serialized_options=b'\n\032yandex.cloud.api.ai.stt.v2Z>github.com/yandex-cloud/go-genproto/yandex/cloud/ai/stt/v2;stt', 25 | create_key=_descriptor._internal_create_key, 26 | serialized_pb=b'\n(yandex/cloud/ai/stt/v2/stt_service.proto\x12\x16yandex.cloud.ai.stt.v2\x1a\x1cgoogle/api/annotations.proto\x1a\x1egoogle/protobuf/duration.proto\x1a yandex/cloud/api/operation.proto\x1a&yandex/cloud/operation/operation.proto\"\x93\x01\n\x1dLongRunningRecognitionRequest\x12\x39\n\x06\x63onfig\x18\x01 \x01(\x0b\x32).yandex.cloud.ai.stt.v2.RecognitionConfig\x12\x37\n\x05\x61udio\x18\x02 \x01(\x0b\x32(.yandex.cloud.ai.stt.v2.RecognitionAudio\"a\n\x1eLongRunningRecognitionResponse\x12?\n\x06\x63hunks\x18\x01 \x03(\x0b\x32/.yandex.cloud.ai.stt.v2.SpeechRecognitionResult\"\x88\x01\n\x1bStreamingRecognitionRequest\x12;\n\x06\x63onfig\x18\x01 \x01(\x0b\x32).yandex.cloud.ai.stt.v2.RecognitionConfigH\x00\x12\x17\n\raudio_content\x18\x02 \x01(\x0cH\x00\x42\x13\n\x11streaming_request\"}\n\x1cStreamingRecognitionResponse\x12>\n\x06\x63hunks\x18\x01 \x03(\x0b\x32..yandex.cloud.ai.stt.v2.SpeechRecognitionChunkJ\x04\x08\x02\x10\x03R\x17\x65nd_of_single_utterance\"D\n\x10RecognitionAudio\x12\x11\n\x07\x63ontent\x18\x01 \x01(\x0cH\x00\x12\r\n\x03uri\x18\x02 \x01(\tH\x00\x42\x0e\n\x0c\x61udio_source\"f\n\x11RecognitionConfig\x12>\n\rspecification\x18\x01 \x01(\x0b\x32\'.yandex.cloud.ai.stt.v2.RecognitionSpec\x12\x11\n\tfolder_id\x18\x02 \x01(\t\"\xf1\x02\n\x0fRecognitionSpec\x12M\n\x0e\x61udio_encoding\x18\x01 \x01(\x0e\x32\x35.yandex.cloud.ai.stt.v2.RecognitionSpec.AudioEncoding\x12\x19\n\x11sample_rate_hertz\x18\x02 \x01(\x03\x12\x15\n\rlanguage_code\x18\x03 \x01(\t\x12\x18\n\x10profanity_filter\x18\x04 \x01(\x08\x12\r\n\x05model\x18\x05 \x01(\t\x12\x17\n\x0fpartial_results\x18\x07 \x01(\x08\x12\x18\n\x10single_utterance\x18\x08 \x01(\x08\x12\x1b\n\x13\x61udio_channel_count\x18\t \x01(\x03\x12\x13\n\x0braw_results\x18\n \x01(\x08\"O\n\rAudioEncoding\x12\x1e\n\x1a\x41UDIO_ENCODING_UNSPECIFIED\x10\x00\x12\x10\n\x0cLINEAR16_PCM\x10\x01\x12\x0c\n\x08OGG_OPUS\x10\x02\"\x8d\x01\n\x16SpeechRecognitionChunk\x12J\n\x0c\x61lternatives\x18\x01 \x03(\x0b\x32\x34.yandex.cloud.ai.stt.v2.SpeechRecognitionAlternative\x12\r\n\x05\x66inal\x18\x02 \x01(\x08\x12\x18\n\x10\x65nd_of_utterance\x18\x03 \x01(\x08\"z\n\x17SpeechRecognitionResult\x12J\n\x0c\x61lternatives\x18\x01 \x03(\x0b\x32\x34.yandex.cloud.ai.stt.v2.SpeechRecognitionAlternative\x12\x13\n\x0b\x63hannel_tag\x18\x02 \x01(\x03\"q\n\x1cSpeechRecognitionAlternative\x12\x0c\n\x04text\x18\x01 \x01(\t\x12\x12\n\nconfidence\x18\x02 \x01(\x02\x12/\n\x05words\x18\x03 \x03(\x0b\x32 .yandex.cloud.ai.stt.v2.WordInfo\"\x88\x01\n\x08WordInfo\x12-\n\nstart_time\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12+\n\x08\x65nd_time\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0c\n\x04word\x18\x03 \x01(\t\x12\x12\n\nconfidence\x18\x04 \x01(\x02\x32\xdb\x02\n\nSttService\x12\xc4\x01\n\x14LongRunningRecognize\x12\x35.yandex.cloud.ai.stt.v2.LongRunningRecognitionRequest\x1a!.yandex.cloud.operation.Operation\"R\x82\xd3\xe4\x93\x02(\"#/speech/stt/v2/longRunningRecognize:\x01*\xb2\xd2* \x12\x1eLongRunningRecognitionResponse\x12\x85\x01\n\x12StreamingRecognize\x12\x33.yandex.cloud.ai.stt.v2.StreamingRecognitionRequest\x1a\x34.yandex.cloud.ai.stt.v2.StreamingRecognitionResponse\"\x00(\x01\x30\x01\x42\\\n\x1ayandex.cloud.api.ai.stt.v2Z>github.com/yandex-cloud/go-genproto/yandex/cloud/ai/stt/v2;sttb\x06proto3' 27 | , 28 | dependencies=[google_dot_api_dot_annotations__pb2.DESCRIPTOR,google_dot_protobuf_dot_duration__pb2.DESCRIPTOR,yandex_dot_cloud_dot_api_dot_operation__pb2.DESCRIPTOR,yandex_dot_cloud_dot_operation_dot_operation__pb2.DESCRIPTOR,]) 29 | 30 | 31 | 32 | _RECOGNITIONSPEC_AUDIOENCODING = _descriptor.EnumDescriptor( 33 | name='AudioEncoding', 34 | full_name='yandex.cloud.ai.stt.v2.RecognitionSpec.AudioEncoding', 35 | filename=None, 36 | file=DESCRIPTOR, 37 | create_key=_descriptor._internal_create_key, 38 | values=[ 39 | _descriptor.EnumValueDescriptor( 40 | name='AUDIO_ENCODING_UNSPECIFIED', index=0, number=0, 41 | serialized_options=None, 42 | type=None, 43 | create_key=_descriptor._internal_create_key), 44 | _descriptor.EnumValueDescriptor( 45 | name='LINEAR16_PCM', index=1, number=1, 46 | serialized_options=None, 47 | type=None, 48 | create_key=_descriptor._internal_create_key), 49 | _descriptor.EnumValueDescriptor( 50 | name='OGG_OPUS', index=2, number=2, 51 | serialized_options=None, 52 | type=None, 53 | create_key=_descriptor._internal_create_key), 54 | ], 55 | containing_type=None, 56 | serialized_options=None, 57 | serialized_start=1184, 58 | serialized_end=1263, 59 | ) 60 | _sym_db.RegisterEnumDescriptor(_RECOGNITIONSPEC_AUDIOENCODING) 61 | 62 | 63 | _LONGRUNNINGRECOGNITIONREQUEST = _descriptor.Descriptor( 64 | name='LongRunningRecognitionRequest', 65 | full_name='yandex.cloud.ai.stt.v2.LongRunningRecognitionRequest', 66 | filename=None, 67 | file=DESCRIPTOR, 68 | containing_type=None, 69 | create_key=_descriptor._internal_create_key, 70 | fields=[ 71 | _descriptor.FieldDescriptor( 72 | name='config', full_name='yandex.cloud.ai.stt.v2.LongRunningRecognitionRequest.config', index=0, 73 | number=1, type=11, cpp_type=10, label=1, 74 | has_default_value=False, default_value=None, 75 | message_type=None, enum_type=None, containing_type=None, 76 | is_extension=False, extension_scope=None, 77 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 78 | _descriptor.FieldDescriptor( 79 | name='audio', full_name='yandex.cloud.ai.stt.v2.LongRunningRecognitionRequest.audio', index=1, 80 | number=2, type=11, cpp_type=10, label=1, 81 | has_default_value=False, default_value=None, 82 | message_type=None, enum_type=None, containing_type=None, 83 | is_extension=False, extension_scope=None, 84 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 85 | ], 86 | extensions=[ 87 | ], 88 | nested_types=[], 89 | enum_types=[ 90 | ], 91 | serialized_options=None, 92 | is_extendable=False, 93 | syntax='proto3', 94 | extension_ranges=[], 95 | oneofs=[ 96 | ], 97 | serialized_start=205, 98 | serialized_end=352, 99 | ) 100 | 101 | 102 | _LONGRUNNINGRECOGNITIONRESPONSE = _descriptor.Descriptor( 103 | name='LongRunningRecognitionResponse', 104 | full_name='yandex.cloud.ai.stt.v2.LongRunningRecognitionResponse', 105 | filename=None, 106 | file=DESCRIPTOR, 107 | containing_type=None, 108 | create_key=_descriptor._internal_create_key, 109 | fields=[ 110 | _descriptor.FieldDescriptor( 111 | name='chunks', full_name='yandex.cloud.ai.stt.v2.LongRunningRecognitionResponse.chunks', index=0, 112 | number=1, type=11, cpp_type=10, label=3, 113 | has_default_value=False, default_value=[], 114 | message_type=None, enum_type=None, containing_type=None, 115 | is_extension=False, extension_scope=None, 116 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 117 | ], 118 | extensions=[ 119 | ], 120 | nested_types=[], 121 | enum_types=[ 122 | ], 123 | serialized_options=None, 124 | is_extendable=False, 125 | syntax='proto3', 126 | extension_ranges=[], 127 | oneofs=[ 128 | ], 129 | serialized_start=354, 130 | serialized_end=451, 131 | ) 132 | 133 | 134 | _STREAMINGRECOGNITIONREQUEST = _descriptor.Descriptor( 135 | name='StreamingRecognitionRequest', 136 | full_name='yandex.cloud.ai.stt.v2.StreamingRecognitionRequest', 137 | filename=None, 138 | file=DESCRIPTOR, 139 | containing_type=None, 140 | create_key=_descriptor._internal_create_key, 141 | fields=[ 142 | _descriptor.FieldDescriptor( 143 | name='config', full_name='yandex.cloud.ai.stt.v2.StreamingRecognitionRequest.config', index=0, 144 | number=1, type=11, cpp_type=10, label=1, 145 | has_default_value=False, default_value=None, 146 | message_type=None, enum_type=None, containing_type=None, 147 | is_extension=False, extension_scope=None, 148 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 149 | _descriptor.FieldDescriptor( 150 | name='audio_content', full_name='yandex.cloud.ai.stt.v2.StreamingRecognitionRequest.audio_content', index=1, 151 | number=2, type=12, cpp_type=9, label=1, 152 | has_default_value=False, default_value=b"", 153 | message_type=None, enum_type=None, containing_type=None, 154 | is_extension=False, extension_scope=None, 155 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 156 | ], 157 | extensions=[ 158 | ], 159 | nested_types=[], 160 | enum_types=[ 161 | ], 162 | serialized_options=None, 163 | is_extendable=False, 164 | syntax='proto3', 165 | extension_ranges=[], 166 | oneofs=[ 167 | _descriptor.OneofDescriptor( 168 | name='streaming_request', full_name='yandex.cloud.ai.stt.v2.StreamingRecognitionRequest.streaming_request', 169 | index=0, containing_type=None, 170 | create_key=_descriptor._internal_create_key, 171 | fields=[]), 172 | ], 173 | serialized_start=454, 174 | serialized_end=590, 175 | ) 176 | 177 | 178 | _STREAMINGRECOGNITIONRESPONSE = _descriptor.Descriptor( 179 | name='StreamingRecognitionResponse', 180 | full_name='yandex.cloud.ai.stt.v2.StreamingRecognitionResponse', 181 | filename=None, 182 | file=DESCRIPTOR, 183 | containing_type=None, 184 | create_key=_descriptor._internal_create_key, 185 | fields=[ 186 | _descriptor.FieldDescriptor( 187 | name='chunks', full_name='yandex.cloud.ai.stt.v2.StreamingRecognitionResponse.chunks', index=0, 188 | number=1, type=11, cpp_type=10, label=3, 189 | has_default_value=False, default_value=[], 190 | message_type=None, enum_type=None, containing_type=None, 191 | is_extension=False, extension_scope=None, 192 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 193 | ], 194 | extensions=[ 195 | ], 196 | nested_types=[], 197 | enum_types=[ 198 | ], 199 | serialized_options=None, 200 | is_extendable=False, 201 | syntax='proto3', 202 | extension_ranges=[], 203 | oneofs=[ 204 | ], 205 | serialized_start=592, 206 | serialized_end=717, 207 | ) 208 | 209 | 210 | _RECOGNITIONAUDIO = _descriptor.Descriptor( 211 | name='RecognitionAudio', 212 | full_name='yandex.cloud.ai.stt.v2.RecognitionAudio', 213 | filename=None, 214 | file=DESCRIPTOR, 215 | containing_type=None, 216 | create_key=_descriptor._internal_create_key, 217 | fields=[ 218 | _descriptor.FieldDescriptor( 219 | name='content', full_name='yandex.cloud.ai.stt.v2.RecognitionAudio.content', index=0, 220 | number=1, type=12, cpp_type=9, label=1, 221 | has_default_value=False, default_value=b"", 222 | message_type=None, enum_type=None, containing_type=None, 223 | is_extension=False, extension_scope=None, 224 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 225 | _descriptor.FieldDescriptor( 226 | name='uri', full_name='yandex.cloud.ai.stt.v2.RecognitionAudio.uri', index=1, 227 | number=2, type=9, cpp_type=9, label=1, 228 | has_default_value=False, default_value=b"".decode('utf-8'), 229 | message_type=None, enum_type=None, containing_type=None, 230 | is_extension=False, extension_scope=None, 231 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 232 | ], 233 | extensions=[ 234 | ], 235 | nested_types=[], 236 | enum_types=[ 237 | ], 238 | serialized_options=None, 239 | is_extendable=False, 240 | syntax='proto3', 241 | extension_ranges=[], 242 | oneofs=[ 243 | _descriptor.OneofDescriptor( 244 | name='audio_source', full_name='yandex.cloud.ai.stt.v2.RecognitionAudio.audio_source', 245 | index=0, containing_type=None, 246 | create_key=_descriptor._internal_create_key, 247 | fields=[]), 248 | ], 249 | serialized_start=719, 250 | serialized_end=787, 251 | ) 252 | 253 | 254 | _RECOGNITIONCONFIG = _descriptor.Descriptor( 255 | name='RecognitionConfig', 256 | full_name='yandex.cloud.ai.stt.v2.RecognitionConfig', 257 | filename=None, 258 | file=DESCRIPTOR, 259 | containing_type=None, 260 | create_key=_descriptor._internal_create_key, 261 | fields=[ 262 | _descriptor.FieldDescriptor( 263 | name='specification', full_name='yandex.cloud.ai.stt.v2.RecognitionConfig.specification', index=0, 264 | number=1, type=11, cpp_type=10, label=1, 265 | has_default_value=False, default_value=None, 266 | message_type=None, enum_type=None, containing_type=None, 267 | is_extension=False, extension_scope=None, 268 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 269 | _descriptor.FieldDescriptor( 270 | name='folder_id', full_name='yandex.cloud.ai.stt.v2.RecognitionConfig.folder_id', index=1, 271 | number=2, type=9, cpp_type=9, label=1, 272 | has_default_value=False, default_value=b"".decode('utf-8'), 273 | message_type=None, enum_type=None, containing_type=None, 274 | is_extension=False, extension_scope=None, 275 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 276 | ], 277 | extensions=[ 278 | ], 279 | nested_types=[], 280 | enum_types=[ 281 | ], 282 | serialized_options=None, 283 | is_extendable=False, 284 | syntax='proto3', 285 | extension_ranges=[], 286 | oneofs=[ 287 | ], 288 | serialized_start=789, 289 | serialized_end=891, 290 | ) 291 | 292 | 293 | _RECOGNITIONSPEC = _descriptor.Descriptor( 294 | name='RecognitionSpec', 295 | full_name='yandex.cloud.ai.stt.v2.RecognitionSpec', 296 | filename=None, 297 | file=DESCRIPTOR, 298 | containing_type=None, 299 | create_key=_descriptor._internal_create_key, 300 | fields=[ 301 | _descriptor.FieldDescriptor( 302 | name='audio_encoding', full_name='yandex.cloud.ai.stt.v2.RecognitionSpec.audio_encoding', index=0, 303 | number=1, type=14, cpp_type=8, label=1, 304 | has_default_value=False, default_value=0, 305 | message_type=None, enum_type=None, containing_type=None, 306 | is_extension=False, extension_scope=None, 307 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 308 | _descriptor.FieldDescriptor( 309 | name='sample_rate_hertz', full_name='yandex.cloud.ai.stt.v2.RecognitionSpec.sample_rate_hertz', index=1, 310 | number=2, type=3, cpp_type=2, label=1, 311 | has_default_value=False, default_value=0, 312 | message_type=None, enum_type=None, containing_type=None, 313 | is_extension=False, extension_scope=None, 314 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 315 | _descriptor.FieldDescriptor( 316 | name='language_code', full_name='yandex.cloud.ai.stt.v2.RecognitionSpec.language_code', index=2, 317 | number=3, type=9, cpp_type=9, label=1, 318 | has_default_value=False, default_value=b"".decode('utf-8'), 319 | message_type=None, enum_type=None, containing_type=None, 320 | is_extension=False, extension_scope=None, 321 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 322 | _descriptor.FieldDescriptor( 323 | name='profanity_filter', full_name='yandex.cloud.ai.stt.v2.RecognitionSpec.profanity_filter', index=3, 324 | number=4, type=8, cpp_type=7, label=1, 325 | has_default_value=False, default_value=False, 326 | message_type=None, enum_type=None, containing_type=None, 327 | is_extension=False, extension_scope=None, 328 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 329 | _descriptor.FieldDescriptor( 330 | name='model', full_name='yandex.cloud.ai.stt.v2.RecognitionSpec.model', index=4, 331 | number=5, type=9, cpp_type=9, label=1, 332 | has_default_value=False, default_value=b"".decode('utf-8'), 333 | message_type=None, enum_type=None, containing_type=None, 334 | is_extension=False, extension_scope=None, 335 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 336 | _descriptor.FieldDescriptor( 337 | name='partial_results', full_name='yandex.cloud.ai.stt.v2.RecognitionSpec.partial_results', index=5, 338 | number=7, type=8, cpp_type=7, label=1, 339 | has_default_value=False, default_value=False, 340 | message_type=None, enum_type=None, containing_type=None, 341 | is_extension=False, extension_scope=None, 342 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 343 | _descriptor.FieldDescriptor( 344 | name='single_utterance', full_name='yandex.cloud.ai.stt.v2.RecognitionSpec.single_utterance', index=6, 345 | number=8, type=8, cpp_type=7, label=1, 346 | has_default_value=False, default_value=False, 347 | message_type=None, enum_type=None, containing_type=None, 348 | is_extension=False, extension_scope=None, 349 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 350 | _descriptor.FieldDescriptor( 351 | name='audio_channel_count', full_name='yandex.cloud.ai.stt.v2.RecognitionSpec.audio_channel_count', index=7, 352 | number=9, type=3, cpp_type=2, label=1, 353 | has_default_value=False, default_value=0, 354 | message_type=None, enum_type=None, containing_type=None, 355 | is_extension=False, extension_scope=None, 356 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 357 | _descriptor.FieldDescriptor( 358 | name='raw_results', full_name='yandex.cloud.ai.stt.v2.RecognitionSpec.raw_results', index=8, 359 | number=10, type=8, cpp_type=7, label=1, 360 | has_default_value=False, default_value=False, 361 | message_type=None, enum_type=None, containing_type=None, 362 | is_extension=False, extension_scope=None, 363 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 364 | ], 365 | extensions=[ 366 | ], 367 | nested_types=[], 368 | enum_types=[ 369 | _RECOGNITIONSPEC_AUDIOENCODING, 370 | ], 371 | serialized_options=None, 372 | is_extendable=False, 373 | syntax='proto3', 374 | extension_ranges=[], 375 | oneofs=[ 376 | ], 377 | serialized_start=894, 378 | serialized_end=1263, 379 | ) 380 | 381 | 382 | _SPEECHRECOGNITIONCHUNK = _descriptor.Descriptor( 383 | name='SpeechRecognitionChunk', 384 | full_name='yandex.cloud.ai.stt.v2.SpeechRecognitionChunk', 385 | filename=None, 386 | file=DESCRIPTOR, 387 | containing_type=None, 388 | create_key=_descriptor._internal_create_key, 389 | fields=[ 390 | _descriptor.FieldDescriptor( 391 | name='alternatives', full_name='yandex.cloud.ai.stt.v2.SpeechRecognitionChunk.alternatives', index=0, 392 | number=1, type=11, cpp_type=10, label=3, 393 | has_default_value=False, default_value=[], 394 | message_type=None, enum_type=None, containing_type=None, 395 | is_extension=False, extension_scope=None, 396 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 397 | _descriptor.FieldDescriptor( 398 | name='final', full_name='yandex.cloud.ai.stt.v2.SpeechRecognitionChunk.final', index=1, 399 | number=2, type=8, cpp_type=7, label=1, 400 | has_default_value=False, default_value=False, 401 | message_type=None, enum_type=None, containing_type=None, 402 | is_extension=False, extension_scope=None, 403 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 404 | _descriptor.FieldDescriptor( 405 | name='end_of_utterance', full_name='yandex.cloud.ai.stt.v2.SpeechRecognitionChunk.end_of_utterance', index=2, 406 | number=3, type=8, cpp_type=7, label=1, 407 | has_default_value=False, default_value=False, 408 | message_type=None, enum_type=None, containing_type=None, 409 | is_extension=False, extension_scope=None, 410 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 411 | ], 412 | extensions=[ 413 | ], 414 | nested_types=[], 415 | enum_types=[ 416 | ], 417 | serialized_options=None, 418 | is_extendable=False, 419 | syntax='proto3', 420 | extension_ranges=[], 421 | oneofs=[ 422 | ], 423 | serialized_start=1266, 424 | serialized_end=1407, 425 | ) 426 | 427 | 428 | _SPEECHRECOGNITIONRESULT = _descriptor.Descriptor( 429 | name='SpeechRecognitionResult', 430 | full_name='yandex.cloud.ai.stt.v2.SpeechRecognitionResult', 431 | filename=None, 432 | file=DESCRIPTOR, 433 | containing_type=None, 434 | create_key=_descriptor._internal_create_key, 435 | fields=[ 436 | _descriptor.FieldDescriptor( 437 | name='alternatives', full_name='yandex.cloud.ai.stt.v2.SpeechRecognitionResult.alternatives', index=0, 438 | number=1, type=11, cpp_type=10, label=3, 439 | has_default_value=False, default_value=[], 440 | message_type=None, enum_type=None, containing_type=None, 441 | is_extension=False, extension_scope=None, 442 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 443 | _descriptor.FieldDescriptor( 444 | name='channel_tag', full_name='yandex.cloud.ai.stt.v2.SpeechRecognitionResult.channel_tag', index=1, 445 | number=2, type=3, cpp_type=2, label=1, 446 | has_default_value=False, default_value=0, 447 | message_type=None, enum_type=None, containing_type=None, 448 | is_extension=False, extension_scope=None, 449 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 450 | ], 451 | extensions=[ 452 | ], 453 | nested_types=[], 454 | enum_types=[ 455 | ], 456 | serialized_options=None, 457 | is_extendable=False, 458 | syntax='proto3', 459 | extension_ranges=[], 460 | oneofs=[ 461 | ], 462 | serialized_start=1409, 463 | serialized_end=1531, 464 | ) 465 | 466 | 467 | _SPEECHRECOGNITIONALTERNATIVE = _descriptor.Descriptor( 468 | name='SpeechRecognitionAlternative', 469 | full_name='yandex.cloud.ai.stt.v2.SpeechRecognitionAlternative', 470 | filename=None, 471 | file=DESCRIPTOR, 472 | containing_type=None, 473 | create_key=_descriptor._internal_create_key, 474 | fields=[ 475 | _descriptor.FieldDescriptor( 476 | name='text', full_name='yandex.cloud.ai.stt.v2.SpeechRecognitionAlternative.text', index=0, 477 | number=1, type=9, cpp_type=9, label=1, 478 | has_default_value=False, default_value=b"".decode('utf-8'), 479 | message_type=None, enum_type=None, containing_type=None, 480 | is_extension=False, extension_scope=None, 481 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 482 | _descriptor.FieldDescriptor( 483 | name='confidence', full_name='yandex.cloud.ai.stt.v2.SpeechRecognitionAlternative.confidence', index=1, 484 | number=2, type=2, cpp_type=6, label=1, 485 | has_default_value=False, default_value=float(0), 486 | message_type=None, enum_type=None, containing_type=None, 487 | is_extension=False, extension_scope=None, 488 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 489 | _descriptor.FieldDescriptor( 490 | name='words', full_name='yandex.cloud.ai.stt.v2.SpeechRecognitionAlternative.words', index=2, 491 | number=3, type=11, cpp_type=10, label=3, 492 | has_default_value=False, default_value=[], 493 | message_type=None, enum_type=None, containing_type=None, 494 | is_extension=False, extension_scope=None, 495 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 496 | ], 497 | extensions=[ 498 | ], 499 | nested_types=[], 500 | enum_types=[ 501 | ], 502 | serialized_options=None, 503 | is_extendable=False, 504 | syntax='proto3', 505 | extension_ranges=[], 506 | oneofs=[ 507 | ], 508 | serialized_start=1533, 509 | serialized_end=1646, 510 | ) 511 | 512 | 513 | _WORDINFO = _descriptor.Descriptor( 514 | name='WordInfo', 515 | full_name='yandex.cloud.ai.stt.v2.WordInfo', 516 | filename=None, 517 | file=DESCRIPTOR, 518 | containing_type=None, 519 | create_key=_descriptor._internal_create_key, 520 | fields=[ 521 | _descriptor.FieldDescriptor( 522 | name='start_time', full_name='yandex.cloud.ai.stt.v2.WordInfo.start_time', index=0, 523 | number=1, type=11, cpp_type=10, label=1, 524 | has_default_value=False, default_value=None, 525 | message_type=None, enum_type=None, containing_type=None, 526 | is_extension=False, extension_scope=None, 527 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 528 | _descriptor.FieldDescriptor( 529 | name='end_time', full_name='yandex.cloud.ai.stt.v2.WordInfo.end_time', index=1, 530 | number=2, type=11, cpp_type=10, label=1, 531 | has_default_value=False, default_value=None, 532 | message_type=None, enum_type=None, containing_type=None, 533 | is_extension=False, extension_scope=None, 534 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 535 | _descriptor.FieldDescriptor( 536 | name='word', full_name='yandex.cloud.ai.stt.v2.WordInfo.word', index=2, 537 | number=3, type=9, cpp_type=9, label=1, 538 | has_default_value=False, default_value=b"".decode('utf-8'), 539 | message_type=None, enum_type=None, containing_type=None, 540 | is_extension=False, extension_scope=None, 541 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 542 | _descriptor.FieldDescriptor( 543 | name='confidence', full_name='yandex.cloud.ai.stt.v2.WordInfo.confidence', index=3, 544 | number=4, type=2, cpp_type=6, label=1, 545 | has_default_value=False, default_value=float(0), 546 | message_type=None, enum_type=None, containing_type=None, 547 | is_extension=False, extension_scope=None, 548 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 549 | ], 550 | extensions=[ 551 | ], 552 | nested_types=[], 553 | enum_types=[ 554 | ], 555 | serialized_options=None, 556 | is_extendable=False, 557 | syntax='proto3', 558 | extension_ranges=[], 559 | oneofs=[ 560 | ], 561 | serialized_start=1649, 562 | serialized_end=1785, 563 | ) 564 | 565 | _LONGRUNNINGRECOGNITIONREQUEST.fields_by_name['config'].message_type = _RECOGNITIONCONFIG 566 | _LONGRUNNINGRECOGNITIONREQUEST.fields_by_name['audio'].message_type = _RECOGNITIONAUDIO 567 | _LONGRUNNINGRECOGNITIONRESPONSE.fields_by_name['chunks'].message_type = _SPEECHRECOGNITIONRESULT 568 | _STREAMINGRECOGNITIONREQUEST.fields_by_name['config'].message_type = _RECOGNITIONCONFIG 569 | _STREAMINGRECOGNITIONREQUEST.oneofs_by_name['streaming_request'].fields.append( 570 | _STREAMINGRECOGNITIONREQUEST.fields_by_name['config']) 571 | _STREAMINGRECOGNITIONREQUEST.fields_by_name['config'].containing_oneof = _STREAMINGRECOGNITIONREQUEST.oneofs_by_name['streaming_request'] 572 | _STREAMINGRECOGNITIONREQUEST.oneofs_by_name['streaming_request'].fields.append( 573 | _STREAMINGRECOGNITIONREQUEST.fields_by_name['audio_content']) 574 | _STREAMINGRECOGNITIONREQUEST.fields_by_name['audio_content'].containing_oneof = _STREAMINGRECOGNITIONREQUEST.oneofs_by_name['streaming_request'] 575 | _STREAMINGRECOGNITIONRESPONSE.fields_by_name['chunks'].message_type = _SPEECHRECOGNITIONCHUNK 576 | _RECOGNITIONAUDIO.oneofs_by_name['audio_source'].fields.append( 577 | _RECOGNITIONAUDIO.fields_by_name['content']) 578 | _RECOGNITIONAUDIO.fields_by_name['content'].containing_oneof = _RECOGNITIONAUDIO.oneofs_by_name['audio_source'] 579 | _RECOGNITIONAUDIO.oneofs_by_name['audio_source'].fields.append( 580 | _RECOGNITIONAUDIO.fields_by_name['uri']) 581 | _RECOGNITIONAUDIO.fields_by_name['uri'].containing_oneof = _RECOGNITIONAUDIO.oneofs_by_name['audio_source'] 582 | _RECOGNITIONCONFIG.fields_by_name['specification'].message_type = _RECOGNITIONSPEC 583 | _RECOGNITIONSPEC.fields_by_name['audio_encoding'].enum_type = _RECOGNITIONSPEC_AUDIOENCODING 584 | _RECOGNITIONSPEC_AUDIOENCODING.containing_type = _RECOGNITIONSPEC 585 | _SPEECHRECOGNITIONCHUNK.fields_by_name['alternatives'].message_type = _SPEECHRECOGNITIONALTERNATIVE 586 | _SPEECHRECOGNITIONRESULT.fields_by_name['alternatives'].message_type = _SPEECHRECOGNITIONALTERNATIVE 587 | _SPEECHRECOGNITIONALTERNATIVE.fields_by_name['words'].message_type = _WORDINFO 588 | _WORDINFO.fields_by_name['start_time'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION 589 | _WORDINFO.fields_by_name['end_time'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION 590 | DESCRIPTOR.message_types_by_name['LongRunningRecognitionRequest'] = _LONGRUNNINGRECOGNITIONREQUEST 591 | DESCRIPTOR.message_types_by_name['LongRunningRecognitionResponse'] = _LONGRUNNINGRECOGNITIONRESPONSE 592 | DESCRIPTOR.message_types_by_name['StreamingRecognitionRequest'] = _STREAMINGRECOGNITIONREQUEST 593 | DESCRIPTOR.message_types_by_name['StreamingRecognitionResponse'] = _STREAMINGRECOGNITIONRESPONSE 594 | DESCRIPTOR.message_types_by_name['RecognitionAudio'] = _RECOGNITIONAUDIO 595 | DESCRIPTOR.message_types_by_name['RecognitionConfig'] = _RECOGNITIONCONFIG 596 | DESCRIPTOR.message_types_by_name['RecognitionSpec'] = _RECOGNITIONSPEC 597 | DESCRIPTOR.message_types_by_name['SpeechRecognitionChunk'] = _SPEECHRECOGNITIONCHUNK 598 | DESCRIPTOR.message_types_by_name['SpeechRecognitionResult'] = _SPEECHRECOGNITIONRESULT 599 | DESCRIPTOR.message_types_by_name['SpeechRecognitionAlternative'] = _SPEECHRECOGNITIONALTERNATIVE 600 | DESCRIPTOR.message_types_by_name['WordInfo'] = _WORDINFO 601 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 602 | 603 | LongRunningRecognitionRequest = _reflection.GeneratedProtocolMessageType('LongRunningRecognitionRequest', (_message.Message,), { 604 | 'DESCRIPTOR' : _LONGRUNNINGRECOGNITIONREQUEST, 605 | '__module__' : 'yandex.cloud.ai.stt.v2.stt_service_pb2' 606 | # @@protoc_insertion_point(class_scope:yandex.cloud.ai.stt.v2.LongRunningRecognitionRequest) 607 | }) 608 | _sym_db.RegisterMessage(LongRunningRecognitionRequest) 609 | 610 | LongRunningRecognitionResponse = _reflection.GeneratedProtocolMessageType('LongRunningRecognitionResponse', (_message.Message,), { 611 | 'DESCRIPTOR' : _LONGRUNNINGRECOGNITIONRESPONSE, 612 | '__module__' : 'yandex.cloud.ai.stt.v2.stt_service_pb2' 613 | # @@protoc_insertion_point(class_scope:yandex.cloud.ai.stt.v2.LongRunningRecognitionResponse) 614 | }) 615 | _sym_db.RegisterMessage(LongRunningRecognitionResponse) 616 | 617 | StreamingRecognitionRequest = _reflection.GeneratedProtocolMessageType('StreamingRecognitionRequest', (_message.Message,), { 618 | 'DESCRIPTOR' : _STREAMINGRECOGNITIONREQUEST, 619 | '__module__' : 'yandex.cloud.ai.stt.v2.stt_service_pb2' 620 | # @@protoc_insertion_point(class_scope:yandex.cloud.ai.stt.v2.StreamingRecognitionRequest) 621 | }) 622 | _sym_db.RegisterMessage(StreamingRecognitionRequest) 623 | 624 | StreamingRecognitionResponse = _reflection.GeneratedProtocolMessageType('StreamingRecognitionResponse', (_message.Message,), { 625 | 'DESCRIPTOR' : _STREAMINGRECOGNITIONRESPONSE, 626 | '__module__' : 'yandex.cloud.ai.stt.v2.stt_service_pb2' 627 | # @@protoc_insertion_point(class_scope:yandex.cloud.ai.stt.v2.StreamingRecognitionResponse) 628 | }) 629 | _sym_db.RegisterMessage(StreamingRecognitionResponse) 630 | 631 | RecognitionAudio = _reflection.GeneratedProtocolMessageType('RecognitionAudio', (_message.Message,), { 632 | 'DESCRIPTOR' : _RECOGNITIONAUDIO, 633 | '__module__' : 'yandex.cloud.ai.stt.v2.stt_service_pb2' 634 | # @@protoc_insertion_point(class_scope:yandex.cloud.ai.stt.v2.RecognitionAudio) 635 | }) 636 | _sym_db.RegisterMessage(RecognitionAudio) 637 | 638 | RecognitionConfig = _reflection.GeneratedProtocolMessageType('RecognitionConfig', (_message.Message,), { 639 | 'DESCRIPTOR' : _RECOGNITIONCONFIG, 640 | '__module__' : 'yandex.cloud.ai.stt.v2.stt_service_pb2' 641 | # @@protoc_insertion_point(class_scope:yandex.cloud.ai.stt.v2.RecognitionConfig) 642 | }) 643 | _sym_db.RegisterMessage(RecognitionConfig) 644 | 645 | RecognitionSpec = _reflection.GeneratedProtocolMessageType('RecognitionSpec', (_message.Message,), { 646 | 'DESCRIPTOR' : _RECOGNITIONSPEC, 647 | '__module__' : 'yandex.cloud.ai.stt.v2.stt_service_pb2' 648 | # @@protoc_insertion_point(class_scope:yandex.cloud.ai.stt.v2.RecognitionSpec) 649 | }) 650 | _sym_db.RegisterMessage(RecognitionSpec) 651 | 652 | SpeechRecognitionChunk = _reflection.GeneratedProtocolMessageType('SpeechRecognitionChunk', (_message.Message,), { 653 | 'DESCRIPTOR' : _SPEECHRECOGNITIONCHUNK, 654 | '__module__' : 'yandex.cloud.ai.stt.v2.stt_service_pb2' 655 | # @@protoc_insertion_point(class_scope:yandex.cloud.ai.stt.v2.SpeechRecognitionChunk) 656 | }) 657 | _sym_db.RegisterMessage(SpeechRecognitionChunk) 658 | 659 | SpeechRecognitionResult = _reflection.GeneratedProtocolMessageType('SpeechRecognitionResult', (_message.Message,), { 660 | 'DESCRIPTOR' : _SPEECHRECOGNITIONRESULT, 661 | '__module__' : 'yandex.cloud.ai.stt.v2.stt_service_pb2' 662 | # @@protoc_insertion_point(class_scope:yandex.cloud.ai.stt.v2.SpeechRecognitionResult) 663 | }) 664 | _sym_db.RegisterMessage(SpeechRecognitionResult) 665 | 666 | SpeechRecognitionAlternative = _reflection.GeneratedProtocolMessageType('SpeechRecognitionAlternative', (_message.Message,), { 667 | 'DESCRIPTOR' : _SPEECHRECOGNITIONALTERNATIVE, 668 | '__module__' : 'yandex.cloud.ai.stt.v2.stt_service_pb2' 669 | # @@protoc_insertion_point(class_scope:yandex.cloud.ai.stt.v2.SpeechRecognitionAlternative) 670 | }) 671 | _sym_db.RegisterMessage(SpeechRecognitionAlternative) 672 | 673 | WordInfo = _reflection.GeneratedProtocolMessageType('WordInfo', (_message.Message,), { 674 | 'DESCRIPTOR' : _WORDINFO, 675 | '__module__' : 'yandex.cloud.ai.stt.v2.stt_service_pb2' 676 | # @@protoc_insertion_point(class_scope:yandex.cloud.ai.stt.v2.WordInfo) 677 | }) 678 | _sym_db.RegisterMessage(WordInfo) 679 | 680 | 681 | DESCRIPTOR._options = None 682 | 683 | _STTSERVICE = _descriptor.ServiceDescriptor( 684 | name='SttService', 685 | full_name='yandex.cloud.ai.stt.v2.SttService', 686 | file=DESCRIPTOR, 687 | index=0, 688 | serialized_options=None, 689 | create_key=_descriptor._internal_create_key, 690 | serialized_start=1788, 691 | serialized_end=2135, 692 | methods=[ 693 | _descriptor.MethodDescriptor( 694 | name='LongRunningRecognize', 695 | full_name='yandex.cloud.ai.stt.v2.SttService.LongRunningRecognize', 696 | index=0, 697 | containing_service=None, 698 | input_type=_LONGRUNNINGRECOGNITIONREQUEST, 699 | output_type=yandex_dot_cloud_dot_operation_dot_operation__pb2._OPERATION, 700 | serialized_options=b'\202\323\344\223\002(\"#/speech/stt/v2/longRunningRecognize:\001*\262\322* \022\036LongRunningRecognitionResponse', 701 | create_key=_descriptor._internal_create_key, 702 | ), 703 | _descriptor.MethodDescriptor( 704 | name='StreamingRecognize', 705 | full_name='yandex.cloud.ai.stt.v2.SttService.StreamingRecognize', 706 | index=1, 707 | containing_service=None, 708 | input_type=_STREAMINGRECOGNITIONREQUEST, 709 | output_type=_STREAMINGRECOGNITIONRESPONSE, 710 | serialized_options=None, 711 | create_key=_descriptor._internal_create_key, 712 | ), 713 | ]) 714 | _sym_db.RegisterServiceDescriptor(_STTSERVICE) 715 | 716 | DESCRIPTOR.services_by_name['SttService'] = _STTSERVICE 717 | 718 | # @@protoc_insertion_point(module_scope) 719 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/yandex/cloud/ai/stt/v2/stt_service_pb2_grpc.py: -------------------------------------------------------------------------------- 1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! 2 | """Client and server classes corresponding to protobuf-defined services.""" 3 | import grpc 4 | 5 | from speechkit._recognition.yandex.cloud.ai.stt.v2 import stt_service_pb2 as yandex_dot_cloud_dot_ai_dot_stt_dot_v2_dot_stt__service__pb2 6 | from speechkit._recognition.yandex.cloud.operation import operation_pb2 as yandex_dot_cloud_dot_operation_dot_operation__pb2 7 | 8 | 9 | class SttServiceStub(object): 10 | """Missing associated documentation comment in .proto file.""" 11 | 12 | def __init__(self, channel): 13 | """Constructor. 14 | 15 | Args: 16 | channel: A grpc.Channel. 17 | """ 18 | self.LongRunningRecognize = channel.unary_unary( 19 | '/yandex.cloud.ai.stt.v2.SttService/LongRunningRecognize', 20 | request_serializer=yandex_dot_cloud_dot_ai_dot_stt_dot_v2_dot_stt__service__pb2.LongRunningRecognitionRequest.SerializeToString, 21 | response_deserializer=yandex_dot_cloud_dot_operation_dot_operation__pb2.Operation.FromString, 22 | ) 23 | self.StreamingRecognize = channel.stream_stream( 24 | '/yandex.cloud.ai.stt.v2.SttService/StreamingRecognize', 25 | request_serializer=yandex_dot_cloud_dot_ai_dot_stt_dot_v2_dot_stt__service__pb2.StreamingRecognitionRequest.SerializeToString, 26 | response_deserializer=yandex_dot_cloud_dot_ai_dot_stt_dot_v2_dot_stt__service__pb2.StreamingRecognitionResponse.FromString, 27 | ) 28 | 29 | 30 | class SttServiceServicer(object): 31 | """Missing associated documentation comment in .proto file.""" 32 | 33 | def LongRunningRecognize(self, request, context): 34 | """Missing associated documentation comment in .proto file.""" 35 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) 36 | context.set_details('Method not implemented!') 37 | raise NotImplementedError('Method not implemented!') 38 | 39 | def StreamingRecognize(self, request_iterator, context): 40 | """Missing associated documentation comment in .proto file.""" 41 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) 42 | context.set_details('Method not implemented!') 43 | raise NotImplementedError('Method not implemented!') 44 | 45 | 46 | def add_SttServiceServicer_to_server(servicer, server): 47 | rpc_method_handlers = { 48 | 'LongRunningRecognize': grpc.unary_unary_rpc_method_handler( 49 | servicer.LongRunningRecognize, 50 | request_deserializer=yandex_dot_cloud_dot_ai_dot_stt_dot_v2_dot_stt__service__pb2.LongRunningRecognitionRequest.FromString, 51 | response_serializer=yandex_dot_cloud_dot_operation_dot_operation__pb2.Operation.SerializeToString, 52 | ), 53 | 'StreamingRecognize': grpc.stream_stream_rpc_method_handler( 54 | servicer.StreamingRecognize, 55 | request_deserializer=yandex_dot_cloud_dot_ai_dot_stt_dot_v2_dot_stt__service__pb2.StreamingRecognitionRequest.FromString, 56 | response_serializer=yandex_dot_cloud_dot_ai_dot_stt_dot_v2_dot_stt__service__pb2.StreamingRecognitionResponse.SerializeToString, 57 | ), 58 | } 59 | generic_handler = grpc.method_handlers_generic_handler( 60 | 'yandex.cloud.ai.stt.v2.SttService', rpc_method_handlers) 61 | server.add_generic_rpc_handlers((generic_handler,)) 62 | 63 | 64 | # This class is part of an EXPERIMENTAL API. 65 | class SttService(object): 66 | """Missing associated documentation comment in .proto file.""" 67 | 68 | @staticmethod 69 | def LongRunningRecognize(request, 70 | target, 71 | options=(), 72 | channel_credentials=None, 73 | call_credentials=None, 74 | insecure=False, 75 | compression=None, 76 | wait_for_ready=None, 77 | timeout=None, 78 | metadata=None): 79 | return grpc.experimental.unary_unary(request, target, '/yandex.cloud.ai.stt.v2.SttService/LongRunningRecognize', 80 | yandex_dot_cloud_dot_ai_dot_stt_dot_v2_dot_stt__service__pb2.LongRunningRecognitionRequest.SerializeToString, 81 | yandex_dot_cloud_dot_operation_dot_operation__pb2.Operation.FromString, 82 | options, channel_credentials, 83 | insecure, call_credentials, compression, wait_for_ready, timeout, metadata) 84 | 85 | @staticmethod 86 | def StreamingRecognize(request_iterator, 87 | target, 88 | options=(), 89 | channel_credentials=None, 90 | call_credentials=None, 91 | insecure=False, 92 | compression=None, 93 | wait_for_ready=None, 94 | timeout=None, 95 | metadata=None): 96 | return grpc.experimental.stream_stream(request_iterator, target, '/yandex.cloud.ai.stt.v2.SttService/StreamingRecognize', 97 | yandex_dot_cloud_dot_ai_dot_stt_dot_v2_dot_stt__service__pb2.StreamingRecognitionRequest.SerializeToString, 98 | yandex_dot_cloud_dot_ai_dot_stt_dot_v2_dot_stt__service__pb2.StreamingRecognitionResponse.FromString, 99 | options, channel_credentials, 100 | insecure, call_credentials, compression, wait_for_ready, timeout, metadata) 101 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/yandex/cloud/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikhonp/yandex-speechkit-lib-python/3376c02ed42870c0ad741b52067b5c9941ec84b5/src/speechkit/_recognition/yandex/cloud/api/__init__.py -------------------------------------------------------------------------------- /src/speechkit/_recognition/yandex/cloud/api/operation_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: yandex/cloud/api/operation.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 15 | 16 | 17 | DESCRIPTOR = _descriptor.FileDescriptor( 18 | name='yandex/cloud/api/operation.proto', 19 | package='yandex.cloud.api', 20 | syntax='proto3', 21 | serialized_options=b'Z8github.com/yandex-cloud/go-genproto/yandex/cloud/api;api', 22 | create_key=_descriptor._internal_create_key, 23 | serialized_pb=b'\n yandex/cloud/api/operation.proto\x12\x10yandex.cloud.api\x1a google/protobuf/descriptor.proto\"/\n\tOperation\x12\x10\n\x08metadata\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t:P\n\toperation\x12\x1e.google.protobuf.MethodOptions\x18\xa6\xaa\x05 \x01(\x0b\x32\x1b.yandex.cloud.api.OperationB:Z8github.com/yandex-cloud/go-genproto/yandex/cloud/api;apib\x06proto3' 24 | , 25 | dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,]) 26 | 27 | 28 | OPERATION_FIELD_NUMBER = 87334 29 | operation = _descriptor.FieldDescriptor( 30 | name='operation', full_name='yandex.cloud.api.operation', index=0, 31 | number=87334, type=11, cpp_type=10, label=1, 32 | has_default_value=False, default_value=None, 33 | message_type=None, enum_type=None, containing_type=None, 34 | is_extension=True, extension_scope=None, 35 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key) 36 | 37 | 38 | _OPERATION = _descriptor.Descriptor( 39 | name='Operation', 40 | full_name='yandex.cloud.api.Operation', 41 | filename=None, 42 | file=DESCRIPTOR, 43 | containing_type=None, 44 | create_key=_descriptor._internal_create_key, 45 | fields=[ 46 | _descriptor.FieldDescriptor( 47 | name='metadata', full_name='yandex.cloud.api.Operation.metadata', index=0, 48 | number=1, type=9, cpp_type=9, label=1, 49 | has_default_value=False, default_value=b"".decode('utf-8'), 50 | message_type=None, enum_type=None, containing_type=None, 51 | is_extension=False, extension_scope=None, 52 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 53 | _descriptor.FieldDescriptor( 54 | name='response', full_name='yandex.cloud.api.Operation.response', index=1, 55 | number=2, type=9, cpp_type=9, label=1, 56 | has_default_value=False, default_value=b"".decode('utf-8'), 57 | message_type=None, enum_type=None, containing_type=None, 58 | is_extension=False, extension_scope=None, 59 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 60 | ], 61 | extensions=[ 62 | ], 63 | nested_types=[], 64 | enum_types=[ 65 | ], 66 | serialized_options=None, 67 | is_extendable=False, 68 | syntax='proto3', 69 | extension_ranges=[], 70 | oneofs=[ 71 | ], 72 | serialized_start=88, 73 | serialized_end=135, 74 | ) 75 | 76 | DESCRIPTOR.message_types_by_name['Operation'] = _OPERATION 77 | DESCRIPTOR.extensions_by_name['operation'] = operation 78 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 79 | 80 | Operation = _reflection.GeneratedProtocolMessageType('Operation', (_message.Message,), { 81 | 'DESCRIPTOR' : _OPERATION, 82 | '__module__' : 'yandex.cloud.api.operation_pb2' 83 | # @@protoc_insertion_point(class_scope:yandex.cloud.api.Operation) 84 | }) 85 | _sym_db.RegisterMessage(Operation) 86 | 87 | operation.message_type = _OPERATION 88 | google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(operation) 89 | 90 | DESCRIPTOR._options = None 91 | # @@protoc_insertion_point(module_scope) 92 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/yandex/cloud/api/operation_pb2_grpc.py: -------------------------------------------------------------------------------- 1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! 2 | """Client and server classes corresponding to protobuf-defined services.""" 3 | import grpc 4 | 5 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/yandex/cloud/operation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikhonp/yandex-speechkit-lib-python/3376c02ed42870c0ad741b52067b5c9941ec84b5/src/speechkit/_recognition/yandex/cloud/operation/__init__.py -------------------------------------------------------------------------------- /src/speechkit/_recognition/yandex/cloud/operation/operation_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: yandex/cloud/operation/operation.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 15 | from speechkit._recognition.google.rpc import status_pb2 as google_dot_rpc_dot_status__pb2 16 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 17 | 18 | 19 | DESCRIPTOR = _descriptor.FileDescriptor( 20 | name='yandex/cloud/operation/operation.proto', 21 | package='yandex.cloud.operation', 22 | syntax='proto3', 23 | serialized_options=b'\n\032yandex.cloud.api.operationZDgithub.com/yandex-cloud/go-genproto/yandex/cloud/operation;operation', 24 | create_key=_descriptor._internal_create_key, 25 | serialized_pb=b'\n&yandex/cloud/operation/operation.proto\x12\x16yandex.cloud.operation\x1a\x19google/protobuf/any.proto\x1a\x17google/rpc/status.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xb0\x02\n\tOperation\x12\n\n\x02id\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12.\n\ncreated_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\ncreated_by\x18\x04 \x01(\t\x12/\n\x0bmodified_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0c\n\x04\x64one\x18\x06 \x01(\x08\x12&\n\x08metadata\x18\x07 \x01(\x0b\x32\x14.google.protobuf.Any\x12#\n\x05\x65rror\x18\x08 \x01(\x0b\x32\x12.google.rpc.StatusH\x00\x12(\n\x08response\x18\t \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x42\x08\n\x06resultBb\n\x1ayandex.cloud.api.operationZDgithub.com/yandex-cloud/go-genproto/yandex/cloud/operation;operationb\x06proto3' 26 | , 27 | dependencies=[google_dot_protobuf_dot_any__pb2.DESCRIPTOR,google_dot_rpc_dot_status__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,]) 28 | 29 | 30 | 31 | 32 | _OPERATION = _descriptor.Descriptor( 33 | name='Operation', 34 | full_name='yandex.cloud.operation.Operation', 35 | filename=None, 36 | file=DESCRIPTOR, 37 | containing_type=None, 38 | create_key=_descriptor._internal_create_key, 39 | fields=[ 40 | _descriptor.FieldDescriptor( 41 | name='id', full_name='yandex.cloud.operation.Operation.id', index=0, 42 | number=1, type=9, cpp_type=9, label=1, 43 | has_default_value=False, default_value=b"".decode('utf-8'), 44 | message_type=None, enum_type=None, containing_type=None, 45 | is_extension=False, extension_scope=None, 46 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 47 | _descriptor.FieldDescriptor( 48 | name='description', full_name='yandex.cloud.operation.Operation.description', index=1, 49 | number=2, type=9, cpp_type=9, label=1, 50 | has_default_value=False, default_value=b"".decode('utf-8'), 51 | message_type=None, enum_type=None, containing_type=None, 52 | is_extension=False, extension_scope=None, 53 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 54 | _descriptor.FieldDescriptor( 55 | name='created_at', full_name='yandex.cloud.operation.Operation.created_at', index=2, 56 | number=3, type=11, cpp_type=10, label=1, 57 | has_default_value=False, default_value=None, 58 | message_type=None, enum_type=None, containing_type=None, 59 | is_extension=False, extension_scope=None, 60 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 61 | _descriptor.FieldDescriptor( 62 | name='created_by', full_name='yandex.cloud.operation.Operation.created_by', index=3, 63 | number=4, type=9, cpp_type=9, label=1, 64 | has_default_value=False, default_value=b"".decode('utf-8'), 65 | message_type=None, enum_type=None, containing_type=None, 66 | is_extension=False, extension_scope=None, 67 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 68 | _descriptor.FieldDescriptor( 69 | name='modified_at', full_name='yandex.cloud.operation.Operation.modified_at', index=4, 70 | number=5, type=11, cpp_type=10, label=1, 71 | has_default_value=False, default_value=None, 72 | message_type=None, enum_type=None, containing_type=None, 73 | is_extension=False, extension_scope=None, 74 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 75 | _descriptor.FieldDescriptor( 76 | name='done', full_name='yandex.cloud.operation.Operation.done', index=5, 77 | number=6, type=8, cpp_type=7, label=1, 78 | has_default_value=False, default_value=False, 79 | message_type=None, enum_type=None, containing_type=None, 80 | is_extension=False, extension_scope=None, 81 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 82 | _descriptor.FieldDescriptor( 83 | name='metadata', full_name='yandex.cloud.operation.Operation.metadata', index=6, 84 | number=7, type=11, cpp_type=10, label=1, 85 | has_default_value=False, default_value=None, 86 | message_type=None, enum_type=None, containing_type=None, 87 | is_extension=False, extension_scope=None, 88 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 89 | _descriptor.FieldDescriptor( 90 | name='error', full_name='yandex.cloud.operation.Operation.error', index=7, 91 | number=8, type=11, cpp_type=10, label=1, 92 | has_default_value=False, default_value=None, 93 | message_type=None, enum_type=None, containing_type=None, 94 | is_extension=False, extension_scope=None, 95 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 96 | _descriptor.FieldDescriptor( 97 | name='response', full_name='yandex.cloud.operation.Operation.response', index=8, 98 | number=9, type=11, cpp_type=10, label=1, 99 | has_default_value=False, default_value=None, 100 | message_type=None, enum_type=None, containing_type=None, 101 | is_extension=False, extension_scope=None, 102 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 103 | ], 104 | extensions=[ 105 | ], 106 | nested_types=[], 107 | enum_types=[ 108 | ], 109 | serialized_options=None, 110 | is_extendable=False, 111 | syntax='proto3', 112 | extension_ranges=[], 113 | oneofs=[ 114 | _descriptor.OneofDescriptor( 115 | name='result', full_name='yandex.cloud.operation.Operation.result', 116 | index=0, containing_type=None, 117 | create_key=_descriptor._internal_create_key, 118 | fields=[]), 119 | ], 120 | serialized_start=152, 121 | serialized_end=456, 122 | ) 123 | 124 | _OPERATION.fields_by_name['created_at'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP 125 | _OPERATION.fields_by_name['modified_at'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP 126 | _OPERATION.fields_by_name['metadata'].message_type = google_dot_protobuf_dot_any__pb2._ANY 127 | _OPERATION.fields_by_name['error'].message_type = google_dot_rpc_dot_status__pb2._STATUS 128 | _OPERATION.fields_by_name['response'].message_type = google_dot_protobuf_dot_any__pb2._ANY 129 | _OPERATION.oneofs_by_name['result'].fields.append( 130 | _OPERATION.fields_by_name['error']) 131 | _OPERATION.fields_by_name['error'].containing_oneof = _OPERATION.oneofs_by_name['result'] 132 | _OPERATION.oneofs_by_name['result'].fields.append( 133 | _OPERATION.fields_by_name['response']) 134 | _OPERATION.fields_by_name['response'].containing_oneof = _OPERATION.oneofs_by_name['result'] 135 | DESCRIPTOR.message_types_by_name['Operation'] = _OPERATION 136 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 137 | 138 | Operation = _reflection.GeneratedProtocolMessageType('Operation', (_message.Message,), { 139 | 'DESCRIPTOR' : _OPERATION, 140 | '__module__' : 'yandex.cloud.operation.operation_pb2' 141 | # @@protoc_insertion_point(class_scope:yandex.cloud.operation.Operation) 142 | }) 143 | _sym_db.RegisterMessage(Operation) 144 | 145 | 146 | DESCRIPTOR._options = None 147 | # @@protoc_insertion_point(module_scope) 148 | -------------------------------------------------------------------------------- /src/speechkit/_recognition/yandex/cloud/operation/operation_pb2_grpc.py: -------------------------------------------------------------------------------- 1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! 2 | """Client and server classes corresponding to protobuf-defined services.""" 3 | import grpc 4 | 5 | -------------------------------------------------------------------------------- /src/speechkit/_synthesis.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | from speechkit.exceptions import RequestError 4 | 5 | 6 | class SpeechSynthesis: 7 | """Generates speech from received text.""" 8 | 9 | def __init__(self, session): 10 | """ 11 | Initialize :py:class:`speechkit.SpeechSynthesis` 12 | 13 | :param speechkit.Session session: Session instance for auth 14 | """ 15 | self._headers = session.header 16 | self._folder_id = session.folder_id 17 | 18 | def _synthesize_stream(self, **kwargs): 19 | """Creates request to generate speech from text""" 20 | 21 | url = 'https://tts.api.cloud.yandex.net/speech/v1/tts:synthesize' 22 | params = {'folderId': self._folder_id} if self._folder_id else {} 23 | params.update(kwargs) 24 | answer = requests.post(url, headers=self._headers, data=params, stream=True) 25 | 26 | if not answer.ok: 27 | raise RequestError(answer.json()) 28 | 29 | answer.raw.decode_content = True 30 | return answer.content 31 | 32 | def synthesize(self, file_path, **kwargs): 33 | """ 34 | Generates speech from received text and saves it to file 35 | 36 | :type file_path: string 37 | :param file_path: The path to file where store data 38 | 39 | :type text: string 40 | :param text: UTF-8 encoded text to be converted to speech. 41 | You can only use one `text` and `ssml` field. 42 | For homographs, place a `+` before the stressed vowel. 43 | For example, `contr+ol` or `def+ect`. 44 | To indicate a pause between words, use `-`. 45 | Maximum string length: 5000 characters. 46 | 47 | :type ssml: string 48 | :param ssml: Text in SSML format to be converted into speech. 49 | You can only use one text and ssml fields. 50 | 51 | :type lang: string 52 | :param lang: Language. 53 | Acceptable values: 54 | 55 | * `ru-RU` (default) — Russian. 56 | 57 | * `en-US` — English. 58 | 59 | * `tr-TR` — Turkish. 60 | 61 | :type voice: string 62 | :param voice: Preferred speech synthesis voice from the list. 63 | Default value: `oksana`. 64 | 65 | :type speed: string 66 | :param speed: Rate (speed) of synthesized speech. 67 | The rate of speech is set as a decimal number in the range from 0.1 to 3.0. Where: 68 | 69 | * `3.0` — Fastest rate. 70 | 71 | * `1.0` (default) — Average human speech rate. 72 | 73 | * `0.1` — Slowest speech rate. 74 | 75 | :type format: string 76 | :param format: The format of the synthesized audio. Acceptable values: 77 | 78 | * `lpcm` — Audio file is synthesized in LPCM format with no WAV _header. Audio properties: 79 | 80 | * Sampling — 8, 16, or 48 kHz, depending on the value of the `sample_rate_hertz` parameter. 81 | 82 | * Bit depth — 16-bit. 83 | 84 | * Byte order — Reversed (little-endian). 85 | 86 | * Audio data is stored as signed integers. 87 | 88 | * `oggopus` (default) — Data in the audio file is encoded using the OPUS audio codec and compressed using 89 | the OGG container format (OggOpus). 90 | 91 | :type sampleRateHertz: string 92 | :param sample_rate_hertz: The sampling frequency of the synthesized audio. Used 93 | if format is set to lpcm. Acceptable values: * `48000` (default): Sampling rate of 48 kHz. * `16000`: 94 | Sampling rate of 16 kHz. * `8000`: Sampling rate of 8 kHz. 95 | 96 | :type folderId: string 97 | :param folderId: ID of the folder that you have access to. 98 | Required for authorization with a user account (see the UserAccount resource). 99 | Don't specify this field if you make a request on behalf of a service account. 100 | """ 101 | 102 | if 'text' in kwargs and len(kwargs.get('text', '')) > 5000: 103 | raise ValueError("Text must be less than 5000 characters") 104 | 105 | with open(file_path, "wb") as f: 106 | audio_data = self._synthesize_stream(**kwargs) 107 | f.write(audio_data) 108 | 109 | def synthesize_stream(self, **kwargs): 110 | """ 111 | Generates speech from received text and return :py:meth:`io.BytesIO` object with data. 112 | 113 | :type text: string 114 | :param text: UTF-8 encoded text to be converted to speech. 115 | You can only use one `text` and `ssml` field. 116 | For homographs, place a `+` before the stressed vowel. 117 | For example, `contr+ol` or `def+ect`. 118 | To indicate a pause between words, use `-`. 119 | Maximum string length: 5000 characters. 120 | 121 | :type ssml: string 122 | :param ssml: Text in SSML format to be converted into speech. 123 | You can only use one text and ssml fields. 124 | 125 | :type lang: string 126 | :param lang: Language. 127 | Acceptable values: 128 | 129 | * `ru-RU` (default) — Russian. 130 | 131 | * `en-US` — English. 132 | 133 | * `tr-TR` — Turkish. 134 | 135 | :type voice: string 136 | :param voice: Preferred speech synthesis voice from the list. 137 | Default value: `oksana`. 138 | 139 | :type speed: string 140 | :param speed: Rate (speed) of synthesized speech. 141 | The rate of speech is set as a decimal number in the range from 0.1 to 3.0. Where: 142 | 143 | * `3.0` — Fastest rate. 144 | 145 | * `1.0` (default) — Average human speech rate. 146 | 147 | * `0.1` — Slowest speech rate. 148 | 149 | :type format: string 150 | :param format: The format of the synthesized audio. Acceptable values: 151 | 152 | - `lpcm` — Audio file is synthesized in LPCM format with no WAV _header. Audio properties: 153 | 154 | * Sampling — 8, 16, or 48 kHz, depending on the value of the `sample_rate_hertz` parameter. 155 | 156 | * Bit depth — 16-bit. 157 | 158 | * Byte order — Reversed (little-endian). 159 | 160 | * Audio data is stored as signed integers. 161 | 162 | - `oggopus` (default) — Data in the audio file is encoded using the OPUS audio codec and compressed using 163 | the OGG container format (OggOpus). 164 | 165 | :type sampleRateHertz: string 166 | :param sampleRateHertz: The sampling frequency of the synthesized audio. 167 | Used if format is set to lpcm. Acceptable values: 168 | 169 | * `48000` (default): Sampling rate of 48 kHz. 170 | 171 | * `16000`: Sampling rate of 16 kHz. 172 | 173 | * `8000`: Sampling rate of 8 kHz. 174 | 175 | :type folderId: string 176 | :param folderId: ID of the folder that you have access to. 177 | Required for authorization with a user account (see the UserAccount resource). 178 | Don't specify this field if you make a request on behalf of a service account. 179 | """ 180 | if 'text' in kwargs and len(kwargs.get('text', '')) > 5000: 181 | raise ValueError("Text must be less than 5000 characters") 182 | 183 | return self._synthesize_stream(**kwargs) -------------------------------------------------------------------------------- /src/speechkit/auth.py: -------------------------------------------------------------------------------- 1 | """ 2 | Utilities for Yandex Cloud authorisation 3 | `IAM token `_ 4 | `Api-Key `_ 5 | """ 6 | 7 | from speechkit._auth import generate_jwt, get_iam_token, get_api_key 8 | 9 | __all__ = ['generate_jwt', 'get_iam_token', 'get_api_key'] 10 | -------------------------------------------------------------------------------- /src/speechkit/exceptions.py: -------------------------------------------------------------------------------- 1 | """Basic speechkit exceptions.""" 2 | 3 | 4 | class RequestError(Exception): 5 | """Exception raised for errors while yandex api request""" 6 | 7 | def __init__(self, answer: dict, *args): 8 | self.error_code = str(answer.get('code', '')) + str(answer.get('error_code', '')) 9 | self.message = str(answer.get('message', '')) + str(answer.get('error_message', '')) 10 | if self.error_code + self.message == '': 11 | self.message = str(answer) 12 | 13 | super().__init__(self.error_code + ' ' + self.message, *args) 14 | -------------------------------------------------------------------------------- /src/speechkit/utils.py: -------------------------------------------------------------------------------- 1 | """Utilities functions, tht allow to use different api methods.""" 2 | 3 | import requests 4 | 5 | from speechkit.exceptions import RequestError 6 | 7 | 8 | def list_of_service_accounts(session, **kwargs): 9 | """ 10 | Retrieves the list of ServiceAccount resources in the specified folder. 11 | 12 | :param speechkit._auth.Session session: Session instance for auth 13 | :param dict kwargs: Additional parameters 14 | :return: List of dict with data of services accounts 15 | :rtype: list[dict] 16 | """ 17 | if session.auth_method == session.API_KEY: 18 | raise ValueError("Api-Key authorisation method is invalid.") 19 | if session.folder_id is None: 20 | raise ValueError("You must specify folder is in session.") 21 | 22 | headers = session.header 23 | url = 'https://iam.api.cloud.yandex.net/iam/v1/serviceAccounts' 24 | data = {'folderId': session.folder_id, **kwargs} 25 | answer = requests.get(url, headers=headers, json=data) 26 | 27 | if answer.ok: 28 | return answer.json().get('serviceAccounts', []) 29 | else: 30 | raise RequestError(answer.json()) 31 | -------------------------------------------------------------------------------- /src/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikhonp/yandex-speechkit-lib-python/3376c02ed42870c0ad741b52067b5c9941ec84b5/src/tests/__init__.py -------------------------------------------------------------------------------- /src/tests/test_auth.py: -------------------------------------------------------------------------------- 1 | import os 2 | import unittest 3 | from unittest import TestCase 4 | 5 | from speechkit.auth import generate_jwt, get_iam_token, get_api_key 6 | from speechkit import Session 7 | 8 | 9 | def get_private_key(): 10 | with open('../.YANDEX_PRIVATE_KEY.txt', 'rb') as f: 11 | return f.read() 12 | 13 | 14 | class GenerateJwtTestCase(unittest.TestCase): 15 | def test_generating(self): 16 | service_account_id = os.environ.get('SERVICE_ACCOUNT_ID') 17 | key_id = os.environ.get('YANDEX_KEY_ID') 18 | private_key = get_private_key() 19 | jwt = generate_jwt(service_account_id, key_id, private_key) 20 | self.assertIsInstance(jwt, str) 21 | 22 | def test_assert_incorrect_service_account_id_key_id_private_key(self): 23 | with self.assertRaises(ValueError): 24 | generate_jwt('', 's', b'') 25 | 26 | with self.assertRaises(ValueError): 27 | generate_jwt('s', '', b'') 28 | 29 | with self.assertRaises(ValueError): 30 | generate_jwt('s', '', '') 31 | 32 | 33 | class GetIamTokenTestCase(unittest.TestCase): 34 | def test_assert_empty_data(self): 35 | with self.assertRaises(ValueError): 36 | get_iam_token() 37 | 38 | def test_assert_invalid_yandex_passport_oauth_token(self): 39 | with self.assertRaises(ValueError): 40 | get_iam_token(yandex_passport_oauth_token='', jwt_token='') 41 | 42 | def test_request_yandex_oauth(self): 43 | oauth_token = os.environ.get('YANDEX_OAUTH') 44 | 45 | data = get_iam_token(yandex_passport_oauth_token=oauth_token) 46 | self.assertIsInstance(data, str) 47 | 48 | def test_request_jwt(self): 49 | service_account_id = os.environ.get('SERVICE_ACCOUNT_ID') 50 | key_id = os.environ.get('YANDEX_KEY_ID') 51 | private_key = get_private_key() 52 | jwt = generate_jwt(service_account_id, key_id, private_key) 53 | 54 | data = get_iam_token(jwt_token=jwt) 55 | self.assertIsInstance(data, str) 56 | 57 | 58 | class GetApiKeyTestCase(unittest.TestCase): 59 | def test_request(self): 60 | yandex_passport_oauth_token = os.environ.get('YANDEX_OAUTH') 61 | service_account_id = os.environ.get('SERVICE_ACCOUNT_ID') 62 | 63 | data = get_api_key(yandex_passport_oauth_token, service_account_id) 64 | self.assertIsInstance(data, str) 65 | 66 | def test_invalid_data_empty(self): 67 | with self.assertRaises(ValueError): 68 | get_api_key() 69 | 70 | 71 | class SessionTestCase(TestCase): 72 | def test_from_api_key(self): 73 | api_key = os.environ.get('SERVICE_API_KEY') 74 | folder_id = os.environ.get('CATALOG') 75 | 76 | session = Session.from_api_key(api_key, folder_id) 77 | self.assertIsInstance(session.header, dict) 78 | self.assertEqual(session.folder_id, folder_id) 79 | 80 | def test_from_yandex_passport_oauth_token(self): 81 | oauth_token = os.environ.get('YANDEX_OAUTH') 82 | folder_id = os.environ.get('CATALOG') 83 | 84 | session = Session.from_yandex_passport_oauth_token(oauth_token, folder_id) 85 | self.assertIsInstance(session.header, dict) 86 | 87 | def test_from_jwt(self): 88 | service_account_id = os.environ.get('SERVICE_ACCOUNT_ID') 89 | key_id = os.environ.get('YANDEX_KEY_ID') 90 | private_key = get_private_key() 91 | jwt = generate_jwt(service_account_id, key_id, private_key) 92 | 93 | session = Session.from_jwt(jwt) 94 | self.assertIsInstance(session.header, dict) 95 | 96 | def test_header_api_key(self): 97 | session = Session(Session.API_KEY, 'hello', None) 98 | self.assertEqual(session.header, {'Authorization': 'Api-Key hello'}) 99 | 100 | def test_header_iam_token(self): 101 | session = Session(Session.IAM_TOKEN, 'hello', None) 102 | self.assertEqual(session.header, {'Authorization': 'Bearer hello'}) 103 | 104 | def test_auth_method(self): 105 | session = Session(Session.API_KEY, 'hello', None) 106 | self.assertEqual(session.auth_method, Session.API_KEY) 107 | 108 | session = Session(Session.IAM_TOKEN, 'hello', None) 109 | self.assertEqual(session.auth_method, Session.IAM_TOKEN) 110 | 111 | 112 | if __name__ == '__main__': 113 | unittest.main() 114 | -------------------------------------------------------------------------------- /src/tests/test_exceptions.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from speechkit.exceptions import RequestError 4 | 5 | 6 | class RequestErrorTestCase(unittest.TestCase): 7 | def test_raise_data_1(self): 8 | with self.assertRaises(RequestError) as cm: 9 | raise RequestError({'code': 3, 'message': 'message'}) 10 | 11 | the_exception = cm.exception 12 | self.assertEqual(the_exception.error_code, '3') 13 | self.assertEqual(the_exception.message, 'message') 14 | self.assertEqual(str(the_exception), '3 message') 15 | 16 | def test_raise_data_2(self): 17 | with self.assertRaises(RequestError) as cm: 18 | raise RequestError({'error_code': 3, 'error_message': 'message'}) 19 | 20 | the_exception = cm.exception 21 | self.assertEqual(the_exception.error_code, '3') 22 | self.assertEqual(the_exception.message, 'message') 23 | self.assertEqual(str(the_exception), '3 message') 24 | -------------------------------------------------------------------------------- /src/tests/test_long_audio_recognition.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import unittest 4 | import warnings 5 | 6 | from speechkit import RecognitionLongAudio, Session 7 | from speechkit.auth import generate_jwt 8 | 9 | test_data = b'RIFFl@\x08\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00\x80\xbb\x00\x00\x00w\x01\x00\x02\x00\x10\x00LIST@\x00\x00\x00INFOINAM\x1d\x00\x00\x00\xd1\x83\xd0\xbb\xd0\xb8\xd1\x86\xd0\xb0 8 \xd0\x9c\xd0\xb0\xd1\x80\xd1\x82\xd0\xb0, 6 9\x00\x00ISFT\x0e\x00\x00\x00Lavf58.76.100\x00data\x00@\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x00\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x00\x02\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x00\x02\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x01\x00\x00\x00\x00\x00\x01\x00\x02\x00\x02\x00\x03\x00\x02\x00\x02\x00\x01\x00\xff\xff\xff\xff\x00\x00\xff\xff\xfe\xff\xff\xff\x02\x00\x03\x00\x00\x00\xfd\xff\xfe\xff\x02\x00\x03\x00\x01\x00\xfe\xff\x01\x00\x04\x00\x03\x00\xfe\xff\xfb\xff\xfd\xff\x01\x00\x02\x00\x00\x00\xfc\xff\xfb\xff\xfc\xff\xff\xff\x02\x00\xff\xff\xf2\xff\xe0\xff\xd3\xff\xcf\xff\xd0\xff\xcc\xff\xc4\xff\xbd\xff\xb5\xff\xa5\xff\x8d\xfft\xffd\xff\\\xffX\xffV\xffV\xffV\xffN\xff?\xff1\xff/\xff8\xffA\xffG\xffJ\xffN\xffO\xffL\xffF\xffF\xffH\xffG\xff<\xff.\xff(\xff(\xff&\xff\x1e\xff\x16\xff\x18\xff#\xff0\xff8\xff<\xffA\xffF\xffH\xffH\xffL\xffV\xffb\xffm\xffs\xffv\xffy\xff}\xff\x85\xff\x8f\xff\x9a\xff\xa1\xff\xa8\xff\xaf\xff\xb4\xff\xb6\xff\xb7\xff\xbd\xff\xcc\xff\xdd\xff\xec\xff\xf9\xff\x08\x00\x18\x00\'\x003\x00?\x00J\x00Q\x00T\x00T\x00T\x00S\x00S\x00Z\x00n\x00\x87\x00\x99\x00\xa2\x00\xab\x00\xbb\x00\xcb\x00\xd4\x00\xd3\x00\xce\x00\xc9\x00\xc1\x00\xb4\x00\xa6\x00\x99\x00\x8b\x00~\x00w\x00z\x00\x80\x00\x80\x00w\x00n\x00k\x00o\x00q\x00n\x00j\x00k\x00p\x00q\x00h\x00Y\x00K\x00G\x00G\x00I\x00M\x00V\x00`\x00b\x00]\x00Y\x00X\x00T\x00D\x001\x00(\x00\'\x00 \x00\x0f\x00\xff\xff\xff\xff\t\x00\x0e\x00\x08\x00\xff\xff\xff\xff\x03\x00\x07\x00\t\x00\t\x00\x07\x00\x04\x00\x08\x00\x18\x00,\x005\x007\x00>\x00P\x00_\x00`\x00Y\x00Y\x00e\x00s\x00z\x00\x7f\x00\x85\x00\x8c\x00\x8f\x00\x8e\x00\x8d\x00\x8a\x00\x80\x00r\x00h\x00h\x00n\x00r\x00n\x00j\x00l\x00s\x00w\x00u\x00m\x00f\x00_\x00U\x00F\x008\x001\x00/\x00+\x00"\x00\x1a\x00\x16\x00\x0e\x00\xf9\xff\xda\xff\xbd\xff\xa7\xff\x90\xffs\xffX\xffH\xffA\xff6\xff#\xff\x12\xff\x0c\xff\x0b\xff\x05\xff\xf8\xfe\xed\xfe\xec\xfe\xed\xfe\xea\xfe\xe2\xfe\xde\xfe\xe0\xfe\xe4\xfe\xe5\xfe\xe4\xfe\xe3\xfe\xe1\xfe\xde\xfe\xdb\xfe\xdc\xfe\xe1\xfe\xe3\xfe\xe0\xfe\xde\xfe\xe1\xfe\xe7\xfe\xec\xfe\xf0\xfe\xfc\xfe\x10\xff!\xff\'\xff\'\xff-\xff<\xffJ\xffQ\xffV\xff]\xffe\xfff\xffa\xff\\\xff\\\xff`\xffh\xffs\xff\x81\xff\x8d\xff\x9a\xff\xa9\xff\xbc\xff\xcf\xff\xdf\xff\xf1\xff\x06\x00\x18\x00\x1f\x00!\x00,\x00E\x00^\x00m\x00v\x00\x82\x00\x91\x00\x9b\x00\x9f\x00\xa7\x00\xb8\x00\xcb\x00\xd9\x00\xe2\x00\xee\x00\xfb\x00\x04\x01\x05\x01\x02\x01\x01\x01\x01\x01\xff\x00\xfa\x00\xf4\x00\xec\x00\xe5\x00\xe3\x00\xe6\x00\xed\x00\xf5\x00\x01\x01\x0e\x01\x14\x01\x14\x01\x11\x01\x14\x01\x19\x01\x19\x01\x11\x01\x06\x01\xfc\x00\xf4\x00\xee\x00\xeb\x00\xe9\x00\xe5\x00\xde\x00\xd8\x00\xd5\x00\xce\x00\xbe\x00\xae\x00\xa8\x00\xaa\x00\xa3\x00\x91\x00\x83\x00\x86\x00\x91\x00\x90\x00\x82\x00v\x00r\x00l\x00[\x00H\x00A\x00F\x00G\x00=\x000\x00)\x00\'\x00$\x00\x1b\x00\x11\x00\n\x00\x07\x00\x05\x00\x01\x00\xf8\xff\xe9\xff\xd8\xff\xcc\xff\xc3\xff\xb6\xff\xa2\xff\x91\xff\x8a\xff\x90\xff\x9b\xff\xa4\xff\xad\xff\xba\xff\xcb\xff\xda\xff\xe5\xff\xef\xff\xf9\xff\xff\xff\xfe\xff\xfa\xff\xfa\xff\x02\x00\x08\x00\n\x00\x0e\x00\x1e\x004\x00D\x00K\x00U\x00k\x00\x84\x00\x92\x00\x99\x00\xa9\x00\xc3\x00\xd9\x00\xe3\x00\xec\x00\x02\x01\x1c\x01.\x017\x01D\x01X\x01d\x01^\x01T\x01U\x01^\x01^\x01P\x01C\x01C\x01N\x01W\x01\\\x01b\x01l\x01w\x01\x7f\x01\x84\x01\x83\x01|\x01u\x01q\x01o\x01g\x01W\x01F\x01<\x017\x012\x01)\x01"\x01\x1d\x01\x1b\x01\x16\x01\n\x01\xf5\x00\xd7\x00\xb6\x00\x9c\x00\x87\x00o\x00S\x007\x00$\x00\x1c\x00\x14\x00\x07\x00\xf4\xff\xe1\xff\xd0\xff\xc1\xff\xb1\xff\x9f\xff\x8e\xff\x82\xff|\xffz\xfft\xffj\xff`\xffZ\xffT\xffL\xffC\xff:\xff4\xff-\xff%\xff\x1b\xff\x11\xff\x08\xff\xff\xfe\xfa\xfe\xf8\xfe\xf7\xfe\xf3\xfe\xec\xfe\xe4\xfe\xdf\xfe\xe0\xfe\xe5\xfe\xed\xfe\xf4\xfe\xfd\xfe\r\xff\x1f\xff,\xff.\xff,\xff3\xffE\xffY\xfff\xffq\xff\x80\xff\x98\xff\xb8\xff\xd9\xff\xf5\xff\x06\x00\x10\x00\x1d\x00.\x00<\x00<\x005\x004\x00:\x00:\x00&\x00\n\x00\xf8\xff\xf5\xff\xf6\xff\xf2\xff\xef\xff\xf3\xff\xfa\xff\xfc\xff\xf9\xff\xfb\xff\x00\x00\x03\x00\x01\x00\xff\xff\x04\x00\x0c\x00\x10\x00\x0e\x00\n\x00\x0b\x00\r\x00\x0f\x00\x0e\x00\x0c\x00\x0c\x00\x0c\x00\x0e\x00\r\x00\x0b\x00\t\x00\x0c\x00\x10\x00\x0f\x00\t\x00\x02\x00\x02\x00\x07\x00\n\x00\n\x00\t\x00\t\x00\t\x00\x07\x00\x06\x00\x05\x00\x04\x00\x01\x00\x00\x00\x01\x00\x00\x00\xfe\xff\xfb\xff\xfb\xff\xfc\xff\xfb\xff\xf8\xff\xf5\xff\xf7\xff\xf9\xff\xf7\xff\xf2\xff\xf1\xff\xf4\xff\xf7\xff\xf5\xff\xf2\xff\xf1\xff\xf2\xff\xf3\xff\xf3\xff\xf2\xff\xf2\xff\xf2\xff\xf1\xff\xef\xff\xed\xff\xec\xff\xed\xff\xef\xff\xf0\xff\xf1\xff\xf2\xff\xf3\xff\xf4\xff\xf5\xff\xf3\xff\xf0\xff\xee\xff\xed\xff\xee\xff\xed\xff\xeb\xff\xea\xff\xeb\xff\xec\xff\xeb\xff\xe9\xff\xe8\xff\xea\xff\xec\xff\xec\xff\xea\xff\xe9\xff\xea\xff\xeb\xff\xea\xff\xe9\xff\xe8\xff\xe9\xff\xe9\xff\xea\xff\xea\xff\xe8\xff\xe5\xff\xe2\xff\xe2\xff\xe4\xff\xe4\xff\xe2\xff\xdf\xff\xdf\xff\xe0\xff\xe0\xff\xde\xff\xdd\xff\xdc\xff\xda\xff\xd9\xff\xd9\xff\xdb\xff\xdd\xff\xdc\xff\xd9\xff\xd8\xff\xda\xff\xdb\xff\xdb\xff\xdc\xff\xde\xff\xdd\xff\xda\xff\xd7\xff\xd7\xff\xd8\xff\xd8\xff\xd7\xff\xd7\xff\xd9\xff\xda\xff\xd8\xff\xd6\xff\xd5\xff\xd5\xff\xd5\xff\xd5\xff\xd5\xff\xd5\xff\xd5\xff\xd6\xff\xda\xff\xdd\xff\xde\xff\xde\xff\xde\xff\xe1\xff\xe2\xff\xe1\xff\xe0\xff\xe1\xff\xe3\xff\xe4\xff\xe2\xff\xe1\xff\xe3\xff\xe4\xff\xe4\xff\xe2\xff\xe2\xff\xe4\xff\xe6\xff\xe8\xff\xe9\xff\xe9\xff\xea\xff\xeb\xff\xec\xff\xec\xff\xec\xff\xed\xff\xef\xff\xf0\xff\xef\xff\xed\xff\xed\xff\xee\xff\xef\xff\xee\xff\xec\xff\xeb\xff\xeb\xff\xeb\xff\xea\xff\xea\xff\xe9\xff\xe9\xff\xe8\xff\xe8\xff\xe8\xff\xe7\xff\xe5\xff\xe4\xff\xe4\xff\xe6\xff\xe8\xff\xe8\xff\xe6\xff\xe4\xff\xe4\xff\xe5\xff\xe6\xff\xe6\xff\xe5\xff\xe4\xff\xe3\xff\xe4\xff\xe4\xff\xe3\xff\xe1\xff\xe0\xff\xe0\xff\xe0\xff\xdf\xff\xde\xff\xde\xff\xdd\xff\xdb\xff\xda\xff\xda\xff\xda\xff\xd9\xff\xd8\xff\xd7\xff\xd8\xff\xd8\xff\xd6\xff\xd3\xff\xd2\xff\xd3\xff\xd5\xff\xd7\xff\xda\xff\xdc\xff\xde\xff\xde\xff\xde\xff\xdf\xff\xe0\xff\xe0\xff\xe0\xff\xe1\xff\xe3\xff\xe5\xff\xe4\xff\xe0\xff\xdd\xff\xdd\xff\xe1\xff\xe4\xff\xe4\xff\xe2\xff\xe1\xff\xe2\xff\xe3\xff\xe4\xff\xe5\xff\xe5\xff\xe5\xff\xe4\xff\xe4\xff\xe5\xff\xe6\xff\xe7\xff\xe7\xff\xe6\xff\xe6\xff\xe7\xff\xe7\xff\xe8\xff\xe8\xff\xe8\xff\xe8\xff\xe9\xff\xea\xff\xea\xff\xea\xff\xe9\xff\xe9\xff\xe9\xff\xe9\xff\xe9\xff\xe9\xff\xe8\xff\xe8\xff\xe8\xff\xe8\xff\xe9\xff\xe9\xff\xe8\xff\xe7\xff\xe6\xff\xe7\xff\xe7\xff\xe6\xff\xe5\xff\xe5\xff\xe5\xff\xe6\xff\xe5\xff\xe4\xff\xe4\xff\xe5\xff\xe4\xff\xe4\xff\xe3\xff\xe2\xff\xe2\xff\xe2\xff\xe1\xff\xe0\xff\xe0\xff\xdf\xff\xde\xff\xde\xff\xdd\xff\xdd\xff\xdc\xff\xdc\xff\xdb\xff\xdb\xff\xdb\xff\xda\xff\xda\xff\xda\xff\xda\xff\xd9\xff\xd9\xff\xd9\xff\xd8\xff\xd8\xff\xd9\xff\xd9\xff\xd9\xff\xd9\xff\xd9\xff\xda\xff\xda\xff\xda\xff\xda\xff\xdb\xff\xdb\xff\xdb\xff\xdc\xff\xdc\xff\xdc\xff\xdd\xff\xdd\xff\xde\xff\xde\xff\xdf\xff\xdf\xff\xe0\xff\xe0\xff\xe1\xff\xe1\xff\xe1\xff\xe2\xff\xe2\xff\xe3\xff\xe3\xff\xe3\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe3\xff\xe3\xff\xe3\xff\xe2\xff\xe2\xff\xe2\xff\xe2\xff\xe1\xff\xe1\xff\xe1\xff\xe1\xff' 10 | 11 | 12 | def get_private_key(): 13 | with open('../.YANDEX_PRIVATE_KEY.txt', 'rb') as f: 14 | return f.read() 15 | 16 | 17 | class RecognizeLongAudio(unittest.TestCase): 18 | def setUp(self): 19 | warnings.filterwarnings("ignore", category=ResourceWarning, message="unclosed.*") 20 | 21 | def test_init_wrong_description(self): 22 | session = Session(auth_type=Session.IAM_TOKEN, credential='lol', folder_id='ad') 23 | 24 | with self.assertRaises(ValueError): 25 | RecognitionLongAudio(session, 'acid', 'bucket', aws_credentials_description='l' * 257) 26 | 27 | def test_init(self): 28 | bucket_name = os.environ.get('BUCKET_NAME') 29 | service_account_id = os.environ.get('SERVICE_ACCOUNT_ID') 30 | key_id = os.environ.get('YANDEX_KEY_ID') 31 | private_key = get_private_key() 32 | jwt = generate_jwt(service_account_id, key_id, private_key) 33 | 34 | session = Session.from_jwt(jwt) 35 | recognize_long_audio = RecognitionLongAudio(session, service_account_id, bucket_name) 36 | self.assertIsInstance(recognize_long_audio._headers, dict) 37 | 38 | def test_get_aws_credentials(self): 39 | service_account_id = os.environ.get('SERVICE_ACCOUNT_ID') 40 | key_id = os.environ.get('YANDEX_KEY_ID') 41 | private_key = get_private_key() 42 | jwt = generate_jwt(service_account_id, key_id, private_key) 43 | 44 | session = Session.from_jwt(jwt) 45 | access_key_id, secret = RecognitionLongAudio.get_aws_credentials(session, service_account_id) 46 | self.assertIsInstance(access_key_id, str) 47 | self.assertIsInstance(secret, str) 48 | 49 | def test_init_from_aws_credentials(self): 50 | bucket_name = os.environ.get('BUCKET_NAME') 51 | service_account_id = os.environ.get('SERVICE_ACCOUNT_ID') 52 | key_id = os.environ.get('YANDEX_KEY_ID') 53 | private_key = get_private_key() 54 | jwt = generate_jwt(service_account_id, key_id, private_key) 55 | 56 | session = Session.from_jwt(jwt) 57 | access_key_id, secret = RecognitionLongAudio.get_aws_credentials(session, service_account_id) 58 | 59 | recognize_long_audio = RecognitionLongAudio(session, service_account_id, bucket_name, 60 | aws_access_key_id=access_key_id, aws_secret=secret) 61 | self.assertIsInstance(recognize_long_audio._headers, dict) 62 | 63 | def test_recognition(self): 64 | bucket_name = os.environ.get('BUCKET_NAME') 65 | service_account_id = os.environ.get('SERVICE_ACCOUNT_ID') 66 | key_id = os.environ.get('YANDEX_KEY_ID') 67 | private_key = get_private_key() 68 | jwt = generate_jwt(service_account_id, key_id, private_key) 69 | 70 | session = Session.from_jwt(jwt) 71 | recognize_long_audio = RecognitionLongAudio(session, service_account_id, bucket_name) 72 | 73 | self.path = os.path.join(os.path.dirname(__file__), 'test_rec.wav') 74 | with open(self.path, 'wb') as f: 75 | f.write(test_data) 76 | 77 | recognize_long_audio.send_for_recognition(self.path, audioEncoding='LINEAR16_PCM', sampleRateHertz='48000', 78 | audioChannelCount=1, rawResults=False) 79 | 80 | while True: 81 | time.sleep(2) 82 | if recognize_long_audio.get_recognition_results(): 83 | break 84 | 85 | data = recognize_long_audio.get_data() 86 | self.assertIsInstance(data, (list, type(None))) 87 | 88 | text = recognize_long_audio.get_raw_text() 89 | self.assertIsInstance(text, str) 90 | -------------------------------------------------------------------------------- /src/tests/test_short_audio_recognition.py: -------------------------------------------------------------------------------- 1 | import os 2 | import unittest 3 | 4 | import speechkit 5 | from speechkit import Session, ShortAudioRecognition 6 | from speechkit.auth import generate_jwt 7 | 8 | test_data = b'RIFFl@\x08\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00\x80\xbb\x00\x00\x00w\x01\x00\x02\x00\x10\x00LIST@\x00\x00\x00INFOINAM\x1d\x00\x00\x00\xd1\x83\xd0\xbb\xd0\xb8\xd1\x86\xd0\xb0 8 \xd0\x9c\xd0\xb0\xd1\x80\xd1\x82\xd0\xb0, 6 9\x00\x00ISFT\x0e\x00\x00\x00Lavf58.76.100\x00data\x00@\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x00\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x00\x02\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x00\x02\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x01\x00\x00\x00\x00\x00\x01\x00\x02\x00\x02\x00\x03\x00\x02\x00\x02\x00\x01\x00\xff\xff\xff\xff\x00\x00\xff\xff\xfe\xff\xff\xff\x02\x00\x03\x00\x00\x00\xfd\xff\xfe\xff\x02\x00\x03\x00\x01\x00\xfe\xff\x01\x00\x04\x00\x03\x00\xfe\xff\xfb\xff\xfd\xff\x01\x00\x02\x00\x00\x00\xfc\xff\xfb\xff\xfc\xff\xff\xff\x02\x00\xff\xff\xf2\xff\xe0\xff\xd3\xff\xcf\xff\xd0\xff\xcc\xff\xc4\xff\xbd\xff\xb5\xff\xa5\xff\x8d\xfft\xffd\xff\\\xffX\xffV\xffV\xffV\xffN\xff?\xff1\xff/\xff8\xffA\xffG\xffJ\xffN\xffO\xffL\xffF\xffF\xffH\xffG\xff<\xff.\xff(\xff(\xff&\xff\x1e\xff\x16\xff\x18\xff#\xff0\xff8\xff<\xffA\xffF\xffH\xffH\xffL\xffV\xffb\xffm\xffs\xffv\xffy\xff}\xff\x85\xff\x8f\xff\x9a\xff\xa1\xff\xa8\xff\xaf\xff\xb4\xff\xb6\xff\xb7\xff\xbd\xff\xcc\xff\xdd\xff\xec\xff\xf9\xff\x08\x00\x18\x00\'\x003\x00?\x00J\x00Q\x00T\x00T\x00T\x00S\x00S\x00Z\x00n\x00\x87\x00\x99\x00\xa2\x00\xab\x00\xbb\x00\xcb\x00\xd4\x00\xd3\x00\xce\x00\xc9\x00\xc1\x00\xb4\x00\xa6\x00\x99\x00\x8b\x00~\x00w\x00z\x00\x80\x00\x80\x00w\x00n\x00k\x00o\x00q\x00n\x00j\x00k\x00p\x00q\x00h\x00Y\x00K\x00G\x00G\x00I\x00M\x00V\x00`\x00b\x00]\x00Y\x00X\x00T\x00D\x001\x00(\x00\'\x00 \x00\x0f\x00\xff\xff\xff\xff\t\x00\x0e\x00\x08\x00\xff\xff\xff\xff\x03\x00\x07\x00\t\x00\t\x00\x07\x00\x04\x00\x08\x00\x18\x00,\x005\x007\x00>\x00P\x00_\x00`\x00Y\x00Y\x00e\x00s\x00z\x00\x7f\x00\x85\x00\x8c\x00\x8f\x00\x8e\x00\x8d\x00\x8a\x00\x80\x00r\x00h\x00h\x00n\x00r\x00n\x00j\x00l\x00s\x00w\x00u\x00m\x00f\x00_\x00U\x00F\x008\x001\x00/\x00+\x00"\x00\x1a\x00\x16\x00\x0e\x00\xf9\xff\xda\xff\xbd\xff\xa7\xff\x90\xffs\xffX\xffH\xffA\xff6\xff#\xff\x12\xff\x0c\xff\x0b\xff\x05\xff\xf8\xfe\xed\xfe\xec\xfe\xed\xfe\xea\xfe\xe2\xfe\xde\xfe\xe0\xfe\xe4\xfe\xe5\xfe\xe4\xfe\xe3\xfe\xe1\xfe\xde\xfe\xdb\xfe\xdc\xfe\xe1\xfe\xe3\xfe\xe0\xfe\xde\xfe\xe1\xfe\xe7\xfe\xec\xfe\xf0\xfe\xfc\xfe\x10\xff!\xff\'\xff\'\xff-\xff<\xffJ\xffQ\xffV\xff]\xffe\xfff\xffa\xff\\\xff\\\xff`\xffh\xffs\xff\x81\xff\x8d\xff\x9a\xff\xa9\xff\xbc\xff\xcf\xff\xdf\xff\xf1\xff\x06\x00\x18\x00\x1f\x00!\x00,\x00E\x00^\x00m\x00v\x00\x82\x00\x91\x00\x9b\x00\x9f\x00\xa7\x00\xb8\x00\xcb\x00\xd9\x00\xe2\x00\xee\x00\xfb\x00\x04\x01\x05\x01\x02\x01\x01\x01\x01\x01\xff\x00\xfa\x00\xf4\x00\xec\x00\xe5\x00\xe3\x00\xe6\x00\xed\x00\xf5\x00\x01\x01\x0e\x01\x14\x01\x14\x01\x11\x01\x14\x01\x19\x01\x19\x01\x11\x01\x06\x01\xfc\x00\xf4\x00\xee\x00\xeb\x00\xe9\x00\xe5\x00\xde\x00\xd8\x00\xd5\x00\xce\x00\xbe\x00\xae\x00\xa8\x00\xaa\x00\xa3\x00\x91\x00\x83\x00\x86\x00\x91\x00\x90\x00\x82\x00v\x00r\x00l\x00[\x00H\x00A\x00F\x00G\x00=\x000\x00)\x00\'\x00$\x00\x1b\x00\x11\x00\n\x00\x07\x00\x05\x00\x01\x00\xf8\xff\xe9\xff\xd8\xff\xcc\xff\xc3\xff\xb6\xff\xa2\xff\x91\xff\x8a\xff\x90\xff\x9b\xff\xa4\xff\xad\xff\xba\xff\xcb\xff\xda\xff\xe5\xff\xef\xff\xf9\xff\xff\xff\xfe\xff\xfa\xff\xfa\xff\x02\x00\x08\x00\n\x00\x0e\x00\x1e\x004\x00D\x00K\x00U\x00k\x00\x84\x00\x92\x00\x99\x00\xa9\x00\xc3\x00\xd9\x00\xe3\x00\xec\x00\x02\x01\x1c\x01.\x017\x01D\x01X\x01d\x01^\x01T\x01U\x01^\x01^\x01P\x01C\x01C\x01N\x01W\x01\\\x01b\x01l\x01w\x01\x7f\x01\x84\x01\x83\x01|\x01u\x01q\x01o\x01g\x01W\x01F\x01<\x017\x012\x01)\x01"\x01\x1d\x01\x1b\x01\x16\x01\n\x01\xf5\x00\xd7\x00\xb6\x00\x9c\x00\x87\x00o\x00S\x007\x00$\x00\x1c\x00\x14\x00\x07\x00\xf4\xff\xe1\xff\xd0\xff\xc1\xff\xb1\xff\x9f\xff\x8e\xff\x82\xff|\xffz\xfft\xffj\xff`\xffZ\xffT\xffL\xffC\xff:\xff4\xff-\xff%\xff\x1b\xff\x11\xff\x08\xff\xff\xfe\xfa\xfe\xf8\xfe\xf7\xfe\xf3\xfe\xec\xfe\xe4\xfe\xdf\xfe\xe0\xfe\xe5\xfe\xed\xfe\xf4\xfe\xfd\xfe\r\xff\x1f\xff,\xff.\xff,\xff3\xffE\xffY\xfff\xffq\xff\x80\xff\x98\xff\xb8\xff\xd9\xff\xf5\xff\x06\x00\x10\x00\x1d\x00.\x00<\x00<\x005\x004\x00:\x00:\x00&\x00\n\x00\xf8\xff\xf5\xff\xf6\xff\xf2\xff\xef\xff\xf3\xff\xfa\xff\xfc\xff\xf9\xff\xfb\xff\x00\x00\x03\x00\x01\x00\xff\xff\x04\x00\x0c\x00\x10\x00\x0e\x00\n\x00\x0b\x00\r\x00\x0f\x00\x0e\x00\x0c\x00\x0c\x00\x0c\x00\x0e\x00\r\x00\x0b\x00\t\x00\x0c\x00\x10\x00\x0f\x00\t\x00\x02\x00\x02\x00\x07\x00\n\x00\n\x00\t\x00\t\x00\t\x00\x07\x00\x06\x00\x05\x00\x04\x00\x01\x00\x00\x00\x01\x00\x00\x00\xfe\xff\xfb\xff\xfb\xff\xfc\xff\xfb\xff\xf8\xff\xf5\xff\xf7\xff\xf9\xff\xf7\xff\xf2\xff\xf1\xff\xf4\xff\xf7\xff\xf5\xff\xf2\xff\xf1\xff\xf2\xff\xf3\xff\xf3\xff\xf2\xff\xf2\xff\xf2\xff\xf1\xff\xef\xff\xed\xff\xec\xff\xed\xff\xef\xff\xf0\xff\xf1\xff\xf2\xff\xf3\xff\xf4\xff\xf5\xff\xf3\xff\xf0\xff\xee\xff\xed\xff\xee\xff\xed\xff\xeb\xff\xea\xff\xeb\xff\xec\xff\xeb\xff\xe9\xff\xe8\xff\xea\xff\xec\xff\xec\xff\xea\xff\xe9\xff\xea\xff\xeb\xff\xea\xff\xe9\xff\xe8\xff\xe9\xff\xe9\xff\xea\xff\xea\xff\xe8\xff\xe5\xff\xe2\xff\xe2\xff\xe4\xff\xe4\xff\xe2\xff\xdf\xff\xdf\xff\xe0\xff\xe0\xff\xde\xff\xdd\xff\xdc\xff\xda\xff\xd9\xff\xd9\xff\xdb\xff\xdd\xff\xdc\xff\xd9\xff\xd8\xff\xda\xff\xdb\xff\xdb\xff\xdc\xff\xde\xff\xdd\xff\xda\xff\xd7\xff\xd7\xff\xd8\xff\xd8\xff\xd7\xff\xd7\xff\xd9\xff\xda\xff\xd8\xff\xd6\xff\xd5\xff\xd5\xff\xd5\xff\xd5\xff\xd5\xff\xd5\xff\xd5\xff\xd6\xff\xda\xff\xdd\xff\xde\xff\xde\xff\xde\xff\xe1\xff\xe2\xff\xe1\xff\xe0\xff\xe1\xff\xe3\xff\xe4\xff\xe2\xff\xe1\xff\xe3\xff\xe4\xff\xe4\xff\xe2\xff\xe2\xff\xe4\xff\xe6\xff\xe8\xff\xe9\xff\xe9\xff\xea\xff\xeb\xff\xec\xff\xec\xff\xec\xff\xed\xff\xef\xff\xf0\xff\xef\xff\xed\xff\xed\xff\xee\xff\xef\xff\xee\xff\xec\xff\xeb\xff\xeb\xff\xeb\xff\xea\xff\xea\xff\xe9\xff\xe9\xff\xe8\xff\xe8\xff\xe8\xff\xe7\xff\xe5\xff\xe4\xff\xe4\xff\xe6\xff\xe8\xff\xe8\xff\xe6\xff\xe4\xff\xe4\xff\xe5\xff\xe6\xff\xe6\xff\xe5\xff\xe4\xff\xe3\xff\xe4\xff\xe4\xff\xe3\xff\xe1\xff\xe0\xff\xe0\xff\xe0\xff\xdf\xff\xde\xff\xde\xff\xdd\xff\xdb\xff\xda\xff\xda\xff\xda\xff\xd9\xff\xd8\xff\xd7\xff\xd8\xff\xd8\xff\xd6\xff\xd3\xff\xd2\xff\xd3\xff\xd5\xff\xd7\xff\xda\xff\xdc\xff\xde\xff\xde\xff\xde\xff\xdf\xff\xe0\xff\xe0\xff\xe0\xff\xe1\xff\xe3\xff\xe5\xff\xe4\xff\xe0\xff\xdd\xff\xdd\xff\xe1\xff\xe4\xff\xe4\xff\xe2\xff\xe1\xff\xe2\xff\xe3\xff\xe4\xff\xe5\xff\xe5\xff\xe5\xff\xe4\xff\xe4\xff\xe5\xff\xe6\xff\xe7\xff\xe7\xff\xe6\xff\xe6\xff\xe7\xff\xe7\xff\xe8\xff\xe8\xff\xe8\xff\xe8\xff\xe9\xff\xea\xff\xea\xff\xea\xff\xe9\xff\xe9\xff\xe9\xff\xe9\xff\xe9\xff\xe9\xff\xe8\xff\xe8\xff\xe8\xff\xe8\xff\xe9\xff\xe9\xff\xe8\xff\xe7\xff\xe6\xff\xe7\xff\xe7\xff\xe6\xff\xe5\xff\xe5\xff\xe5\xff\xe6\xff\xe5\xff\xe4\xff\xe4\xff\xe5\xff\xe4\xff\xe4\xff\xe3\xff\xe2\xff\xe2\xff\xe2\xff\xe1\xff\xe0\xff\xe0\xff\xdf\xff\xde\xff\xde\xff\xdd\xff\xdd\xff\xdc\xff\xdc\xff\xdb\xff\xdb\xff\xdb\xff\xda\xff\xda\xff\xda\xff\xda\xff\xd9\xff\xd9\xff\xd9\xff\xd8\xff\xd8\xff\xd9\xff\xd9\xff\xd9\xff\xd9\xff\xd9\xff\xda\xff\xda\xff\xda\xff\xda\xff\xdb\xff\xdb\xff\xdb\xff\xdc\xff\xdc\xff\xdc\xff\xdd\xff\xdd\xff\xde\xff\xde\xff\xdf\xff\xdf\xff\xe0\xff\xe0\xff\xe1\xff\xe1\xff\xe1\xff\xe2\xff\xe2\xff\xe3\xff\xe3\xff\xe3\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe4\xff\xe3\xff\xe3\xff\xe3\xff\xe2\xff\xe2\xff\xe2\xff\xe2\xff\xe1\xff\xe1\xff\xe1\xff\xe1\xff' 9 | 10 | 11 | def get_private_key(): 12 | with open('../.YANDEX_PRIVATE_KEY.txt', 'rb') as f: 13 | return f.read() 14 | 15 | 16 | class RecognizeShortAudioTestCaseApiKey(unittest.TestCase): 17 | def setUp(self) -> None: 18 | api_key = os.environ.get('SERVICE_API_KEY') 19 | folder_id = os.environ.get('CATALOG') 20 | 21 | session = Session.from_api_key(api_key, folder_id) 22 | self.recognize_short_audio = ShortAudioRecognition(session) 23 | 24 | def test_init(self): 25 | self.assertIsInstance(self.recognize_short_audio._headers, dict) 26 | 27 | def test_wrong_catalog(self): 28 | with self.assertRaises(speechkit.exceptions.RequestError): 29 | api_key = os.environ.get('SERVICE_API_KEY') 30 | 31 | session = Session.from_api_key(api_key, 'lol') 32 | recognize_short_audio = ShortAudioRecognition(session) 33 | 34 | recognize_short_audio.recognize(bytes()) 35 | 36 | def test_recognize(self): 37 | text = self.recognize_short_audio.recognize( 38 | test_data, format='lpcm', sampleRateHertz='48000' 39 | ) 40 | self.assertIsInstance(text, str) 41 | 42 | 43 | class RecognizeShortAudioTestCaseJwt(unittest.TestCase): 44 | def setUp(self) -> None: 45 | service_account_id = os.environ.get('SERVICE_ACCOUNT_ID') 46 | key_id = os.environ.get('YANDEX_KEY_ID') 47 | private_key = get_private_key() 48 | jwt = generate_jwt(service_account_id, key_id, private_key) 49 | 50 | session = Session.from_jwt(jwt) 51 | 52 | self.recognize_short_audio = ShortAudioRecognition(session) 53 | 54 | def test_init(self): 55 | self.assertIsInstance(self.recognize_short_audio._headers, dict) 56 | 57 | def test_wrong_catalog(self): 58 | with self.assertRaises(speechkit.exceptions.RequestError): 59 | api_key = os.environ.get('SERVICE_API_KEY') 60 | 61 | session = Session.from_api_key(api_key, 'lol') 62 | recognize_short_audio = ShortAudioRecognition(session) 63 | 64 | recognize_short_audio.recognize(bytes()) 65 | 66 | def test_recognize(self): 67 | text = self.recognize_short_audio.recognize( 68 | test_data, format='lpcm', sampleRateHertz='48000' 69 | ) 70 | self.assertIsInstance(text, str) 71 | -------------------------------------------------------------------------------- /src/tests/test_speech_synthesis.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pathlib 3 | import unittest 4 | 5 | from speechkit import SpeechSynthesis, Session 6 | 7 | 8 | class SynthesizeAudio(unittest.TestCase): 9 | def test_init(self): 10 | api_key = os.environ.get('SERVICE_API_KEY') 11 | session = Session.from_api_key(api_key) 12 | synthesize_audio = SpeechSynthesis(session) 13 | self.assertIsInstance(synthesize_audio._headers, dict) 14 | 15 | def test_synthesize(self): 16 | api_key = os.environ.get('SERVICE_API_KEY') 17 | session = Session.from_api_key(api_key) 18 | synthesize_audio = SpeechSynthesis(session) 19 | 20 | self.path = os.path.join(os.path.dirname(__file__), 'test_synth.wav') 21 | synthesize_audio.synthesize( 22 | self.path, text='text', 23 | voice='oksana', format='lpcm', sampleRateHertz='16000' 24 | ) 25 | self.assertTrue(pathlib.Path(self.path).resolve().is_file()) 26 | 27 | def test_assert_synthesize(self): 28 | api_key = os.environ.get('SERVICE_API_KEY') 29 | session = Session.from_api_key(api_key) 30 | synthesize_audio = SpeechSynthesis(session) 31 | 32 | with self.assertRaises(ValueError): 33 | synthesize_audio.synthesize( 34 | 'ok', text='t' * 5001 35 | ) 36 | 37 | def test_synthesize_stream(self): 38 | api_key = os.environ.get('SERVICE_API_KEY') 39 | session = Session.from_api_key(api_key) 40 | synthesize_audio = SpeechSynthesis(session) 41 | 42 | data = synthesize_audio.synthesize_stream( 43 | text='text', voice='oksana', format='lpcm', 44 | sampleRateHertz='16000' 45 | ) 46 | self.assertIsInstance(data, bytes) 47 | -------------------------------------------------------------------------------- /src/tests/test_streaming_recognition.py: -------------------------------------------------------------------------------- 1 | import os 2 | from unittest import TestCase 3 | 4 | from speechkit import Session, DataStreamingRecognition 5 | from speechkit.auth import generate_jwt 6 | import speechkit 7 | 8 | 9 | def get_private_key(): 10 | with open('../.YANDEX_PRIVATE_KEY.txt', 'rb') as f: 11 | return f.read() 12 | 13 | 14 | class DataStreamingRecognitionTestCase(TestCase): 15 | def setUp(self) -> None: 16 | service_account_id = os.environ.get('SERVICE_ACCOUNT_ID') 17 | key_id = os.environ.get('YANDEX_KEY_ID') 18 | private_key = get_private_key() 19 | 20 | jwt = generate_jwt(service_account_id, key_id, private_key) 21 | self.session = Session.from_jwt(jwt) 22 | 23 | def test_init(self): 24 | data_streaming_recognition = DataStreamingRecognition( 25 | self.session, 26 | language_code='ru-RU', 27 | audio_encoding='LINEAR16_PCM', 28 | sample_rate_hertz=8000, 29 | partial_results=False, 30 | single_utterance=True, 31 | ) 32 | self.assertIsInstance(data_streaming_recognition._headers, tuple) 33 | 34 | def test__gen(self): 35 | def gen_func(): 36 | yield bytes() 37 | 38 | data_streaming_recognition = DataStreamingRecognition( 39 | self.session, 40 | language_code='ru-RU', 41 | audio_encoding='LINEAR16_PCM', 42 | sample_rate_hertz=8000, 43 | partial_results=False, 44 | single_utterance=True, 45 | ) 46 | next(data_streaming_recognition._gen(gen_func)) 47 | self.assertIsInstance(next(data_streaming_recognition._gen(gen_func)), 48 | speechkit._recognition.yandex.cloud.ai.stt.v2.stt_service_pb2.StreamingRecognitionRequest) 49 | 50 | # def test_recognize_raw(self): 51 | # self.fail() 52 | # 53 | # def test_recognize(self): 54 | # self.fail() 55 | -------------------------------------------------------------------------------- /src/tests/test_utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import unittest 3 | 4 | from speechkit import Session 5 | from speechkit.utils import list_of_service_accounts 6 | 7 | 8 | class ListOfServiceAccountsTestCase(unittest.TestCase): 9 | def test_request(self): 10 | api_key = os.environ.get('YANDEX_OAUTH') 11 | folder_id = os.environ.get('CATALOG') 12 | 13 | session = Session.from_yandex_passport_oauth_token(api_key, folder_id) 14 | 15 | data = list_of_service_accounts(session) 16 | self.assertIsInstance(data, list) 17 | 18 | def invalid_session_from_api_key(self): 19 | session = Session.from_api_key('api_key', 'sdsas') 20 | with self.assertRaises(ValueError): 21 | list_of_service_accounts(session) 22 | 23 | def invalid_session_no_folder_id(self): 24 | api_key = os.environ.get('YANDEX_OAUTH') 25 | session = Session.from_api_key(api_key) 26 | with self.assertRaises(ValueError): 27 | list_of_service_accounts(session) 28 | --------------------------------------------------------------------------------