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 the speech property of an APL component. You can then instruct Alexa to play the audio with the SpeakItem or SpeakList.
  • 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 the speech property of an APL component. You can then instruct Alexa to play the speech with the SpeakItem or SpeakList 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.
  • 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 the speech property of an APL component. The speech associated with the component can then be spoken using a SpeakItem 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.1",
    "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.1",
    "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 the outputName defined in the transformer.
  • Converts the APLA document to audio, replacing data binding expressions that reference data with the data from the itemList item. For example, when the transformer processes the first item, it replaces ${payload.data.name} with "Baseball" and payload.shoppingItems.properties.backgroundRoomAudio[payload.data.category] with the audio file "https://outdoor_sounds.mp3".
  • Saves the converted audio into a url property on the speech 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

transformer

String

Yes

Set to lineBreakProcessor

inputPath

String

Yes

Path to a property in the data source that contains the text input to transform. Must be a property within the properties object.

outputName

String

No

Name of the property to add to the properties object with the results of the transformation. When not provided, the transformer writes the result to the inputPath property.

locale

String

Yes

Locale of the text provided in inputPath. Determines which character sequences should not be broken. Must be a Japanese language locale, such as ja-JP.

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 of catFactSsml into speech and places the output in a new property called catFactSpeech. Recall that the catFactSpeech property is bound to the speech property in the Text component shown earlier.
  • The ssmlToText transformer transforms the value of catFactSsml into plain text and places the output in a new property called catFact. Recall that the catFact property is bound to the text property in the Text 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.


Was this page helpful?

Last updated: Nov 28, 2023