Google Cloud Speech API - certificate verify failed in Python - python-3.x

I'm using SpeechRecognition library.
import speech_recognition as sr
AUDIO_FILE = 'test_audio.wav'
with open("api-key.json") as f:
GOOGLE_CLOUD_SPEECH_CREDENTIALS = f.read()
r = sr.Recognizer()
with sr.AudioFile(AUDIO_FILE) as source:
audio = r.record(source)
print('Starting recognition...')
print(r.recognize_google_cloud(audio, credentials_json=GOOGLE_CLOUD_SPEECH_CREDENTIALS))
print('Completed')
When above code is run, an error occurs -
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify
failed (_ssl.c:777)
The audio file and api-key files are in place.

I managed to consume through proxy by directly editing the code of google speech client library in python. Specifically I edited the file at(it might be different in your case):
lib/python3.6/site-packages/google/auth/transport/requests.py
the class Request, method call, there is a line like:
response = self.session.request(method, url, data=body, headers=headers, timeout=timeout)
I added the parameter verify=False to that call which will just ignore SSL certificate verifications. However that is not recommended since incurs in security issues. If you happen to have the certificates of the CA in the proxy you replace verify=False with cert="/local/address/to/ca/cert". Here is how I have it working:
response = self.session.request(method, url, data=body, headers=headers, timeout=timeout,verify=False,**kwargs)

Related

How can I install the SSL certificates in a virtual environment in Python on a Mac?

When I try to make a request to some urls, I get an SSLError. I think it is because I didn't install the right certificates in my Python3.9 virtual environment.
This is my code:
import requests
url = "https://survey.unibz.it/opinio/s?s=12131"
r = requests.get(url)
print(r)
tjos os mymy file structure
the error I get
This isn't an issue with your code. That website has their certificate mis-configured.
You can skip validating their cert with
r = requests.get(url, verify=False)
Keep in mind if you do this, it's possible you're not talking to the owners of the website but someone impersonating them.

Python OAuth after few days fails refreshing tokens with "invalid_grant" error

I have a Python app running on Raspberry Pi that starts a livestream to a YouTube channel that I manage. This is the code that I use to authenticate:
import google_auth_oauthlib.flow
import googleapiclient.discovery
import googleapiclient.errors
import google.auth.transport.requests
import google.oauth2.credentials
import requests
CLIENT_SECRETS_FILE = "client_secrets.json"
YOUTUBE_READ_WRITE_SCOPE = "https://www.googleapis.com/auth/youtube"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"
def get_authenticated_service(args):
credentials = None
credentials_json_file = "youtube-%s.json" % slugify(args.oauth2_name)
if os.path.exists(credentials_json_file):
# load credentials from file
with open(credentials_json_file, encoding='utf-8') as f:
credentials_json = json.load(f)
credentials = google.oauth2.credentials.Credentials.from_authorized_user_info(credentials_json)
if not credentials or not credentials.valid:
# no credentials file or invalid credentials
if credentials and credentials.expired and credentials.refresh_token:
# refresh
request = google.auth.transport.requests.Request()
credentials.refresh(request)
else:
# re-authenticate
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, [YOUTUBE_READ_WRITE_SCOPE])
credentials = flow.run_console()
# save credentials to file
credentials_json = credentials.to_json()
with open(credentials_json_file, 'w', encoding='utf-8') as f:
f.write(credentials_json)
return googleapiclient.discovery.build(
YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, credentials=credentials)
When I run my app a first time, I must authenticate. The credentials are stored in a JSON file that looks like this:
{
"token": "...",
"refresh_token": "...",
"token_uri": "https://oauth2.googleapis.com/token",
"client_id": "....apps.googleusercontent.com",
"client_secret": "...",
"scopes": ["https://www.googleapis.com/auth/youtube"],
"expiry": "2021-02-28T09:27:44.221302Z"
}
When I re-run the app later on, I don't have to re-authenticate. That works fine.
But after 2-3 days, I get this error:
Traceback (most recent call last):
File "./create_broadcast.py", line 188, in <module>
youtube = get_authenticated_service(args)
File "./create_broadcast.py", line 83, in get_authenticated_service
credentials.refresh(request)
File "/home/pi/.local/lib/python3.7/site-packages/google/oauth2/credentials.py", line 214, in refresh
scopes,
File "/home/pi/.local/lib/python3.7/site-packages/google/oauth2/_client.py", line 248, in refresh_grant
response_data = _token_endpoint_request(request, token_uri, body)
File "/home/pi/.local/lib/python3.7/site-packages/google/oauth2/_client.py", line 124, in _token_endpoint_request
_handle_error_response(response_body)
File "/home/pi/.local/lib/python3.7/site-packages/google/oauth2/_client.py", line 60, in _handle_error_response
raise exceptions.RefreshError(error_details, response_body)
google.auth.exceptions.RefreshError: ('invalid_grant: Token has been expired or revoked.', '{\n "error": "invalid_grant",\n "error_description": "Token has been expired or revoked."\n}')
The workaround is to delete the credentials file and re-authenticate. But I'd expect the credentials refresh to still work after a couple of days!
I do have NTP installed and running. I didn't manually revoke the token. I didn't change my Google password. I didn't generate a lot of other tokens elsewhere. I did none of the things that are told elsewhere to cause this error.
One thing to note: the app is not verified, because it's only meant for internal use. Still this shouldn't impact the lifespan of the refresh token, should it?
What could make that refreshing works after 1 day or after 2 days, but not anymore after 3 days?!
Best regards,
Vic
I very much presume that your corresponding Google project shows -- from within the Developers Console, on the page OAuth consent screen -- your app to have its Publishing status set as Testing.
According to the official documentation, your refresh tokens are subject to the following restrictions:
Refresh token expiration
You must write your code to anticipate the possibility that a granted refresh token might no longer work. A refresh token might stop working for one of these reasons:
[...]
A Google Cloud Platform project with an OAuth consent screen configured for an external user type and a publishing status of "Testing" is issued a refresh token expiring in 7 days.
Until your app's publishing status becomes set to in production -- i.e. your app gets audited by Google --, the above restriction implies that you have to run to successful completion an OAuth authentication/authorization flow every week for to obtain new refresh tokens (that have a limited lifespan of only 7 days).

