- What: Use SSML markup in the
<Speak>XML element to control TTS voice, pitch, volume, rate, pronunciation, and pauses. - When: Use it with Amazon Polly voices for finer control than plain text-to-speech.
<Response>
<Speak voice="MAN">Go Green, Go Plivo</Speak> //Basic Text-to-Speech
<Speak voice="Polly.Joey">
<emphasis level="moderate">Go Green, Go Plivo</emphasis> //Text-to-Speech using SSML
</Speak>
</Response>
voice attribute of Plivo’s <Speak> XML tag. Note that Polly voices must be namespaced with a Polly prefix.
For example:
<Response>
<Speak voice="Polly.Joey">
<emphasis level="moderate">Go Green, Go Plivo</emphasis>
</Speak>
</Response>
SSML tags
You can use these SSML tags within Plivo XML.| SSML Tag | Action | Description |
|---|---|---|
| <break> | Add a pause | Use this tag to include a pause in the speech. |
| <emphasis> | Emphasize words | Use this tag to change the rate and voice of the speech. |
| <lang> | Specify another language for specific words | Use this tag to set the natural language of the text. |
| <p> | Add a pause between paragraphs | Use this tag to represent a paragraph. |
| <phoneme> | Use phonetic pronunciation | Use this tag to set phonetic pronunciation for specific text. |
| <prosody> | Control volume, speaking rate, and pitch | Use this tag to modify the volume, speaking rate, and pitch of the tagged text. |
| <s> | Add a pause between sentences | Use this tag to represent a sentence. This adds a strong break before and after the tag. |
| <say-as> | Control how special types of words are spoken | Use this tag to describe how to interpret the text. |
| <sub> | Pronounce acronyms and abbreviations | Use this tag to pronounce the specified words or phrases as different words or phrases. |
| <w> | Improve pronunciation by specifying parts of speech | Use this tag to customize the pronunciation of words by specifying the part of speech they are. |
- <amazon:auto-breaths>
- <amazon:effect name=“drc”>
- <amazon:effect phonation=“soft”>
- <amazon:effect vocal-tract-length>
- <amazon: effect name=“whispered”>
SSML voices
Plivo supports these Amazon Polly voices for use with Plivo XML:Character limit
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.from flask import Flask, Response, request, url_for
from plivo import plivoxml
app = Flask(__name__)
@app.route("/ssml/", methods=["GET", "POST"])
def ssml():
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)
return Response(response, mimetype="text/xml")
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
class PlivoController < ApplicationController
def ssml
response = Plivo::XML::Response.new
speak_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)
puts xml.to_xml()
render xml: xml.to_xml
end
end
var plivo = require('plivo');
var express = require('express');
var app = express();
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
app.all('/ssml/', function (request, response) {
if (request.method == "GET") {
var r = new plivo.Response();
const speakElem = 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'));
});
<?php
namespace App\Http\Controllers;
require '../vendor/autoload.php';
use Plivo\RestClient;
use Plivo\XML\Response;
use Illuminate\Http\Request;
class ReceivecallController extends Controller
{
public function ssml()
{
$response = new Response();
$speak_elem = $response->addSpeak('The date is', ['language'=>"en-US", 'voice'=>"Polly.Joey"]);
$speak_elem->addSayAs('20200626', ['interpret-as'=>"date"]);
$xml_response = $response->toXML();
return response($xml_response, 200)->header('Content-Type', 'application/xml');
}
}
package com.example.SsmlHandler;
import com.plivo.api.exceptions.PlivoXmlException;
import com.plivo.api.xml.*;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
@SpringBootApplication
@RestController
public class SsmlApplication {
public static void main(String[] args) {
SpringApplication.run(SsmlHandlerApplication.class, args);
}
@RequestMapping(value = "/ssml/", produces = { "application/xml" }, method = { RequestMethod.GET, RequestMethod.POST })
public Response SsmlHandler() throws PlivoXmlException {
Response response = new Response().children(new Speak("The date is").
children(new SayAs("20200626", "date")));
System.out.println(response.toXmlString());
return response;
}
}
package main
import (
"net/http"
"github.com/go-martini/martini"
"github.com/plivo/plivo-go/v7/xml"
)
func main() {
m := martini.Classic()
m.Any("/ssml/", func(w http.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", ""),
},
}
return response.String()
})
m.Run()
}
using System.Collections.Generic;
using Plivo.XML;
using Microsoft.AspNetCore.Mvc;
namespace Voicemail.Controllers
{
public class SsmlController : Controller
{
// GET: /<controller>/
public IActionResult Index()
{
var resp = new Response();
Speak speak_elem = new Speak("The date is", new Dictionary<string, string>() {
{"voice","Polly.Joey"},
{"language","en-US"},
});
resp.Add(speak_elem);
speak_elem.AddSayAs("20200626", new Dictionary<string, string>() {
{ "interpret-as", "date" }
});
var output = resp.ToString();
return this.Content(output, "text/xml");
}
}
}
<Response>
<Speak voice="Polly.Joey">The date is
<say-as interpret-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.from flask import Flask, Response, request, url_for
from plivo import plivoxml
app = Flask(__name__)
@app.route("/ssml/", methods=["GET", "POST"])
def ssml():
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)
return Response(response, mimetype="text/xml")
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
class PlivoController < ApplicationController
def ssml
response = Plivo::XML::Response.new
speak_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)
puts xml.to_xml()
render xml: xml.to_xml
end
end
var plivo = require('plivo');
var express = require('express');
var app = express();
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
app.all('/ssml/', function(request, response) {
if (request.method == "GET") {
var r = new plivo.Response();
const speakElem = 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'));
});
<?php
namespace App\Http\Controllers;
require '../vendor/autoload.php';
use Plivo\RestClient;
use Plivo\XML\Response;
use Illuminate\Http\Request;
class ReceivecallController extends Controller
{
public function ssml()
{
$response = new Response();
$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();
return response($xml_response, 200)->header('Content-Type', 'application/xml');
}
}
package com.example.SsmlHandler;
import com.plivo.api.exceptions.PlivoXmlException;
import com.plivo.api.xml.*;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
@SpringBootApplication
@RestController
public class SsmlApplication {
public static void main(String[] args) {
SpringApplication.run(SsmlHandlerApplication.class, args);
}
@RequestMapping(value = "/ssml/", produces = { "application/xml" }, method = { RequestMethod.GET, RequestMethod.POST })
public Response Ssml() throws PlivoXmlException {
Response response = new Response().children(new Speak("The word","Polly.Joey","en-US",1)
.children(new SayAs("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());
return response;
}
}
package main
import (
"net/http"
"github.com/go-martini/martini"
"github.com/plivo/plivo-go/v7/xml"
)
func main() {
m := martini.Classic()
m.Any("/ssml/", func(w http.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"),
},
}
return response.String()
})
m.Run()
}
using System.Collections.Generic;
using Plivo.XML;
using Microsoft.AspNetCore.Mvc;
namespace Voicemail.Controllers
{
public class SsmlController : Controller
{
// GET: /<controller>/
public IActionResult Index()
{
var resp = new Response();
Speak speak_elem = new Speak("The word", new Dictionary<string, string>() {
{"voice","Polly.Joey"},
{"language","en-US"},
});
resp.Add(speak_elem);
speak_elem.AddSayAs("read", new Dictionary<string, string>() {
{ "interpret-as", "characters" }
});
speak_elem.AddS("may be interpreted as either the present simple form");
speak_elem.AddW("read", new Dictionary<string, string>() {
{ "role", "amazon:VB" }
});
speak_elem.AddS("or the past participle form");
speak_elem.AddW("read", new Dictionary<string, string>() {
{ "role", "amazon:VBD" }
});
var output = resp.ToString();
return this.Content(output, "text/xml");
}
}
}
<Response>
<Speak voice="Polly.Joey">The word
<say-as interpret-as="characters">read</say-as>
<s>
may be interpreted as either the present simple form
</s>
<w role="amazon:VB">read</w>
<s>or the past participle form</s>
<w role="amazon:VBD">read</w>
</Speak>
</Response>
More examples
<Response>
<Speak>I can speak in a
<prosody pitch="high">higher pitched voice</prosody>
, or I can speak
<prosody pitch="low">in a lower pitched voice</prosody>
</Speak>
</Response>
<Response>
<Speak>I can speak
<prosody rate="x-slow">really slowly</prosody>
, or I can speak
<prosody rate="x-fast">really fast</prosody>
</Speak>
</Response>
<Response>
<Speak>I can also speak
<prosody volume="x-loud">very loudly</prosody>
, or I can speak <prosody volume="x-soft">very quietly</prosody>.
</Speak>
</Response>