Dustin Coates in Googleassistant

Actions on Google SDK V2 Preview: SSML Utilities

Dialogflow (ne API.AI) V1 hits end of life in May of 2018, and the Actions on Google team is working to bring a new JavaScript SDK that will support the new interface. V2 of the Actions on Google SDK is now available in alpha on Github and can be used (gingerly) in Google Assistant apps using Dialogflow V2. We’ll take a look at the new SDK in a series of posts, and today we start with a basic utility to work with SSML.

Utilities

One of the new additions to V2 is a set of discrete utilities that do specific tasks. These are so set apart, that the Actions team has requested feedback on whether they should be in separate NPM packages altogether. One such utility is for working with SSML. It’s a useful addition, as its one of those utilities that everyone needs to write at some point. This utility has two capabilities: create SSML tags, and sanitizing input for the SSML.

SSML Sanitzation Utility

The sanitization takes place through tagged template literals. Template literals are strings with data interpolated inside, whereas tagged template literals take a function and manipulate the strings and data, generally returning an assembled string.

const num = 10;
console.log(`I have written this code at least ${num} times!`);
// "I have written this code at least 10 times!"

function scream(strings, ...values) {
  return strings.map((str, i) => str.toUpperCase() + (values[i] || '')).join('');
}

console.log(scream`Hello, I am ${myName}, nice to meet you.`);
// "HELLO, I AM Dustin, NICE TO MEET YOU."

The Actions SDK V2 SSML utility takes a template string and returns SSML that is properly escaped, and with excess whitespace removed. The escaping makes sure that an errant < or > doesn’t cause issues with Assistant parsing the SSML (it is XML, afterall). The whitespace removal allows for easier-to-read SSML in the fulfillment code. Here’s an example directly from the Actions SDK itself.

const { ssml } = require('actions-on-google/util/ssml');
const equation = '"1 + 1 > 1"'
ssml`
  <speak>
    ${equation}
  </speak>
`
// "<speak>&quot;1 + 1 &gt; 1&quot;</speak>"

Could you do this yourself? Sure. Do you want to write it each time? No, no you don’t.

ssml#create

There’s one more utility: ssml.create. This function takes an object and creates an SSML string:

ssml.create(`say-as`, {"interpret-as": `cardinal`}, 100)
// '<say-as interpret-as="cardinal">100</say-as>'

The primary use of this function is for JSX support. JSX uses ssml.create as the JSX factory, which transforms JSX code to a string. With this syntax, you can more easily create long SSML, including something like this:

import * as functions from 'firebase-functions'
import { dialogflow, ssml } from '../../../src'

const app = dialogflow()

app.intent('Default Welcome Intent', conv => {
  conv.ask(
    <speak>
      Hello
      <break time="1s" strength="strong"/>
      <say-as interpret-as="characters">Hello</say-as>
      <audio src="https://actions.google.com/sounds/v1/animals/cat_purr_close.ogg">
        <desc>a cat purring</desc>
        PURR (sound didn't load)
      </audio>
      <p>
        <s>This is sentence one.</s>
        <s>This is sentence two.</s>
      </p>
      <sub alias="World Wide Web Consortium">W3C</sub>
      <prosody rate="slow" pitch="-2st">Can you hear me now?</prosody>
      <emphasis level="moderate">This is an important announcement</emphasis>
      <speak>
        <par>
          <media xmlId="question" begin="0.5s">
            <speak>Who invented the Internet?</speak>
          </media>
          <media xmlId="answer" begin="question.end+2.0s">
            <speak>The Internet was invented by cats.</speak>
          </media>
          <media begin="answer.end-0.2s" soundLevel="-6db">
            <audio src="https://actions.google.com/sounds/v1/cartoon/cartoon_boing.ogg"/>
          </media>
          <media
            repeatCount={3}
            soundLevel="+2.28dB"
            fadeInDur="2s"
            fadeOutDur="0.2s">
            <audio src="https://actions.google.com/sounds/v1/cartoon/cartoon_boing.ogg"/>
          </media>
        </par>
      </speak>
    </speak>,
  )
})

exports.dialog = functions.https.onRequest(app)

Interested in more of this tour of what new the Actions SDK V2 has that will soon be available in a stable release? Follow along, and get notifications of new posts by following me on Twitter.