How do I use API key credential with Google text-to-speech client library methods?

I'd like to instantiate a TextToSpeechClient() with an API key rather than service account credentials provided in a global GOOGLE_APPLICATION_CREDENTIALS variable. Specifically, I'd like to use the following function provided on the relevant website, but I'm unable to instantiate client due to lack of credentials.
def synthesize_text(text):
"""Synthesizes speech from the input string of text."""
from google.cloud import texttospeech
client = texttospeech.TextToSpeechClient()
input_text = texttospeech.types.SynthesisInput(text=text)
# Note: the voice can also be specified by name.
# Names of voices can be retrieved with client.list_voices().
voice = texttospeech.types.VoiceSelectionParams(
language_code='en-US',
name='en-US-Standard-C',
ssml_gender=texttospeech.enums.SsmlVoiceGender.FEMALE)
audio_config = texttospeech.types.AudioConfig(
audio_encoding=texttospeech.enums.AudioEncoding.MP3)
response = client.synthesize_speech(input_text, voice, audio_config)
# The response's audio_content is binary.
with open('output.mp3', 'wb') as out:
out.write(response.audio_content)
print('Audio content written to file "output.mp3"')
Alternately, I get past the credentials issue when I tried using the JSON from the Google text-to-speech website at https://cloud.google.com/text-to-speech and the requests package as follows:
r = requests.post('https://texttospeech.googleapis.com/v1beta1/text:synthesize?key=API_KEY', data = json.dumps(data))
and I receive a response with text content. If I was to do it this way, how do I save the content I receive as an audio file?

using requests.post to send a request with a certificate

I am trying to send some data via a web based api. The client has given me an example snippet of code to test everything.
My problem below is how to use my certificate.
Their example
response = requests.post(url, data=data, headers=headers, cert=('certificate.cer','keyfile.key'))
I tried
response = requests.post(url, data=data, headers=headers, cert=('C:\MyPath\My-certs.p12','password'))
However I get the error,
OSError: Could not find the TLS key file, invalid path: password
I have written a C# example and the code works, so I know the certificate and the other pieces are ok. I just can't get the certificate to work in python
Your certificate file is P12, which isn't supported by requests yet. You have two options:
Convert the P12 file into separate public certificate and private key files. For Linux or Mac, use this. Then you can use the separate files as a tuple in cert.
Use requests-pkcs12 which has support for P12 files:
--
from requests_pkcs12 import post
response = post(url, data=data, headers=headers, pkcs12_filename='C:\MyPath\My-certs.p12', pkcs12_password='password')

urlopen(url) 403 Forbidden error

I'm using python to open an URL with the following code and sometimes I get this error:
from urllib import urlopen
url = "http://www.gutenberg.org/files/2554/2554.txt"
raw = urlopen(url).read()
error:'\n\n403 Forbidden\n\nForbidden\nYou don\'t have permission to access /files/2554/2554.txt\non this server.\n\nApache Server at www.gutenberg.org Port 80\n\n'
What is this?
Thank you
This is the web page blocking Python access as it is making requests with the header 'User-Agent'.
To get around this, download the 'urllib2' module and use this code:
req = urllib2.Request(url, headers ={'User-Agent':'Chrome'})
raw = urllib2.urlopen(req).read()
You are know accessing the site with the header 'Chrome' and should no longer be forbidden (I tried it myself and it worked).
Hope this helps.

Resources