Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SSMLのマークアップ効率化のためにTypeScriptとJSXに手を出した話/aajug-2...

 SSMLのマークアップ効率化のためにTypeScriptとJSXに手を出した話/aajug-202005

Hidetaka Okamoto

May 29, 2020
Tweet

More Decks by Hidetaka Okamoto

Other Decks in Programming

Transcript

  1. npm i -S ssml-builder var Speech = require('ssml-builder'); var speech

    = new Speech(); speech.say('Hello') .pause('1s') .say('fellow Alexa developers') .pause('500ms') .say('Testing phone numbers') .sayAs({ word: "+1-377-777-1888", interpret: "telephone" }); var speechOutput = speech.ssml(true); • ϝιουܗࣜͰSSMLΛදݱ • ม׵݁ՌΛϨεϙϯε΁ ௥ՃͰ͖Δ • ϝιουνΣʔϯͰ ॊೈʹ௥ՃՄೳ
  2. npm i -S speechmarkdow n-js const smd = require('speechmarkdown-js'); const

    markdown = `Sample [3s] speech [250ms] markdown`; const options = { platform: 'amazon-alexa' }; const speech = new smd.SpeechMarkdown(); const ssml = speech.toSSML(markdown, options); === RESULT === <speak> Sample <break time="3s"/> speech <break time="250ms"/> markdown </speak> • MarkdownͰSSMLΛهड़ • ϚϧνϓϥοτϑΥʔϜରԠ • fsͳͲΛ૊Έ߹Θͤͯ .mdϑΝΠϧʹهड़΋Մೳ
  3. ReactͷΑ͏ʹ SSMLΛॻ͖͍ͨ import React from 'react'; import { CopyToClipboard }

    from 'react-copy-to- clipboard'; const CopyLink = ({param}: {param: string}) => ( <CopyToClipboard text={param}> <span> {param} <i className="fa fa-copy ml-1" style={{ cursor: 'pointer' }} /> </span> </CopyToClipboard> ); export default () => { return <CopyLink param={`https://google.com`} /> } • ॻ͖׳ΕͨϑΥʔϚοτ • View (Speech)΁ͷϑΥʔΧε Λڧ੍Ͱ͖Δ • JSΒ͍͠ಈతͳॲཧ΋Մೳ
  4. npm i -S ssml-tsx /** @jsx ssml */ import ssml,

    { rendetToString, FC } from "ssml-tsx"; const Foo= ({ name }) => ( <speak> <say-as interpret-as="characters">{name}</say-as> <break time="2s" /> <p>What would you like to do today?</p> </speak> ); console.log(renderToString(<Foo name="bar" />)); • SSMLΛJSXͰॻ͚Δ • from TimeTree • GitHubͷϨεϙϯε΋ૣ͍ • ݱঢ়͜ΕҰ୒
  5. JSX / TSX͸ ม׵ඞਢ // Example for Babel { "plugins":

    [ ["transform-jsx", { "function": "ssml", "useVariables": true }] ] } • JSX / TSX͸JSͰಈ͔ͳ͍ • BabelͰͷม׵͕Ұൠత • ४උͷҰखؒΛڐ༰Ͱ͖Δ͔ ͕෼ਫྮ • Ͳ͏ͤ΍ΔͳΒTypeScript
  6. JSX΍ΔͳΒ TypeScript { "compilerOptions": { ..., + "jsx": "react", }

    } • tscίϚϯυͰ·ͱΊͯ ίϯύΠϧ • ܕݕূͷԸܙ͸େ͖͍ • ASK SDK΋TypeScriptରԠ
  7. ࣮૷αϯϓϧ ʢSSMLʣ /** @jsx ssml */ import { ssml, SpeechScriptJSX

    } from '@ask-utils/speech-script' class LaunchRequestScriptForEnglish extends SpeechScriptJSX { speech() { return ( <speak> Hello! <break time="0.5s"/>How are you? </speak> ) } reprompt() { return ( <speak> How are you?<break time="0.5s"/> <amazon-effect name="whispered">I hope you to have a good day.</amazon-effect> </speak> ) } } • speech / repromptͦΕͧΕʹ JSXͰϚʔΫΞοϓ • this.props͔ΒϦΫΤετ಺༰ ͕ͱΕΔ • ReactϥΠΫʹهड़Մೳ
  8. ࣮૷αϯϓϧ ʢHandlerʣ const handler = { canHandle(handlerInput) { return handlerInput.requestEnvelope.request.type

    === 'LaunchRequest' }, handle(handlerInput) { const Speech = new LaunchRequestScript(handlerInput) return Speech.createResponse() } } • SSMLΛॻ͍ͨΫϥεΛར༻͢ Δ • responseBuilder಺ଂͳͷͰɺ ͦͷ··return͢Ε͹OK
  9. Next Step: Localization class LaunchRequestScriptForJapanse extends LaunchRequestScript { speech() {

    return ( <speak>͜Μʹͪ͸</speak> ) } } class LaunchRequestScriptForEnglish extends LaunchRequestScript { speech() { return ( <speak>Hello! <break time="0.5s"/>How are you?</speak> ) } } export const createLaunchRequestScript = (handlerInput: HandlerInput, options?: LaunchRequestProps): SpeechScriptJSX => { const factory = new L11NSpeechScriptJSXFactory({ allowLanguageMatcher: true }).putLocales({ locale: 'ja-JP', script: new LaunchRequestScriptForJapanese(handlerInput, options) }, { locale: 'en-US', script: new LaunchRequestScriptForEnglish(handlerInput, options) }) return factory.create(handlerInput) } • ݴޠ͝ͱʹSSMLΛهड़͢Δ • en-USͳͲͷݫີͳ੔߹ͱɺ en͚ͩͰ·ΔΊΔ؇͍੔߹ ྆ํΛαϙʔτʢ༧ఆʣ