1# -*- coding: utf-8 -*- 2# Copyright 2020 Google LLC 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16from collections import OrderedDict 17import functools 18import re 19from typing import ( 20 Dict, 21 AsyncIterable, 22 Awaitable, 23 AsyncIterator, 24 Sequence, 25 Tuple, 26 Type, 27 Union, 28) 29import pkg_resources 30 31from google.api_core.client_options import ClientOptions # type: ignore 32from google.api_core import exceptions as core_exceptions # type: ignore 33from google.api_core import gapic_v1 # type: ignore 34from google.api_core import retry as retries # type: ignore 35from google.auth import credentials as ga_credentials # type: ignore 36from google.oauth2 import service_account # type: ignore 37 38OptionalRetry = Union[retries.Retry, object] 39 40from google.api_core import operation # type: ignore 41from google.api_core import operation_async # type: ignore 42from google.cloud.speech_v1p1beta1.types import cloud_speech 43from google.protobuf import duration_pb2 # type: ignore 44from google.rpc import status_pb2 # type: ignore 45from .transports.base import SpeechTransport, DEFAULT_CLIENT_INFO 46from .transports.grpc_asyncio import SpeechGrpcAsyncIOTransport 47from .client import SpeechClient 48 49 50class SpeechAsyncClient: 51 """Service that implements Google Cloud Speech API.""" 52 53 _client: SpeechClient 54 55 DEFAULT_ENDPOINT = SpeechClient.DEFAULT_ENDPOINT 56 DEFAULT_MTLS_ENDPOINT = SpeechClient.DEFAULT_MTLS_ENDPOINT 57 58 custom_class_path = staticmethod(SpeechClient.custom_class_path) 59 parse_custom_class_path = staticmethod(SpeechClient.parse_custom_class_path) 60 phrase_set_path = staticmethod(SpeechClient.phrase_set_path) 61 parse_phrase_set_path = staticmethod(SpeechClient.parse_phrase_set_path) 62 common_billing_account_path = staticmethod(SpeechClient.common_billing_account_path) 63 parse_common_billing_account_path = staticmethod( 64 SpeechClient.parse_common_billing_account_path 65 ) 66 common_folder_path = staticmethod(SpeechClient.common_folder_path) 67 parse_common_folder_path = staticmethod(SpeechClient.parse_common_folder_path) 68 common_organization_path = staticmethod(SpeechClient.common_organization_path) 69 parse_common_organization_path = staticmethod( 70 SpeechClient.parse_common_organization_path 71 ) 72 common_project_path = staticmethod(SpeechClient.common_project_path) 73 parse_common_project_path = staticmethod(SpeechClient.parse_common_project_path) 74 common_location_path = staticmethod(SpeechClient.common_location_path) 75 parse_common_location_path = staticmethod(SpeechClient.parse_common_location_path) 76 77 @classmethod 78 def from_service_account_info(cls, info: dict, *args, **kwargs): 79 """Creates an instance of this client using the provided credentials 80 info. 81 82 Args: 83 info (dict): The service account private key info. 84 args: Additional arguments to pass to the constructor. 85 kwargs: Additional arguments to pass to the constructor. 86 87 Returns: 88 SpeechAsyncClient: The constructed client. 89 """ 90 return SpeechClient.from_service_account_info.__func__(SpeechAsyncClient, info, *args, **kwargs) # type: ignore 91 92 @classmethod 93 def from_service_account_file(cls, filename: str, *args, **kwargs): 94 """Creates an instance of this client using the provided credentials 95 file. 96 97 Args: 98 filename (str): The path to the service account private key json 99 file. 100 args: Additional arguments to pass to the constructor. 101 kwargs: Additional arguments to pass to the constructor. 102 103 Returns: 104 SpeechAsyncClient: The constructed client. 105 """ 106 return SpeechClient.from_service_account_file.__func__(SpeechAsyncClient, filename, *args, **kwargs) # type: ignore 107 108 from_service_account_json = from_service_account_file 109 110 @property 111 def transport(self) -> SpeechTransport: 112 """Returns the transport used by the client instance. 113 114 Returns: 115 SpeechTransport: The transport used by the client instance. 116 """ 117 return self._client.transport 118 119 get_transport_class = functools.partial( 120 type(SpeechClient).get_transport_class, type(SpeechClient) 121 ) 122 123 def __init__( 124 self, 125 *, 126 credentials: ga_credentials.Credentials = None, 127 transport: Union[str, SpeechTransport] = "grpc_asyncio", 128 client_options: ClientOptions = None, 129 client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, 130 ) -> None: 131 """Instantiates the speech client. 132 133 Args: 134 credentials (Optional[google.auth.credentials.Credentials]): The 135 authorization credentials to attach to requests. These 136 credentials identify the application to the service; if none 137 are specified, the client will attempt to ascertain the 138 credentials from the environment. 139 transport (Union[str, ~.SpeechTransport]): The 140 transport to use. If set to None, a transport is chosen 141 automatically. 142 client_options (ClientOptions): Custom options for the client. It 143 won't take effect if a ``transport`` instance is provided. 144 (1) The ``api_endpoint`` property can be used to override the 145 default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT 146 environment variable can also be used to override the endpoint: 147 "always" (always use the default mTLS endpoint), "never" (always 148 use the default regular endpoint) and "auto" (auto switch to the 149 default mTLS endpoint if client certificate is present, this is 150 the default value). However, the ``api_endpoint`` property takes 151 precedence if provided. 152 (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable 153 is "true", then the ``client_cert_source`` property can be used 154 to provide client certificate for mutual TLS transport. If 155 not provided, the default SSL client certificate will be used if 156 present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not 157 set, no client certificate will be used. 158 159 Raises: 160 google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport 161 creation failed for any reason. 162 """ 163 self._client = SpeechClient( 164 credentials=credentials, 165 transport=transport, 166 client_options=client_options, 167 client_info=client_info, 168 ) 169 170 async def recognize( 171 self, 172 request: Union[cloud_speech.RecognizeRequest, dict] = None, 173 *, 174 config: cloud_speech.RecognitionConfig = None, 175 audio: cloud_speech.RecognitionAudio = None, 176 retry: OptionalRetry = gapic_v1.method.DEFAULT, 177 timeout: float = None, 178 metadata: Sequence[Tuple[str, str]] = (), 179 ) -> cloud_speech.RecognizeResponse: 180 r"""Performs synchronous speech recognition: receive 181 results after all audio has been sent and processed. 182 183 Args: 184 request (Union[google.cloud.speech_v1p1beta1.types.RecognizeRequest, dict]): 185 The request object. The top-level message sent by the 186 client for the `Recognize` method. 187 config (:class:`google.cloud.speech_v1p1beta1.types.RecognitionConfig`): 188 Required. Provides information to the 189 recognizer that specifies how to process 190 the request. 191 192 This corresponds to the ``config`` field 193 on the ``request`` instance; if ``request`` is provided, this 194 should not be set. 195 audio (:class:`google.cloud.speech_v1p1beta1.types.RecognitionAudio`): 196 Required. The audio data to be 197 recognized. 198 199 This corresponds to the ``audio`` field 200 on the ``request`` instance; if ``request`` is provided, this 201 should not be set. 202 retry (google.api_core.retry.Retry): Designation of what errors, if any, 203 should be retried. 204 timeout (float): The timeout for this request. 205 metadata (Sequence[Tuple[str, str]]): Strings which should be 206 sent along with the request as metadata. 207 208 Returns: 209 google.cloud.speech_v1p1beta1.types.RecognizeResponse: 210 The only message returned to the client by the Recognize method. It 211 contains the result as zero or more sequential 212 SpeechRecognitionResult messages. 213 214 """ 215 # Create or coerce a protobuf request object. 216 # Sanity check: If we got a request object, we should *not* have 217 # gotten any keyword arguments that map to the request. 218 has_flattened_params = any([config, audio]) 219 if request is not None and has_flattened_params: 220 raise ValueError( 221 "If the `request` argument is set, then none of " 222 "the individual field arguments should be set." 223 ) 224 225 request = cloud_speech.RecognizeRequest(request) 226 227 # If we have keyword arguments corresponding to fields on the 228 # request, apply these. 229 if config is not None: 230 request.config = config 231 if audio is not None: 232 request.audio = audio 233 234 # Wrap the RPC method; this adds retry and timeout information, 235 # and friendly error handling. 236 rpc = gapic_v1.method_async.wrap_method( 237 self._client._transport.recognize, 238 default_retry=retries.Retry( 239 initial=0.1, 240 maximum=60.0, 241 multiplier=1.3, 242 predicate=retries.if_exception_type( 243 core_exceptions.DeadlineExceeded, 244 core_exceptions.ServiceUnavailable, 245 ), 246 deadline=5000.0, 247 ), 248 default_timeout=5000.0, 249 client_info=DEFAULT_CLIENT_INFO, 250 ) 251 252 # Send the request. 253 response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) 254 255 # Done; return the response. 256 return response 257 258 async def long_running_recognize( 259 self, 260 request: Union[cloud_speech.LongRunningRecognizeRequest, dict] = None, 261 *, 262 config: cloud_speech.RecognitionConfig = None, 263 audio: cloud_speech.RecognitionAudio = None, 264 retry: OptionalRetry = gapic_v1.method.DEFAULT, 265 timeout: float = None, 266 metadata: Sequence[Tuple[str, str]] = (), 267 ) -> operation_async.AsyncOperation: 268 r"""Performs asynchronous speech recognition: receive results via 269 the google.longrunning.Operations interface. Returns either an 270 ``Operation.error`` or an ``Operation.response`` which contains 271 a ``LongRunningRecognizeResponse`` message. For more information 272 on asynchronous speech recognition, see the 273 `how-to <https://cloud.google.com/speech-to-text/docs/async-recognize>`__. 274 275 Args: 276 request (Union[google.cloud.speech_v1p1beta1.types.LongRunningRecognizeRequest, dict]): 277 The request object. The top-level message sent by the 278 client for the `LongRunningRecognize` method. 279 config (:class:`google.cloud.speech_v1p1beta1.types.RecognitionConfig`): 280 Required. Provides information to the 281 recognizer that specifies how to process 282 the request. 283 284 This corresponds to the ``config`` field 285 on the ``request`` instance; if ``request`` is provided, this 286 should not be set. 287 audio (:class:`google.cloud.speech_v1p1beta1.types.RecognitionAudio`): 288 Required. The audio data to be 289 recognized. 290 291 This corresponds to the ``audio`` field 292 on the ``request`` instance; if ``request`` is provided, this 293 should not be set. 294 retry (google.api_core.retry.Retry): Designation of what errors, if any, 295 should be retried. 296 timeout (float): The timeout for this request. 297 metadata (Sequence[Tuple[str, str]]): Strings which should be 298 sent along with the request as metadata. 299 300 Returns: 301 google.api_core.operation_async.AsyncOperation: 302 An object representing a long-running operation. 303 304 The result type for the operation will be :class:`google.cloud.speech_v1p1beta1.types.LongRunningRecognizeResponse` The only message returned to the client by the LongRunningRecognize method. 305 It contains the result as zero or more sequential 306 SpeechRecognitionResult messages. It is included in 307 the result.response field of the Operation returned 308 by the GetOperation call of the 309 google::longrunning::Operations service. 310 311 """ 312 # Create or coerce a protobuf request object. 313 # Sanity check: If we got a request object, we should *not* have 314 # gotten any keyword arguments that map to the request. 315 has_flattened_params = any([config, audio]) 316 if request is not None and has_flattened_params: 317 raise ValueError( 318 "If the `request` argument is set, then none of " 319 "the individual field arguments should be set." 320 ) 321 322 request = cloud_speech.LongRunningRecognizeRequest(request) 323 324 # If we have keyword arguments corresponding to fields on the 325 # request, apply these. 326 if config is not None: 327 request.config = config 328 if audio is not None: 329 request.audio = audio 330 331 # Wrap the RPC method; this adds retry and timeout information, 332 # and friendly error handling. 333 rpc = gapic_v1.method_async.wrap_method( 334 self._client._transport.long_running_recognize, 335 default_timeout=5000.0, 336 client_info=DEFAULT_CLIENT_INFO, 337 ) 338 339 # Send the request. 340 response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) 341 342 # Wrap the response in an operation future. 343 response = operation_async.from_gapic( 344 response, 345 self._client._transport.operations_client, 346 cloud_speech.LongRunningRecognizeResponse, 347 metadata_type=cloud_speech.LongRunningRecognizeMetadata, 348 ) 349 350 # Done; return the response. 351 return response 352 353 def streaming_recognize( 354 self, 355 requests: AsyncIterator[cloud_speech.StreamingRecognizeRequest] = None, 356 *, 357 retry: OptionalRetry = gapic_v1.method.DEFAULT, 358 timeout: float = None, 359 metadata: Sequence[Tuple[str, str]] = (), 360 ) -> Awaitable[AsyncIterable[cloud_speech.StreamingRecognizeResponse]]: 361 r"""Performs bidirectional streaming speech recognition: 362 receive results while sending audio. This method is only 363 available via the gRPC API (not REST). 364 365 Args: 366 requests (AsyncIterator[`google.cloud.speech_v1p1beta1.types.StreamingRecognizeRequest`]): 367 The request object AsyncIterator. The top-level message sent by the 368 client for the `StreamingRecognize` method. Multiple 369 `StreamingRecognizeRequest` messages are sent. The first 370 message must contain a `streaming_config` message and 371 must not contain `audio_content`. All subsequent 372 messages must contain `audio_content` and must not 373 contain a `streaming_config` message. 374 retry (google.api_core.retry.Retry): Designation of what errors, if any, 375 should be retried. 376 timeout (float): The timeout for this request. 377 metadata (Sequence[Tuple[str, str]]): Strings which should be 378 sent along with the request as metadata. 379 380 Returns: 381 AsyncIterable[google.cloud.speech_v1p1beta1.types.StreamingRecognizeResponse]: 382 StreamingRecognizeResponse is the only message returned to the client by 383 StreamingRecognize. A series of zero or more 384 StreamingRecognizeResponse messages are streamed back 385 to the client. If there is no recognizable audio, and 386 single_utterance is set to false, then no messages 387 are streamed back to the client. 388 389 Here's an example of a series of 390 StreamingRecognizeResponses that might be returned 391 while processing audio: 392 393 1. results { alternatives { transcript: "tube" } 394 stability: 0.01 } 395 2. results { alternatives { transcript: "to be a" } 396 stability: 0.01 } 397 3. results { alternatives { transcript: "to be" } 398 stability: 0.9 } results { alternatives { 399 transcript: " or not to be" } stability: 0.01 } 400 4. 401 402 results { alternatives { transcript: "to be or not to be" 403 confidence: 0.92 } 404 405 alternatives { transcript: "to bee or not to bee" } 406 is_final: true } 407 408 5. results { alternatives { transcript: " that's" } 409 stability: 0.01 } 410 6. results { alternatives { transcript: " that is" } 411 stability: 0.9 } results { alternatives { 412 transcript: " the question" } stability: 0.01 } 413 7. 414 415 results { alternatives { transcript: " that is the question" 416 confidence: 0.98 } 417 418 alternatives { transcript: " that was the question" } 419 is_final: true } 420 421 Notes: 422 423 - Only two of the above responses #4 and #7 contain 424 final results; they are indicated by 425 is_final: true. Concatenating these together 426 generates the full transcript: "to be or not to be 427 that is the question". 428 - The others contain interim results. #3 and #6 429 contain two interim \`results`: the first portion 430 has a high stability and is less likely to change; 431 the second portion has a low stability and is very 432 likely to change. A UI designer might choose to 433 show only high stability results. 434 - The specific stability and confidence values shown 435 above are only for illustrative purposes. Actual 436 values may vary. 437 - 438 439 In each response, only one of these fields will be set: 440 error, speech_event_type, or one or more 441 (repeated) results. 442 443 """ 444 445 # Wrap the RPC method; this adds retry and timeout information, 446 # and friendly error handling. 447 rpc = gapic_v1.method_async.wrap_method( 448 self._client._transport.streaming_recognize, 449 default_retry=retries.Retry( 450 initial=0.1, 451 maximum=60.0, 452 multiplier=1.3, 453 predicate=retries.if_exception_type( 454 core_exceptions.DeadlineExceeded, 455 core_exceptions.ServiceUnavailable, 456 ), 457 deadline=5000.0, 458 ), 459 default_timeout=5000.0, 460 client_info=DEFAULT_CLIENT_INFO, 461 ) 462 463 # Send the request. 464 response = rpc(requests, retry=retry, timeout=timeout, metadata=metadata,) 465 466 # Done; return the response. 467 return response 468 469 async def __aenter__(self): 470 return self 471 472 async def __aexit__(self, exc_type, exc, tb): 473 await self.transport.close() 474 475 476try: 477 DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( 478 gapic_version=pkg_resources.get_distribution("google-cloud-speech",).version, 479 ) 480except pkg_resources.DistributionNotFound: 481 DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() 482 483 484__all__ = ("SpeechAsyncClient",) 485