Before using the Rest API, obtain an API key from Prosa Console.
Synchronous Request
Synchronous Text-to-Speech API request consist of a speech synthesize configuration as well as text to generate speech
from. The text in each synchronous request is limited to 280 characters. The wait parameter is set to true
to indicate that it is a synchronous request.
Example request
1
POST https://api.prosa.ai/v2/speech/tts
1 2 3 4 5 6 7 8 910
{"config":{"model":"tts-dimas-formal","wait":true,"audio_format":"opus"},"request":{"text":"Hasil akhir dari pekerjaan ini cukup memuaskan"}}
{"job_id":"2fec34e1efb146f7a7431cb35b64550d","status":"complete","created_at":"2019-08-24T14:15:22Z","modified_at":"2019-08-24T14:15:22Z","request":{"label":"string","text":"Hasil akhir dari pekerjaan ini cukup memuaskan"},"result":{"data":"<base64-encoded audio data>"},"job_config":{"model":"tts-dimas-formal","wait":false,"pitch":0,"tempo":1,"audio_format":"opus"},"model":{"name":"tts-dimas-formal","label":"TTS Dimas Formal","language":"Bahasa Indonesia","domain":"formal","voice":"Dimas","gender":"male","channels":1,"samplerate":48000}}
importbase64importrequestsurl="https://api.prosa.ai/v2/speech/tts"api_key="..."defmain():filename="audio_file.webm"text="Hasil akhir dari pekerjaan ini cukup memuaskan"audio_data=tts(text,"opus")withopen(filename,"wb")asf:f.write(audio_data)deftts(text:str,audio_format:str)->bytes:job=submit_tts_request(text,audio_format)ifjob["status"]=="complete":returnbase64.b64decode(job["result"]["data"])# Job was not completed within the timeframedefsubmit_tts_request(text:str,audio_format:str)->dict:payload={"config":{"model":"tts-dimas-formal","wait":True,# Blocks the request until the execution is finished"audio_format":audio_format},"request":{"text":text}}response=requests.post(url,json=payload,headers={"x-api-key":api_key})returnresponse.json()if__name__=='__main__':main()
consthttps=require('https');constfs=require('fs');// Setupconsturl='https://api.prosa.ai/v2/speech/tts';constapiKey='...';(async()=>{constfilename='generated_audio.webm';consttext="Hasil akhir dari pekerjaan ini cukup memuaskan";constaudioData=awaittts(text,"opus");fs.writeFileSync(filename,audioData);})();asyncfunctiontts(text){letjob=awaitsubmitTtsRequest(text);if(job["status"]==="complete"){letbase64AudioData=job["result"]["data"];returnBuffer.from(base64AudioData,'base64');}// Job was not completed within the timeframe}asyncfunctionsubmitTtsRequest(text,audio_format){constpayload={"config":{"model":"tts-dimas-formal","wait":true,// Blocks the request until the execution is finished"audio_format":audio_format},"request":{"text":text}}returnawaitrequest(url,"POST",{json:payload,headers:{"x-api-key":apiKey}});}functionrequest(url,method,{headers=null,json=null}){returnnewPromise((resolve,reject)=>{letreq=https.request(url,{method:method,headers:{"Accept":"application/json","Content-Type":"application/json; charset=UTF-8",...headers}},(res)=>{if(res.statusCode===200){letdata=""res.on('data',(chunk)=>{data+=chunk;});res.on('end',()=>{constresponse=JSON.parse(data);resolve(response);});}else{reject(res.statusCode);}})req.on('error',reject);if(json!=null){req.write(JSON.stringify(json));}req.end();})}
Note
The Node.js example contains a simple promise wrapper for built-in https module.
Warning
If the job could not be completed within a specified timeframe, it is treated as an Asynchronous Request.
See Retrieving Result on how to retrieve the result of asynchronous requests.
Configure request
Configure the model to use. In this example, the model being used is tts-dimas-formal.
12345678
defsubmit_tts_request(text:str,audio_format:str)->dict:payload={"config":{"model":"tts-dimas-formal","wait":True,# Blocks the request until the execution is finished"audio_format":audio_format}}
1 2 3 4 5 6 7 8 910
asyncfunctionsubmitTtsRequest(text,audio_format){constpayload={"config":{"model":"tts-dimas-formal","wait":true,// Blocks the request until the execution is finished"audio_format":audio_format}}}
Sending text
The text in sent under request object in the request payload.
12345
{"request":{"text":"text to generate speech from"}}
1 2 3 4 5 6 7 8 91011
defsubmit_tts_request(text:str,audio_format:str)->dict:payload={"config":{"model":"tts-dimas-formal","wait":True,# Blocks the request until the execution is finished"audio_format":audio_format},"request":{"text":text}}
1 2 3 4 5 6 7 8 9101112
asyncfunctionsubmitTtsRequest(text,audio_format){constpayload={"config":{"model":"tts-dimas-formal","wait":true,// Blocks the request until the execution is finished"audio_format":audio_format},"request":{"text":text}}}
Sending the request
Authenticate the request by including API Key in the HTTP request header.
1 2 3 4 5 6 7 8 910111213141516171819
url="https://api.prosa.ai/v2/speech/tts"defsubmit_tts_request(text:str,audio_format:str)->dict:payload={"config":{"model":"tts-dimas-formal","wait":True,# Blocks the request until the execution is finished"audio_format":audio_format},"request":{"text":text}}response=requests.post(url,json=payload,headers={"x-api-key":api_key})returnresponse.json()
1 2 3 4 5 6 7 8 9101112131415161718192021
consturl='https://api.prosa.ai/v2/speech/tts';asyncfunctionsubmitTtsRequest(text,audio_format){constpayload={"config":{"model":"tts-dimas-formal","wait":true,// Blocks the request until the execution is finished"audio_format":audio_format},"request":{"text":text}}returnawaitrequest(url,"POST",{json:payload,headers:{"x-api-key":apiKey}});}
Receiving response
For synchronous requests, the audio data is returned directly under the object result as base64-encoded data.
If the job could not be completed within a specified timeframe, it is treated as an Asynchronous Request instead.
In that case, you need to poll and retrieve the result using job_id. See Retrieving Result on
how to retrieve the result of asynchronous requests.
1234567
deftts(text:str,audio_format:str)->bytes:job=submit_tts_request(text,audio_format)ifjob["status"]=="complete":returnbase64.b64decode(job["result"]["data"])# Job was not completed within the timeframejob_id=job["job_id"]# Retrieve with job_id instead
123456789
asyncfunctiontts(text,audio_format){letjob=awaitsubmitTtsRequest(text,audio_format);if(job["status"]==="complete"){letbase64AudioData=job["result"]["data"];returnBuffer.from(base64AudioData,'base64');}// Job was not completed within the timeframe}
Info
See TtsResponse for more information regading the response.
Asynchronous Request
Asynchronous Text-to-Speech API request is fairly similar to
synchronous Text-to-Speech API request. However, instead of immediately returning the result,
the request will initiate a Long Running Operation and return a response without result.
Each asynchronous requests can process up to 5000 characters.
Here are some example codes to help you get started quickly.
importbase64importtimefromtypingimportOptionalimportrequestsurl="https://api.prosa.ai/v2/speech/tts"api_key="..."defmain():filename="audio_file.webm"text="halo, dunia"audio_data=tts(text,"opus")withopen(filename,"wb")asf:f.write(audio_data)deftts(text:str,audio_format:str,poll_interval:float=5.0)->bytes:job=submit_tts_request(text,audio_format)job_id=job["job_id"]whileTrue:result=query_tts_result(job_id)ifresultisnotNone:returnbase64.b64decode(result["data"])time.sleep(poll_interval)defsubmit_tts_request(text:str,audio_format:str)->dict:payload={"config":{"model":"tts-dimas-formal","wait":False,# Do not wait for the request to complete"audio_format":audio_format},"request":{"text":text}}response=requests.post(url,json=payload,headers={"x-api-key":api_key})returnresponse.json()defquery_tts_result(job_id:str)->Optional[dict]:response=requests.get(url+"/"+job_id,headers={"x-api-key":api_key})ifresponse.status_code==200:job=response.json()status=job["status"]ifstatus=="complete":result=job["result"]returnresultreturnNoneif__name__=='__main__':main()
consthttps=require('https');constfs=require('fs');// Setupconsturl='https://api.prosa.ai/v2/speech/tts';constapiKey='...';(async()=>{constfilename='generated_audio.webm';consttext="Hasil akhir dari pekerjaan ini cukup memuaskan";letres=awaitsubmitTtsRequest(text,"opus");constjobId=res["job_id"];constpollInterval=5.0*1000;letresult=null;while(true){result=awaitqueryTtsResult(jobId);if(result!=null){break;}awaitnewPromise((resolve)=>{setTimeout(resolve,pollInterval);});}fs.writeFileSync(filename,result);})();asyncfunctionsubmitTtsRequest(text,audio_format){constpayload={"config":{"model":"tts-dimas-formal","wait":false,// Do not wait for the request to complete"audio_format":audio_format},"request":{"text":text}}returnawaitrequest(url,"POST",{json:payload,headers:{"x-api-key":apiKey}});}asyncfunctionqueryTtsResult(jobId){letres=awaitrequest(url+"/"+jobId,"GET",{headers:{"x-api-key":apiKey}});if(res["status"]==="complete"){letbase64AudioData=res["result"]["data"];returnBuffer.from(base64AudioData,'base64');}returnnull;}functionrequest(url,method,{headers=null,json=null}){returnnewPromise((resolve,reject)=>{letreq=https.request(url,{method:method,headers:{"Accept":"application/json","Content-Type":"application/json; charset=UTF-8",...headers}},(res)=>{if(res.statusCode===200){letdata=""res.on('data',(chunk)=>{data+=chunk;});res.on('end',()=>{constresponse=JSON.parse(data);resolve(response);});}else{reject(res.statusCode);}})req.on('error',reject);if(json!=null){req.write(JSON.stringify(json));}req.end();})}
The request is fairly similar to synchronous requests except the wait parameter is set to false to
indicate that this is an asynchronous request.
1 2 3 4 5 6 7 8 910111213141516171819
url="https://api.prosa.ai/v2/speech/tts"defsubmit_tts_request(text:str,audio_format:str)->dict:payload={"config":{"model":"tts-dimas-formal","wait":False,# Do not wait for the request to complete"audio_format":audio_format},"request":{"text":text}}response=requests.post(url,json=payload,headers={"x-api-key":api_key})returnresponse.json()
1 2 3 4 5 6 7 8 9101112131415161718192021
consturl='https://api.prosa.ai/v2/speech/tts';asyncfunctionsubmitTtsRequest(text,audio_format){constpayload={"config":{"model":"tts-dimas-formal","wait":false,// Do not wait for the request to complete"audio_format":audio_format},"request":{"text":text}}returnawaitrequest(url,"POST",{json:payload,headers:{"x-api-key":apiKey}});}
Note
Note that the value returned is an TtsResponse object which job_id property will be used to retrieve the result.
Retrieving result
Using the job_id from TtsResponse object we previously received when submitting requests,
we can retrieve the status and the result by querying GET https://api.prosa.ai/v2/speech/tts/{job_id}.
Example request
1
GET https://api.prosa.ai/v2/speech/tts/2fec34e1efb146f7a7431cb35b64550d
{"job_id":"2fec34e1efb146f7a7431cb35b64550d","status":"complete","created_at":"2019-08-24T14:15:22Z","modified_at":"2019-08-24T14:15:22Z","request":{"label":"string","text":"Hasil akhir dari pekerjaan ini cukup memuaskan"},"result":{"data":"<base64-encoded audio data>"},"job_config":{"model":"tts-dimas-formal","wait":false,"pitch":0,"tempo":1,"audio_format":"opus"},"model":{"name":"tts-dimas-formal","label":"TTS Dimas Formal","language":"Bahasa Indonesia","domain":"formal","voice":"Dimas","gender":"male","channels":1,"samplerate":48000}}