Getting started with Speech Synthesis Markup Language (SSML)
The World Wide Web Consortium (W3C) created Speech Synthesis Markup Language (SSML) as an XML-based markup language to assist in generating natural-sounding synthesized speech. The Plivo Speak XML element supports the generation of SSML-based speech, powered by Amazon Polly. It supports 27 languages and more than 40 voices, and allows developers to control pronunciation, pitch, and volume.
Here‘s how SSML appears within Plivo Speak XML elements:
1
2
3
4
5
6
<Response><Speakvoice="MAN">Go Green, Go Plivo</Speak> //Basic Text-to-Speech
<Speakvoice="Polly.Joey"><emphasislevel="moderate">Go Green, Go Plivo</emphasis> //Text-to-Speech using SSML
</Speak></Response>
To synthesize SSML speech on Plivo, specify one of the Amazon Polly voices in the voice attribute of Plivo’s <Speak> XML tag. Note that Polly voices must be namespaced with a Polly prefix.
For example:
1
2
3
4
5
<Response><Speakvoice="Polly.Joey"><emphasislevel="moderate">Go Green, Go Plivo</emphasis></Speak></Response>
To ensure quick synthesis, Plivo caps the length of text that can be synthesized in one <Speak> tag at 3,000 characters.
Pricing
Support for SSML-based speech synthesis is currently in beta and free for all Plivo users. We expect to eventually charge for text-to-speech on the basis of the number of characters synthesized.
SSML support in Plivo Server SDKs
SSML tags are supported in all of our Server SDKs.
Example
This example use the Joey voice for US English (en-US). Use the <Speak voice> tag to specify the voice for your text.
say-as
The say-as tag describes how to interpret the text.
fromflaskimportFlask,Response,request,url_forfromplivoimportplivoxmlapp=Flask(__name__)@app.route("/ssml/",methods=["GET","POST"])defssml():element=plivoxml.ResponseElement()response=(element.add(plivoxml.SpeakElement(content="The date is",voice="Polly.Joey",language="en-US").add_say_as("20200626",interpret_as="date")).to_string(False))print(response)returnResponse(response,mimetype="text/xml")if__name__=="__main__":app.run(host="0.0.0.0",debug=True)
1
2
3
4
5
6
7
8
9
10
classPlivoController<ApplicationControllerdefssmlresponse=Plivo::XML::Response.newspeak_elem=response.addSpeak('The date is',voice: 'Polly.Joey',language: 'en-US')speak_elem.addSayAs('20200626','interpret-as'=>'date')xml=Plivo::XML::PlivoXML.new(response)putsxml.to_xml()renderxml: xml.to_xmlendend
varplivo=require('plivo');varexpress=require('express');varapp=express();app.set('port',(process.env.PORT||5000));app.use(express.static(__dirname+'/public'));app.all('/ssml/',function(request,response){if(request.method=="GET"){varr=newplivo.Response();constspeakElem=r.addSpeak('The date is',{'voice':'Polly.Joey','language':'en-US'});speakElem.addSayAs('20200626',{'interpret-as':'date',});console.log(r.toXML());response.set({'Content-Type':'text/xml'});response.end(r.toXML());}});app.listen(app.get('port'),function(){console.log('Node app is running on port',app.get('port'));});
<?phpnamespaceApp\Http\Controllers;require'../vendor/autoload.php';usePlivo\RestClient;usePlivo\XML\Response;useIlluminate\Http\Request;classReceivecallControllerextendsController{publicfunctionssml(){$response=newResponse();$speak_elem=$response->addSpeak('The date is',['language'=>"en-US",'voice'=>"Polly.Joey"]);$speak_elem->addSayAs('20200626',['interpret-as'=>"date"]);$xml_response=$response->toXML();returnresponse($xml_response,200)->header('Content-Type','application/xml');}}
packagecom.example.SsmlHandler;importcom.plivo.api.exceptions.PlivoXmlException;importcom.plivo.api.xml.*;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.web.bind.annotation.*;@SpringBootApplication@RestControllerpublicclassSsmlApplication{publicstaticvoidmain(String[]args){SpringApplication.run(SsmlHandlerApplication.class,args);}@RequestMapping(value="/ssml/",produces={"application/xml"},method={RequestMethod.GET,RequestMethod.POST})publicResponseSsmlHandler()throwsPlivoXmlException{Responseresponse=newResponse().children(newSpeak("The date is").children(newSayAs("20200626","date")));System.out.println(response.toXmlString());returnresponse;}}
packagemainimport("net/http""github.com/go-martini/martini""github.com/plivo/plivo-go/v7/xml")funcmain(){m:=martini.Classic()m.Any("/ssml/",func(whttp.ResponseWriter,r*http.Request)string{w.Header().Set("Content-Type","application/xml")response:=xml.ResponseElement{Contents:[]interface{}{new(xml.SpeakElement).AddSpeak("The date is","Polly.Joey","en-US",1).AddSayAs("20200626","date",""),},}returnresponse.String()})m.Run()}
usingSystem.Collections.Generic;usingPlivo.XML;usingMicrosoft.AspNetCore.Mvc;namespaceVoicemail.Controllers{publicclassSsmlController:Controller{// GET: /<controller>/publicIActionResultIndex(){varresp=newResponse();Speakspeak_elem=newSpeak("The date is",newDictionary<string,string>(){{"voice","Polly.Joey"},{"language","en-US"},});resp.Add(speak_elem);speak_elem.AddSayAs("20200626",newDictionary<string,string>(){{"interpret-as","date"}});varoutput=resp.ToString();returnthis.Content(output,"text/xml");}}}
The rendered XML document would be:
<Response><Speakvoice="Polly.Joey">The date is
<say-asinterpret-as="date">20200626</say-as></Speak></Response>
w
The w tag lets you customize the pronunciation of a word by specifying its part of speech.
fromflaskimportFlask,Response,request,url_forfromplivoimportplivoxmlapp=Flask(__name__)@app.route("/ssml/",methods=["GET","POST"])defssml():element=plivoxml.ResponseElement()response=(element.add(plivoxml.SpeakElement(content="The word",voice="Polly.Joey",language="en-US").add_say_as("read",interpret_as="characters").add_s("may be interpreted as either the present simple form").add_w("read",role="amazon:VB").add_s("or the past participle form").add_w("read",role="amazon:VBD")).to_string(False))print(response)returnResponse(response,mimetype="text/xml")if__name__=="__main__":app.run(host="0.0.0.0",debug=True)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
classPlivoController<ApplicationControllerdefssmlresponse=Plivo::XML::Response.newspeak_elem=response.addSpeak('The word',voice: 'Polly.Joey',language: 'en-US')speak_elem.addSayAs('read','interpret-as'=>'characters')speak_elem.addS('may be interpreted as either the present simple form')speak_elem.addW('read','role'=>'amazon:VB')speak_elem.addS('or the past participle form')speak_elem.addW('read','role'=>'amazon:VBD')xml=Plivo::XML::PlivoXML.new(response)putsxml.to_xml()renderxml: xml.to_xmlendend
varplivo=require('plivo');varexpress=require('express');varapp=express();app.set('port',(process.env.PORT||5000));app.use(express.static(__dirname+'/public'));app.all('/ssml/',function(request,response){if(request.method=="GET"){varr=newplivo.Response();constspeakElem=r.addSpeak('The word',{'voice':'Polly.Joey','language':'en-US'});speakElem.addSayAs('read',{'interpret-as':'characters'});speakElem.addS('may be interpreted as either the present simple form');speakElem.addW('read',{'role':'amazon:VB'});speakElem.addS('or the past participle form');speakElem.addW('read',{'role':'amazon:VBD'});console.log(r.toXML());response.set({'Content-Type':'text/xml'});response.end(r.toXML());}});app.listen(app.get('port'),function(){console.log('Node app is running on port',app.get('port'));});
<?phpnamespaceApp\Http\Controllers;require'../vendor/autoload.php';usePlivo\RestClient;usePlivo\XML\Response;useIlluminate\Http\Request;classReceivecallControllerextendsController{publicfunctionssml(){$response=newResponse();$speak_elem=$response->addSpeak('The word',['language'=>"en-US",'voice'=>"Polly.Joey"]);$speak_elem->addSayAs('read',['interpret-as'=>"characters"]);$speak_elem->addS('may be interpreted as either the present simple form');$speak_elem->addW('read',['role'=>"amazon:VB"]);$speak_elem->addS('or the past participle form');$speak_elem->addW('read',['role'=>"amazon:VBD"]);$xml_response=$response->toXML();returnresponse($xml_response,200)->header('Content-Type','application/xml');}}
packagecom.example.SsmlHandler;importcom.plivo.api.exceptions.PlivoXmlException;importcom.plivo.api.xml.*;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.web.bind.annotation.*;@SpringBootApplication@RestControllerpublicclassSsmlApplication{publicstaticvoidmain(String[]args){SpringApplication.run(SsmlHandlerApplication.class,args);}@RequestMapping(value="/ssml/",produces={"application/xml"},method={RequestMethod.GET,RequestMethod.POST})publicResponseSsml()throwsPlivoXmlException{Responseresponse=newResponse().children(newSpeak("The word","Polly.Joey","en-US",1).children(newSayAs("read","characters")).addS("may be interpreted as either the present simple form").addW("read","amazon:VB").addS("or the past participle form").addW("read","amazon:VBD"));System.out.println(response.toXmlString());returnresponse;}}
packagemainimport("net/http""github.com/go-martini/martini""github.com/plivo/plivo-go/v7/xml")funcmain(){m:=martini.Classic()m.Any("/ssml/",func(whttp.ResponseWriter,r*http.Request)string{w.Header().Set("Content-Type","application/xml")response:=xml.ResponseElement{Contents:[]interface{}{new(xml.SpeakElement).AddSpeak("The word","Polly.Joey","en-US",1).AddSayAs("read","characters","").AddS("may be interpreted as either the present simple form").AddW("read","amazon:VB").AddS("or the past participle form").AddW("read","amazon:VBD"),},}returnresponse.String()})m.Run()}
usingSystem.Collections.Generic;usingPlivo.XML;usingMicrosoft.AspNetCore.Mvc;namespaceVoicemail.Controllers{publicclassSsmlController:Controller{// GET: /<controller>/publicIActionResultIndex(){varresp=newResponse();Speakspeak_elem=newSpeak("The word",newDictionary<string,string>(){{"voice","Polly.Joey"},{"language","en-US"},});resp.Add(speak_elem);speak_elem.AddSayAs("read",newDictionary<string,string>(){{"interpret-as","characters"}});speak_elem.AddS("may be interpreted as either the present simple form");speak_elem.AddW("read",newDictionary<string,string>(){{"role","amazon:VB"}});speak_elem.AddS("or the past participle form");speak_elem.AddW("read",newDictionary<string,string>(){{"role","amazon:VBD"}});varoutput=resp.ToString();returnthis.Content(output,"text/xml");}}}
The rendered XML document would be:
<Response><Speakvoice="Polly.Joey">The word
<say-asinterpret-as="characters">read</say-as><s>
may be interpreted as either the present simple form
</s><wrole="amazon:VB">read</w><s>or the past participle form</s><wrole="amazon:VBD">read</w></Speak></Response>
More examples
<Response><Speak>I can speak in a
<prosodypitch="high">higher pitched voice</prosody>
, or I can speak
<prosodypitch="low">in a lower pitched voice</prosody></Speak></Response><Response><Speak>I can speak
<prosodyrate="x-slow">really slowly</prosody>
, or I can speak
<prosodyrate="x-fast">really fast</prosody></Speak></Response><Response><Speak>I can also speak
<prosodyvolume="x-loud">very loudly</prosody>
, or I can speak <prosodyvolume="x-soft">very quietly</prosody>.
</Speak></Response>
Rate this page
🥳 Thank you! It means a lot to us!
×
Help Us Improve
Thank you so much for rating the page, we would like to get your input
for further improvements!