ask-sdk / ssml-tsx と Serverless Frameworkを使ってReactライクに発話を定義する
ask-sdkを使うことで、Alexaの会話内容をスクリプタブルに定義できます。 簡単なユースケースであればこれで事足りるのですが、SSMLを駆使した表現を目指すとなるとstringでSSMLを書かないといけない部分など […]
目次
ask-sdkを使うことで、Alexaの会話内容をスクリプタブルに定義できます。
input.responseBuilder.speak([
'Hello world!',
'This is a example sppech content from the skill',
'The cardinal number is <say-as interpret-as="cardinal">12345</say-as>''
].join(' ')).getResponse()
-> "<speak>Hello world! This is a example sppech content from the skill The cardinal number is <say-as interpret-as="cardinal">12345</say-as></speak>"
簡単なユースケースであればこれで事足りるのですが、SSMLを駆使した表現を目指すとなるとstringでSSMLを書かないといけない部分などが断端辛くなってきます。
ssml-tsxを使ってReactライクに記述する
ReactなどのJSXを書いたことがある人であれば、ssml-tsx
を使うのが良さげです。
$ yarn add ssml-tsx
$ vim tsconfig.json
{
"compilerOptions": {
"lib": ["es2017"],
"jsx": "react", // この行を追記する
もしServerless FrameworkでLambdaを管理してる場合は webpack.config.js
も触りましょう。
...
module.exports = {
...
resolve: {
// `.tsx` を追加する
extensions: ['.mjs', '.json', '.ts', '.tsx'],
symlinks: false,
するとSSMLをTSXで定義できるようになります。
$ vim example.tsx
/** @jsx ssml */
import ssml, { renderToString } from "ssml-tsx";
export const speak = renderToString(
<speak>
Hello world! This is a example sppech content from the skill .
The cardinal number is <say-as interpret-as="cardinal">12345</say-as>
</speak>
);
$ vim index.ts
import {speak } from './example'
input.responseBuilder.speak(speak).getResponse()
-> <speak>Hello world! This is a example sppech content from the skill . The cardinal number is <say-as interpret-as="cardinal">12345</say-as></speak>"
Advanced usage
JSX / TSXなので、Reactのようにプロパティを渡すこともできます。カスタムコンポーネントを使う場合はFC
をインポートして型をつけてやりましょう。
// example.tsx
/** @jsx ssml */
import ssml, { renderToString, FC } from "ssml-tsx";
type GreetingComponent = FC<{name?: string}>
const WelcomeMessage: GreetingComponent = ({name}) => {
if (!name) return <p>Hello!</p>
return <p>Hello {name} san!</p>
}
const GreetingMessage: GreetingComponent= ({name}) => (
<speak>
<WelcomeMessage name={name} />
This is a example component to use ssml-tsx.
</speak>
)
export const getGreetingPrompt = (name?: string) => renderToString(
<GreetingMessage name={name} />
)
// index.ts
import { getGreetingPrompt } from './example'
input.responseBuilder.speak(getGreetingPrompt('John')).getResponse()
-> "<speak><p>Hello John san!</p>This is a example component to use ssml-tsx.</speak>"
こうなると条件分岐のある発話も結構楽にかけます。
既知の問題 (in Apr. 9)
今のところ
amazon:domain
/ amazon:effect
/ amazon:emotion
のタグはうまく動かない様子です。原因の検討はついたのでレポートとPR作成までやってありますので、遠からず解決するとは思います。
- https://github.com/jubilee-works/ssml-tsx/issues/40
- https://github.com/jubilee-works/ssml-tsx/pull/41
Apr. 10: the issue has been resolved
amazon:XXX
タグについて、version 1.0.9にて解決されました。
https://github.com/jubilee-works/ssml-tsx/releases/tag/v1.0.9
<XXX:YYY>
のようにコロンで区切るマークアップがJSXではできないため、<amazon-domain>
や<amazon-effect>
のようにハイフンで区切って実装する形となっています。
まとめ
結構こういう周辺ライブラリ入れると実装楽になるので、「おれの思う最強のAlexaスキル開発環境話」が増えてくるとうれしいなと思います。