Transformers
Transformers convert data in an Alexa Presentation Language (APL) data source into alternative representations. You can include an array of transformer objects in the transformers
property of an object data source.
Available transformers
APL supports the following transformers:
aplAudioToSpeech
– Converts an APL for Audio document into audio you can bind to thespeech
property of an APL component. You can then instruct Alexa to play the audio with theSpeakItem
orSpeakList
.lineBreakProcessor
: Updates text input with<nobr>
tags around character sequences that should not break at a new line.ssmlToSpeech
– Converts the input Speech Synthesis Markup Language (SSML) into speech you can bind to thespeech
property of an APL component. You can then instruct Alexa to play the speech with theSpeakItem
orSpeakList
command.- The use of the audio tag with the
ssmlToSpeech
transformer is not supported. - The text passed to this transformer must be valid SSML enclosed within
<speak>
tags.
- The use of the audio tag with the
ssmlToText
– Converts the input SSML to plain text.textToHint
– Converts the input to a hint with the correct user-configured wake word for the device (Try "Alexa, This is the hint"). Users can choose the wake word for their devices, so avoid hard-coding the word "Alexa" in your hint.textToSpeech
– Converts the input plain text into speech you can bind to thespeech
property of an APL component. The speech associated with the component can then be spoken using aSpeakItem
APL command. This transformer takes plain text with no SSML tags.
Transformer properties and conversion rules
A transformer converts data from a named property inside a data source, performs the transformation and writes the data back to a property in the original data source. If the outputName
is not supplied, a transformer overwrites the input
property. Transformers have the base properties shown in this table:
Property | Type | Required | Description |
---|---|---|---|
transformer |
String | Yes | The type of the transformer. |
inputPath |
String | Yes | Path within the object to the content to transform. This must reference a property within the properties object in the data source. |
outputName |
String | No | Name of the property to be added to the object. If no outputName is supplied, the transformer overwrites the inputPath with the transformed output. |
template |
String | No | Reference to an APL for Audio document provided in the sources object of the RenderDocument directive. Applies to the aplAudioToSpeech transformer only. |
The inputPath
points to either a single entity in the data source object, or a set of entities using wildcard properties or unresolved arrays. Each property that matches the inputPath
is transformed. The inputPath
pattern is a symbol followed by some number of node and/or wildcard references.
The following rules apply:
-
A symbol name or array index must match an existing object property or array index inside the properties block. If the match fails, the transformation is abandoned.
-
The location where the output is stored is found by replacing the last non-wildcard node with the outputName. If there are no non-wildcard nodes, the symbol is replaced by outputName.
-
The last non-wildcard node cannot be a numeric index. If the last non-wildcard node is numeric, the transformation is abandoned.
These examples demonstrate how referencing works. Consider the sample data shown here:
{
"myDocumentData": {
"type": "object",
"properties": {
"name": "Sam Lee",
"address": {
"street": "301 Charles Way",
"city": "Bedford"
},
"family": [
{
"name": "Alex",
"relation": "wife"
},
{
"name": "Patty",
"relation": "daughter"
}
],
"contacts": [
"Robin Barnes",
"Betty Barnes"
]
},
"transformers": [
{
"inputPath": ["see examples in table below"],
"outputName": ["see examples in table below"],
"transformer": "textToSpeech"
}
]
}
}
This table shows how different values in inputPath
and outputName
would transform the data shown in the above data source.
inputPath | Item to be transformed | Result stored at: |
---|---|---|
name | "Sam Lee" | outputName |
address.street | "301 Charles Way" | address.outputName |
contacts.* | ["Robin Barnes", "Betty Barnes"] | outputName[0], outputName[1] |
family[0].name | "Alex" | family[0].outputName |
family[*].name | "Alex", "Patty" | family[0].outputName, family[1].outputName |
address.* | "301 Charles Way", "Bedford" | outputName.street, outputName.city |
family[3].name | Does not work: the family array does not have a value at index 3 |
|
family[1].names | Does not work: the value at family[1] does not have a names property |
|
family[0] | { "name": "Alex", "relation": "wife" } | Does not work: the last non-wildcard node cannot be a numeric index |
aplAudioToSpeech transformer
Converts an APL for Audio document into audio you can bind to the speech
property of an APL component. You can then instruct Alexa to play the audio with the SpeakItem
or SpeakList
.
The aplAudioToSpeech
transformer has the following properties.
Property | Type | Required | Description |
---|---|---|---|
transformer |
String | Yes | Set to aplAudioToSpeech |
inputPath |
String | No | Path to an object in the data source that contains data to substitute into the APL for Audio document |
outputName |
String | Yes | Name of the property to add to the data source with the results of the transformation. |
template |
String | Yes | Reference to an APL for Audio document provided in the sources property of the RenderDocument directive. This is the document to transform into audio. Follows the syntax {identifierName}. |
The inputPath
in this transformer identifies an entity or array of entities in the data source object. For each entity identified, the transformer adds a new property called data to the data source. The transformer then uses the modified data source to evaluate the APL for Audio document. This lets you use data binding in your document. For an example, see Example transformation with no inputPath.
The outputName
identifies the property in the data source to use for the results of the transformation. The transformer adds the outputName
to the data source as an object with a url
property. The url
property contains the audio to play. You bind the url
property to the speech
property of the component in your APL document.
The template
provides a reference to the full APL for Audio document to transform. You provide this document in the sources
property of the RenderDocument
directive. The sources
property is a key/object map. Use the key in sources
as the name in template
.
In this example, the sources
property of the RenderDocument
directive contains one APL for Audio document, with the key catFactAPLAudio
. To use this document with the transformer, set template
to catFactAPLAudio
.
{
"sources": {
"catFactAPLAudio": {
"type": "APLA",
"version": "0.91",
"mainTemplate": {
"items": [
{
"type": "Speech",
"contentType": "SSML",
"content": "<speak>Not all cats like <emphasis level='strong'>catnip</emphasis>.</speak>"
}
]
}
}
}
}
Example transformation with no inputPath
The inputPath
property isn't required. The following example illustrates a document in which inputPath
isn't included.
This example includes the document
, sources
, and datasources
properties of a RenderDocument
directive.
{
"document": {
"type": "APL",
"version": "2024.2",
"theme": "dark",
"mainTemplate": {
"parameters": [
"payload"
],
"items": {
"type": "Text",
"id": "catFactText",
"text": "${payload.catFactData.properties.catFact}",
"speech": "${payload.catFactData.properties.catFactAudio.url}"
}
}
},
"sources": {
"catFactAPLAudio": {
"type": "APLA",
"version": "0.91",
"mainTemplate": {
"items": [
{
"type": "Speech",
"contentType": "SSML",
"content": "<speak>Not all cats like <emphasis level='strong'>catnip</emphasis>.</speak>"
}
]
}
}
},
"datasources": {
"catFactData": {
"type": "object",
"properties": {
"backgroundImage": "https://.../catfacts.png",
"title": "Cat Fact #9",
"logoUrl": "https://.../logo.png",
"image": "https://.../catfact9.png",
"catFact": "Not all cats like catnip."
},
"transformers": [
{
"template": "catFactAPLAudio",
"outputName": "catFactAudio",
"transformer": "aplAudioToSpeech"
}
]
}
}
}
The transformation adds new object catFactAudio
to the properties
object in the data source. This new object has the property url
, which contains a URL with the audio to play. In the example, the speech
component of the Text
property uses the data binding expression ${payload.catFactData.properties.catFactAudio.url}
to reference that audio.
Example transformation with the inputPath
The following example illustrates using the inputPath
property to substitute data from the data source into the APL for Audio document during the transformation. This example includes the document
, sources
, and datasources
properties of a RenderDocument
directive.
The APL document binds an array of objects in shoppingItems.properties.itemList
to the data
property of the Sequence
, to display a list of all the items in the array. The APLA document defines a template in which speaks a name and plays a background sound. This template also uses data binding to refer to the name
and the background sound audio file.
The transformer sets the inputPath
to the itemList.*
to reference the items in the properties.itemList
array.
{
"document": {
"type": "APL",
"version": "2024.2",
"theme": "dark",
"mainTemplate": {
"parameters": [
"payload"
],
"item": {
"type": "Sequence",
"width": "100%",
"height": "100%",
"data": "${payload.shoppingItems.properties.itemList}",
"items": [
{
"type": "Container",
"direction": "row",
"items": [
{
"type": "Text",
"text": "${data.name}",
"color": "white"
},
{
"type": "Image",
"source": "${data.image}",
"align": "top",
"scale": "best-fit"
}
],
"speech": "${data.speech.url}"
}
]
}
}
},
"sources": {
"TextWithBackgroundAudio": {
"type": "APLA",
"version": "0.91",
"mainTemplate": {
"parameters": [
"payload"
],
"item": {
"type": "Mixer",
"items": [
{
"type": "Speech",
"content": "${payload.data.name}"
},
{
"type": "Audio",
"source": "${payload.shoppingItems.properties.backgroundRoomAudio[payload.data.category]}"
}
]
}
}
}
},
"datasources": {
"shoppingItems": {
"type": "object",
"properties": {
"itemList": [
{
"name": "Baseball",
"image": "https://imgur.com/gallery/Szbir",
"category": "Outdoor"
},
{
"name": "Frisbee",
"image": "https://imgur.com/t/frisbee/6yWhK5k",
"category": "Outdoor"
},
{
"name": "Coffee pot",
"image": "https://imgur.com/gallery/IJwSUPE",
"category": "Kitchen"
}
],
"backgroundRoomAudio": {
"Bathroom": "https://bathroom_sounds.mp3",
"Kitchen": "https://kitchen_sounds.mp3",
"Outdoor": "https://outdoor_sounds.mp3"
}
},
"transformers": [
{
"inputPath": "itemList.*",
"outputName": "speech",
"transformer": "aplAudioToSpeech",
"template": "TextWithBackgroundAudio"
}
]
}
}
}
The transformer does the following for each item in the properties.itemList
array:
- Adds a new property called
speech
. The name "speech comes from theoutputName
defined in the transformer. - Converts the APLA document to audio, replacing data binding expressions that reference
data
with the data from theitemList
item. For example, when the transformer processes the first item, it replaces${payload.data.name}
with "Baseball" andpayload.shoppingItems.properties.backgroundRoomAudio[payload.data.category]
with the audio file "https://outdoor_sounds.mp3". - Saves the converted audio into a
url
property on thespeech
object.
This example shows the transformed data source.
{
"shoppingItems": {
"type": "object",
"properties": {
"itemList": [
{
"name": "Baseball",
"image": "https://imgur.com/gallery/Szbir",
"category": "Outdoor",
"speech": {
"url": "https://www.amazonalexa.com/examples/mp3/baseballaudio.mp3"
}
},
{
"name": "Frisbee",
"image": "https://imgur.com/t/frisbee/6yWhK5k",
"category": "Outdoor",
"speech": {
"url": "https://www.amazonalexa.com/examples/mp3/frisbeeaudio.mp3"
}
},
{
"name": "Coffee pot",
"image": "https://imgur.com/gallery/IJwSUPE",
"category": "Kitchen",
"speech": {
"url": "https://www.amazonalexa.com/examples/mp3/coffeepotaudio.mp3"
}
}
],
"backgroundRoomAudio": {
"Bathroom": "https: //bathroom_sounds.mp3",
"Kitchen": "https: //kitchen_sounds.mp3",
"Outdoor": "https://outdoor_sounds.mp3"
}
}
}
}
Render the transformed APLA document
To render the transformed document, use the SpeakItem
or SpeakList
command. You can trigger this command directly in your APL document, such as with a button press. You can also use the Alexa.Presentation.APL.ExecuteCommands
directive to send a SpeakItem
command to the device from your skill.
The following example illustrates the ExecuteCommands
directive.
{
"type": "Alexa.Presentation.APL.ExecuteCommands",
"token": "[SkillProvidedToken]",
"commands": [
{
"type": "SpeakItem",
"componentId": "catFactText",
"highlightMode": "line",
"align": "center"
}
]
}
Note that the token supplied in the ExecuteCommands
directive is required and must match the token provided by the skill in the RenderDocument directive used to render the APL document.
lineBreakProcessor Transformer
Updates text input with <nobr>
tags around character sequences that should not break at a new line. You can use this transformer with Japanese locales.
The transformer has properties shown in the following table.
Property | Type | Required | Description |
---|---|---|---|
|
String |
Yes |
Set to |
|
String |
Yes |
Path to a property in the data source that contains the text input to transform. Must be a property within the |
|
String |
No |
Name of the property to add to the |
|
String |
Yes |
Locale of the text provided in |
The following example shows how to use the lineBreakProcessor
transformer in a datasource with Japanese text.
{
"catFactData": {
"type": "object",
"properties": {
"myText": "EU、日本から渡航解禁へ 7月1日"
},
"transformers": [
{
"inputPath": "myText",
"outputName": "transformedText",
"transformer": "lineBreakProcessor",
"locale": "ja-JP"
}
]
}
}
After the transformation, the transformed data source is
{
"catFactData": {
"type": "object",
"properties": {
"myText": "EU、日本から渡航解禁へ 7月1日",
"transformedText": "<nobr>EU、</nobr><nobr>日本</nobr><nobr>から</nobr><nobr>渡航</nobr><nobr>解禁</nobr><nobr>へ</nobr><nobr>7月1日</nobr>"
}
}
}
ssmlToSpeech transformer
The ssmlToSpeech
transformer converts an SSML string into a speakable entity. The text passed to this transformer must be valid SSML enclosed within <speak>
tags. For plain text, use the textToSpeech
transformer instead.
In your document, bind ssmlToSpeech
transformer output to the speech
property of a component. The code below shows a version of a "Cat Facts" skill that associates speech with a Text
component bound to the cat fact.
Note that the text
property points to catFactData.properties.catFact
, while the speech
component points to catFactData.properties.catFactSpeech
.
{
"type": "Container",
"item": {
"type": "Text",
"id": "catFactText",
"text": "${payload.catFactData.properties.catFact}",
"speech": "${payload.catFactData.properties.catFactSpeech}"
}
}
This example shows the corresponding catFactData
data source. Note that the properties
object has a property catFactSsml
that contains the actual text to use in the component. This property is used as input for both the ssmlToSpeech
and ssmlToText
transformers:
- The
ssmlToSpeech
transformer transforms the value ofcatFactSsml
into speech and places the output in a new property calledcatFactSpeech
. Recall that thecatFactSpeech
property is bound to thespeech
property in theText
component shown earlier. - The
ssmlToText
transformer transforms the value ofcatFactSsml
into plain text and places the output in a new property calledcatFact
. Recall that thecatFact
property is bound to thetext
property in theText
component shown earlier.
{
"catFactData": {
"type": "object",
"properties": {
"backgroundImage": "https://.../catfacts.png",
"title": "Cat Fact #9",
"logoUrl": "https://.../logo.png",
"image": "https://.../catfact9.png",
"catFactSsml": "<speak>Not all cats like <emphasis level='strong'>catnip</emphasis>.</speak>"
},
"transformers": [
{
"inputPath": "catFactSsml",
"outputName": "catFactSpeech",
"transformer": "ssmlToSpeech"
},
{
"inputPath": "catFactSsml",
"outputName": "catFact",
"transformer": "ssmlToText"
}
]
}
}
Finally, to read the cat fact, you send Alexa the Alexa.Presentation.APL.ExecuteCommands
directive with the SpeakItem
command. The code below shows the Alexa.Presentation.APL.ExecuteCommands
directive you can use to read the cat fact. Note that the token supplied in the ExecuteCommands
directive is required and must match the token provided by the skill in the RenderDocument
directive used to render the APL document.
{
"type": "Alexa.Presentation.APL.ExecuteCommands",
"token": "[SkillProvidedToken]",
"commands": [
{
"type": "SpeakItem",
"componentId": "catFactText",
"highlightMode": "line",
"align": "center"
}
]
}
Any text processed with the ssmlToSpeech
transformer displays in the Voice History page in the Alexa app. This section of the app displays Alexa's response to the user. The ssmlToSpeech
text is considered part of the voice response. Note that the text displays in the app even if you never use SpeakItem
to speak the processed text.
ssmlToText transformer
The SSML to text transformer converts a full SSML text string into text that is more appropriate for human reading by removing the SSML markup.
textToHint transformer
The textToHint
transformer converts the input to a hint with the correct user-configured wake word for the device (Try "Alexa, This is the hint"). Users can choose the wake word for their devices, so avoid hard-coding the word "Alexa" in your hint. You typically use this transformer with the AlexaFooter
responsive component.
For an example of displaying a hint, see Use the textToHint transformer.
textToSpeech transformer
The textToSpeech
transformer converts a plain text string into a speakable entity. The text passed to this transformer must be plain text. For SSML text, use the ssmlToSpeech
transformer instead.
This transformer works just like the ssmlToSpeech
transformer. You bind the textToSpeech
transformer output to the speech
property of a component, then use the SpeakItem
command to speak the text.
This example data source shows the same catFactData
data source shown earlier, but with plain text for the catFactText
property. In this case, since the catFactText
property is already plain text, there is no need for the ssmlToText
transformer.
{
"catFactData": {
"type": "object",
"properties": {
"backgroundImage": "https://.../catfacts.png",
"title": "Cat Fact #9",
"logoUrl": "https://.../logo.png",
"image": "https://.../catfact9.png",
"catFactText": "Not all cats like catnip."
},
"transformers": [
{
"inputPath": "catFactText",
"outputName": "catFactSpeech",
"transformer": "textToSpeech"
}
]
}
}
You can then reference this data source in the Text
component like this:
{
"type": "Container",
"item": {
"type": "Text",
"id": "catFactText",
"text": "${payload.catFactData.properties.catFactText}",
"speech": "${payload.catFactData.properties.catFactSpeech}"
}
}
The text
property binds to the un-transformed, plain text catFactText
property. The speech
property binds to the output of the transformer.
Any text processed with the textToSpeech
transformer displays in the Voice History page in the Alexa app. This section of the app displays Alexa's response to the user. The textToSpeech
text is considered part of the voice response. Note that the text displays in the app even if you never use SpeakItem
to speak the processed text.
Related topics
Last updated: Nov 28, 2023