Search code examples
pythonazuretext-to-speechaccess-tokenazure-cognitive-services

Cannot get access token for Azure Cognitive Services (for tts)


I can't seem to get authorization for the Azure cognitive services access token. I'm using the example code (modified to take my key) that the azure team posted to github.

I've gone through the documentation and as far as I can tell I'm doing everything right. I've also used the "Unified Speech Services for free trials" and that also doesn't work.

class TextToSpeech(object):
    def __init__(self, subscription_key):
        self.subscription_key = subscription_key
        self.tts = "testing the TTS abilities of Azure using python"
        #self.tts = input("What would you like to convert to speech: ")
        self.timestr = time.strftime("%Y%m%d-%H%M")
        self.access_token = None

    '''
    The TTS endpoint requires an access token. This method exchanges your
    subscription key for an access token that is valid for ten minutes.
    '''
    def get_token(self):
        fetch_token_url = "https://eastus.api.cognitive.microsoft.com/sts/v1.0/issuetoken"
        headers = {
            'Ocp-Apim-Subscription-Key': self.subscription_key
        }
        response = requests.post(fetch_token_url, headers=headers)
        self.access_token = str(response.text)

if __name__ == "__main__":
    app = TextToSpeech(subscription_key)
    app.get_token()

Here is the output of the access token

'{"error":{"code":"401","message": "Access denied due to invalid subscription key or wrong API endpoint. Make sure to provide a valid key for an active subscription and use a correct regional API endpoint for your resource."}}'

What I should be getting is the temporary access token but for some reason I get the above error and I have no idea why.


Solution

  • This error is due to you called the wrong endpoint . Pls try the code below to get started with your own subscription params in main method :

    import os, requests, time
    from xml.etree import ElementTree
    
    
    try: input = raw_input
    except NameError: pass
    
    
    
    class TextToSpeech(object):
        def __init__(self, subscription_key,region):
            self.subscription_key = subscription_key
            self.region =region
            self.tts = input("What would you like to convert to speech: ")
            self.timestr = time.strftime("%Y%m%d-%H%M")
            self.access_token = None
    
        def get_token(self):
            fetch_token_url = 'https://'+self.region+'.api.cognitive.microsoft.com/sts/v1.0/issuetoken'
            headers = {
                'Ocp-Apim-Subscription-Key': self.subscription_key
            }
            response = requests.post(fetch_token_url, headers=headers)
            self.access_token = str(response.text)
    
        def save_audio(self):
            base_url = 'https://'+self.region+'.tts.speech.microsoft.com/'
            path = 'cognitiveservices/v1'
            constructed_url = base_url + path
            headers = {
                'Authorization': 'Bearer ' + self.access_token,
                'Content-Type': 'application/ssml+xml',
                'X-Microsoft-OutputFormat': 'riff-24khz-16bit-mono-pcm',
                'User-Agent': 'YOUR_RESOURCE_NAME'
            }
            xml_body = ElementTree.Element('speak', version='1.0')
            xml_body.set('{http://www.w3.org/XML/1998/namespace}lang', 'en-us')
            voice = ElementTree.SubElement(xml_body, 'voice')
            voice.set('{http://www.w3.org/XML/1998/namespace}lang', 'en-US')
            voice.set('name', 'en-US-Guy24kRUS') # Short name for 'Microsoft Server Speech Text to Speech Voice (en-US, Guy24KRUS)'
            voice.text = self.tts
            body = ElementTree.tostring(xml_body)
    
            response = requests.post(constructed_url, headers=headers, data=body)
            '''
            If a success response is returned, then the binary audio is written
            to file in your working directory. It is prefaced by sample and
            includes the date.
            '''
            if response.status_code == 200:
                with open('sample-' + self.timestr + '.wav', 'wb') as audio:
                    audio.write(response.content)
                    print("\nStatus code: " + str(response.status_code) + "\nYour TTS is ready for playback.\n")
            else:
                print("\nStatus code: " + str(response.status_code) + "\nSomething went wrong. Check your subscription key and headers.\n")
    
        def get_voices_list(self):
            base_url = 'https://'+self.region+'.tts.speech.microsoft.com/'
            path = 'cognitiveservices/voices/list'
            constructed_url = base_url + path
            headers = {
                'Authorization': 'Bearer ' + self.access_token,
            }
            response = requests.get(constructed_url, headers=headers)
            if response.status_code == 200:
                print("\nAvailable voices: \n" + response.text)
            else:
                print("\nStatus code: " + str(response.status_code) + "\nSomething went wrong. Check your subscription key and headers.\n")
    
    if __name__ == "__main__":
        region = '<your region here , in your case , the value should be eastus>'
        subscription_key = '<your subscription key here>'
        app = TextToSpeech(subscription_key,region)
        app.get_token()
        app.save_audio()
    

    You can find your region and subscription key value on Azure portal here : enter image description here

    I have tested on my side and it works for me .Once you go through the codes , a wav file will be created, that is the thing you need : enter image description here