- First, I signed up for the Azure free plan.
- Then I used the Azure Text to Speech API from Node.js to successfully make calls on the free plan.
- I made about 5000 calls.
- I get the error message
The request is throttled because you have exceeded the concurrent request limit allowed for your sub websocket error code: 4429
. - (I still have $200 in free credits and 29 days left on the free plan)
- Try again an hour later, get the same error.
- Try again a day later, get the same error.
- Subscribe to the $29/month plan, test the API again, get the same error.
- Wait an hour, try the API again, get the same error.
- Submit a support ticket, wait a day, then try again, and get the same error!
What is the deal! What am I doing wrong!? How can I debug this? Why isn’t it working?
I am making 1 request at a time as well, when I make a request, I wait for it to finish, then immediately make the next request (in an async loop in Node.js). I don’t think that has anything to do with concurrent request limits, as I am not making more than 1 concurrent request at a time.
Plus, I waited for 1-2 days, or at least an hour, before trying again, and it still doesn’t work. I would expect the concurrency limit to be reset after at most an hour, but it’s definitely not resetting.
Lastly, as you can see in the code below, I tried waiting 500ms between requests, but even the first request fails with the same error message, so doesn’t matter if there is a pause in between them right now it seems.
Any ideas?
import 'dotenv/config'
import sdk from 'microsoft-cognitiveservices-speech-sdk'
import fs from 'fs'
import { parse } from 'csv-parse/sync'
import talk from '@termsurf/talk'
const terms = parse(
fs.readFileSync(
`tibetan.syllable.csv`,
`utf-8`,
),
{ columns: true },
)
const TERMS = terms.reduce((m: any, x: any) => {
if (x.pronunciation.trim().match(/[s/]|a~/)) return m
m[x.word] = {
talk: x.pronunciation.trim(),
ipa: talk.default.talk.toIPA(x.pronunciation.trim()),
}
return m
}, {})
// This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
call()
async function call() {
for (const term in TERMS) {
await new Promise(res => setTimeout(res, 500))
// continue
const { talk, ipa } = TERMS[term]
const speechConfig = sdk.SpeechConfig.fromSubscription(
String(process.env.SPEECH_KEY),
String(process.env.SPEECH_REGION),
)
// The language of the voice that speaks.
speechConfig.speechSynthesisVoiceName = talk.match(/c/i)
? 'en-US-AndrewMultilingualNeural'
: 'hi-IN-KunalNeural' // hi-IN-AaravNeural
const path = `tmp/tibetan/kunal/${term}-${talk}.mp3`
if (fs.existsSync(path)) {
continue
}
console.log(term, TERMS[term])
// const audioConfig = sdk.AudioConfig.fromAudioFileOutput(path)
// Create the speech synthesizer.
const synthesizer = new sdk.SpeechSynthesizer(
speechConfig,
// audioConfig,
)
const ssml = `<speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="en-US">
<voice name="${speechConfig.speechSynthesisVoiceName}">
<prosody rate="slow">
<phoneme alphabet="ipa" ph="${ipa}">${talk}</phoneme>
</prosody>
</voice>
</speak>`
await new Promise((res, rej) => {
// Start the synthesizer and wait for a result.
synthesizer.speakSsmlAsync(
ssml,
function (result) {
if (result.errorDetails) {
console.error(result.errorDetails)
} else {
// console.log(result)
fs.writeFileSync(path, new Uint8Array(result.audioData))
}
synthesizer.close()
res(undefined)
},
function (err) {
console.trace(err)
synthesizer.close()
rej(err)
},
)
})
}
}