Double Up Now

What R U Waiting FOR!!! Find Out MoreDouble Up Now

How To Maintain A Speech Synthesis Editor

Posted on

About The Creator

Knut Melvær is a humanities technologist currently working as Developer Advocate at Sanity.io. He has previously been a abilities e book and developer at …
More about Knut

Affirm Assistants are on their manner into other folks’s homes, wrists, and pockets. Which technique that some of our allege will be spoken out loud with the reduction of digital speech synthesis. On this tutorial, you are going to be taught to compose a What You Gain Is What You Hear (WYGIWYH) editor for speech synthesis the spend of Sanity.io’s editor for Transportable Textual allege.

When Steve Jobs unveiled the Macintosh in 1984, it acknowledged “Hi there” to us from the stage. Even at that point, speech synthesis wasn’t for tear a brand fresh abilities: Bell Labs developed the vocoder as early as in the late 30s, and the belief of a declare assistant computer made it into other folks’s consciousness when Stanley Kubrick made the vocoder the declare of HAL9000 in 2001: A House Odyssey (1968).

It wasn’t sooner than the introduction of Apple’s Siri, Amazon Echo, and Google Assistant in the mid 2015s that declare interfaces actually realized their manner into a broader public’s homes, wrists, and pockets. We’re light in an adoption section, however it absolutely looks these declare assistants are right here to defend.

In assorted words, the web isn’t unbiased appropriate passive text on a shroud anymore. Net editors and UX designers desire to get accustomed to creating allege and companies that must be spoken out loud.

We’re already difficult hasty in the direction of the spend of allege administration methods that allow us work with our allege headlessly and via APIs. The final part is to compose editorial interfaces that compose it more uncomplicated to tailor allege for declare. So let’s attain unbiased appropriate that!

What Is SSML

While web browsers spend W3C’s specification for HyperText Markup Language (HTML) to visually render paperwork, most declare assistants spend Speech Synthesis Markup Language (SSML) when generating speech.

A minimal instance the spend of the muse instruct , and the paragraph (

) and sentence () tags:


  

This is the first sentence of the paragraph. Right here’s one other sentence.

Press play to listen to to the snippet:

The set SSML will get existing is when we introduce tags for and (pitch):


  

Establish some further weight on these words And speak this unbiased a small higher and faster!

Press play to listen to to the snippet:

SSML has extra sides, however this is ample to get a for tear feel for the basics. Now, let’s think a nearer gape on the editor that we are going to spend to compose the speech synthesis editing interface.

The Editor For Transportable Textual allege

To compose this editor, we’ll spend the editor for Transportable Textual allege that sides in Sanity.io. Transportable Textual allege is a JSON specification for rich text editing, that is also serialized into any markup language, such as SSML. This implies you are going to be in a region to with out complications spend the the same text snippet in extra than one places the spend of assorted markup languages.

Sanity.io’s default editor for Transportable Textual allege
Sanity.io’s default editor for Transportable Textual allege (Massive preview)

Installing Sanity

Sanity.io is a platform for structured allege that comes with an launch-source editing setting built with React.js. It takes two minutes to get it all up and running.

Form npm i -g @sanity/cli && sanity init into your terminal, and practice the instructions. Decide “empty”, if you’re prompted for a project template.

While you happen to don’t want to practice this tutorial and compose this editor from scratch, you are going to be in a region to additionally clone this tutorial’s code and practice the instructions in README.md.

When the editor is downloaded, you creep sanity launch in the project folder to launch it up. This can even unbiased launch a construction server that spend Sizzling Module Reloading to update adjustments as you edit its files.

How To Configure Schemas In Sanity Studio

Rising The Editor Files

We’ll launch by making a folder known as ssml-editor in the /schemas folder. In that folder, we’ll place some empty files:

/ssml-tutorial/schemas/ssml-editor
                        ├── alias.js
                        ├── emphasis.js
                        ├── annotations.js
                        ├── preview.js
                        ├── prosody.js
                        ├── sayAs.js
                        ├── blocksToSSML.js
                        ├── speech.js
                        ├── SSMLeditor.css
                        └── SSMLeditor.js

Now we can add allege schemas in these files. Direct material schemas are what defines the info structure for the rich text, and what Sanity Studio uses to generate the editorial interface. They are easy JavaScript objects that largely require unbiased appropriate a name and a form.

We are capable of additionally add a title and a description to compose unbiased a small nicer for editors. As an illustration, this will be a schema for a easy text arena for a title:

export default {
  name: 'title',
  form: 'string',
  title: 'Title',
  description: 'Titles must be brief and descriptive'
}
Sanity Studio with a title arena and an editor for Transportable Textual allege
The studio with our title arena and the default editor (Massive preview)

Transportable Textual allege is built on the muse of rich text as data. This is extremely tremendous because of it lets in you to query your rich text, and convert it into slightly grand any markup you should love.

It is an array of objects known as “blocks” which you are going to be in a region to imagine as the “paragraphs”. In a block, there is an array of young other folks spans. Every block can like a mode and a feature of place definitions, which relate data constructions disbursed on the young other folks spans.

Sanity.io comes with an editor that could be taught and write to Transportable Textual allege, and is activated by placing the block form interior an array arena, like this:

// speech.js
export default {
  name: 'speech',
  form: 'array',
  title: 'SSML Editor',
  of: [
    { type: 'block' }
  ]
}

An array is also of extra than one kinds. For an SSML-editor, these would be blocks for audio files, however that falls exterior of the scope of this tutorial.

The final thing we want to attain is as a way to add a allege form where this editor is also stale. Most assistants spend a easy allege mannequin of “intents” and “fulfillments”:

  • Intents
    In overall a checklist of strings stale by the AI mannequin to delineate what the user wishes to get accomplished.
  • Fulfillments
    This occurs when an “intent” is identified. A fulfillment on the total is — or no longer decrease than — comes with some construct of response.

So let’s compose a easy allege form known as fulfillment that spend the speech synthesis editor. Maintain a brand fresh file known as fulfillment.js and reserve it in the /schema folder:

// fulfillment.js
export default {
  name: 'fulfillment',
  form: 'doc',
  title: 'Fulfillment',
  of: [
    {
      name: 'title',
      type: 'string',
      title: 'Title',
      description: 'Titles should be short and descriptive'
    },
    {
      name: 'response',
      type: 'speech'
    }
  ]
}

Set aside the file, and launch schema.js. Add it to your studio like this:

// schema.js
import createSchema from 'fragment:@sanity/unfriendly/schema-creator'
import schemaTypes from 'all:fragment:@sanity/unfriendly/schema-form'
import fullfillment from './fullfillment'
import speech from './speech'

export default createSchema({
  name: 'default',
  kinds: schemaTypes.concat([
    fullfillment,
    speech,
  ])
})

While you happen to now creep sanity launch to your account for line interface interior the project’s root folder, the studio will launch up in the neighborhood, and also you’ll be in a region as a way to add entries for fulfillments. You presumably can support the studio running while we meander on, as this could auto-reload with fresh adjustments if you place the files.

Adding SSML To The Editor

By default, the block form gives you a outmoded editor for visually oriented rich text with heading kinds, decorator kinds for emphasis and tough, annotations for hyperlinks, and lists. Now we want to override these with the audial concepts realized in SSML.

We launch with defining the assorted allege constructions, with priceless descriptions for the editors, that we are going as a way to add to the block in SSMLeditorSchema.js as configurations for annotations. These are “emphasis”, “alias”, “prosody”, and “speak as”.

Emphasis

We launch with “emphasis”, which controls how grand weight is place on the marked text. We account for it as a string with a checklist of predefined values that the user can care for from:

// emphasis.js
export default {
  name: 'emphasis',
  form: 'object',
  title: 'Emphasis',
  description:
    'The energy of the emphasis place on the contained text',
  fields: [
    {
      name: 'level',
      type: 'string',
      options: {
        list: [
          { value: 'strong', title: 'Strong' },
          { value: 'moderate', title: 'Moderate' },
          { value: 'none', title: 'None' },
          { value: 'reduced', title: 'Reduced' }
        ]
      }
    }
  ]
}

Alias

Now and again the written and the spoken time duration fluctuate. As an illustration, you should desire to make spend of the abbreviation of a phrase in a written text, however like the total phrase be taught aloud. As an illustration:

It is miles a SSML tutorial
Press play to listen to to the snippet:

The enter arena for the alias is a easy string:

// alias.js
export default {
  name: 'alias',
  form: 'object',
  title: 'Alias (sub)',
  description:
    'Replaces the contained text for pronunciation. This lets in a doc to own both a spoken and written construct.',
  fields: [
    {
      name: 'text',
      type: 'string',
      title: 'Replacement text',
    }
  ]
}

Prosody

With the prosody property we can regulate assorted functions how text must be spoken, like pitch, price, and quantity. The markup for this will gape like this:

Convey this with an further low pitch, and this loudly with a immediate price
Press play to listen to to the snippet:

This enter will like three fields with predefined string choices:

// prosody.js
export default {
  name: 'prosody',
  form: 'object',
  title: 'Prosody',
  description: 'Assign watch over of the pitch, talking price, and quantity',
  fields: [
    {
      name: 'pitch',
      type: 'string',
      title: 'Pitch',
      description: 'The baseline pitch for the contained text',
      options: {
        list: [
          { value: 'x-low', title: 'Extra low' },
          { value: 'low', title: 'Low' },
          { value: 'medium', title: 'Medium' },
          { value: 'high', title: 'High' },
          { value: 'x-high', title: 'Extra high' },
          { value: 'default', title: 'Default' }
        ]
      }
    },
    {
      name: 'price',
      form: 'string',
      title: 'Fee',
      description:
        'A alternate in the talking price for the contained text',
      choices: {
        checklist: [
          { value: 'x-slow', title: 'Extra slow' },
          { value: 'slow', title: 'Slow' },
          { value: 'medium', title: 'Medium' },
          { value: 'fast', title: 'Fast' },
          { value: 'x-fast', title: 'Extra fast' },
          { value: 'default', title: 'Default' }
        ]
      }
    },
    {
      name: 'quantity',
      form: 'string',
      title: 'Quantity',
      description: 'The amount for the contained text.',
      choices: {
        checklist: [
          { value: 'silent', title: 'Silent' },
          { value: 'x-soft', title: 'Extra soft' },
          { value: 'medium', title: 'Medium' },
          { value: 'loud', title: 'Loud' },
          { value: 'x-loud', title: 'Extra loud' },
          { value: 'default', title: 'Default' }
        ]
      }
    }
  ]
}

Convey As

The final one we want to consist of is . This mark lets us exercise unbiased a small extra regulate over how positive data is pronounced. We are capable of even spend it to bleep out words if you’re going to also unbiased desire to redact something in declare interfaces. That’s @!%&© necessary!

Procedure I even desire to frakking spell it out for you!?
Press play to listen to to the snippet:
// sayAs.js
export default {
  name: 'sayAs',
  form: 'object',
  title: 'Convey as...',
  description: 'Enables you to indicate data about the construct of text construct that is contained interior the problem. It additionally helps specify the diploma of instruct for rendering
  the contained text.',
  fields: [
    {
      name: 'interpretAs',
      type: 'string',
      title: 'Interpret as...',
      options: {
        list: [
          { value: 'cardinal', title: 'Cardinal numbers' },
          {
            value: 'ordinal',
            title: 'Ordinal numbers (1st, 2nd, 3th...)'
          },
          { value: 'characters', title: 'Spell out characters' },
          { value: 'fraction', title: 'Say numbers as fractions' },
          { value: 'expletive', title: 'Blip out this word' },
          {
            value: 'unit',
            title: 'Adapt unit to singular or plural'
          },
          {
            value: 'verbatim',
            title: 'Spell out letter by letter (verbatim)'
          },
          { value: 'date', title: 'Say as a date' },
          { value: 'telephone', title: 'Say as a telephone number' }
        ]
      }
    },
    {
      name: 'date',
      form: 'object',
      title: 'Date',
      fields: [
        {
          name: 'format',
          type: 'string',
          description: 'The format attribute is a sequence of date field character codes. Supported field character codes in format are {y, m, d} for year, month, and day (of the month) respectively. If the field code appears once for year, month, or day then the number of digits expected are 4, 2, and 2 respectively. If the field code is repeated then the number of expected digits is the number of times the code is repeated. Fields in the date text may be separated by punctuation and/or spaces.'
        },
        {
          name: 'detail',
          type: 'number',
          validation: Rule =>
            Rule.required()
              .min(0)
              .max(2),
          description: 'The detail attribute controls the spoken form of the date. For detail='1' only the day fields and one of month or year fields are required, although both may be supplied'
        }
      ]
    }
  ]
}

Now we can import these in an annotations.js file, which makes things unbiased a small tidier.

// annotations.js
export {default as alias} from './alias'
export {default as emphasis} from './emphasis'
export {default as prosody} from './prosody'
export {default as sayAs} from './sayAs'

Now we can import these annotation kinds into our well-known schemas:

// schema.js
import createSchema from "fragment:@sanity/unfriendly/schema-creator"
import schemaTypes from "all:fragment:@sanity/unfriendly/schema-form"
import fulfillment from './fulfillment'
import speech from './ssml-editor/speech'
import {
  alias,
  emphasis,
  prosody,
  sayAs
} from './annotations'

export default createSchema({
  name: "default",
  kinds: schemaTypes.concat([
    fulfillment,
    speech,
    alias,
    emphasis,
    prosody,
    sayAs
  ])
})

At final, we can now add these to the editor like this:

// speech.js
export default {
  name: 'speech',
  form: 'array',
  title: 'SSML Editor',
  of: [
    {
      type: 'block',
      styles: [],
      lists: [],
      marks: {
        decorators: [],
        annotations: [
          {type: 'alias'},
          {type: 'emphasis'},
          {type: 'prosody'},
          {type: 'sayAs'}
        ]
      }
    }
  ]
}

Explore that we additionally added empty arrays to kinds, and decorators. This disables the default kinds and interior decorators (like dauntless and emphasis) since they don’t compose that grand sense in this particular case.

Customizing The See And Feel

Now we like now got the efficiency in residing, however since we haven’t specified any icons, each annotation will spend the default icon, which makes the editor laborious to actually spend for authors. So let’s fix that!

With the editor for Transportable Textual allege it’s doubtless to inject React parts both for the icons and for how the marked text must be rendered. Right here, we’ll unbiased appropriate let some emoji attain the work for us, however you are going to clearly meander some distance with this, making them dynamic and heaps others. For prosody we’ll even compose the icon alternate looking out on the quantity selected. Showcase that I omitted the fields in these snippets for brevity, you shouldn’t take them to your native files.

// alias.js
import React from 'react'

export default {
  name: 'alias',
  form: 'object',
  title: 'Alias (sub)',
  description: 'Replaces the contained text for pronunciation. This lets in a doc to own both a spoken and written construct.',
  fields: [
    /* all the fields */
  ],
  blockEditor: {
    icon: () => '🔤',
    render: ({ young other folks }) => {young other folks} 🔤,
  },
};
// emphasis.js
import React from 'react'

export default {
  name: 'emphasis',
  form: 'object',
  title: 'Emphasis',
  description: 'The energy of the emphasis place on the contained text',
  fields: [
    /* all the fields */
  ],
  blockEditor: {
    icon: () => '🗯',
    render: ({ young other folks }) => {young other folks} 🗯,
  },
};

// prosody.js
import React from 'react'

export default {
  name: 'prosody',
  form: 'object',
  title: 'Prosody',
  description: 'Assign watch over of the pitch, talking price, and quantity',
  fields: [
    /* all the fields */
  ],
  blockEditor: {
    icon: () => '🔊',
    render: ({ young other folks, quantity }) => (
      
        {young other folks} {['x-loud', 'loud'].entails(quantity) ? '🔊' : '🔈'}
      
    ),
  },
};
// sayAs.js
import React from 'react'

export default {
  name: 'sayAs',
  form: 'object',
  title: 'Convey as...',
  description: 'Enables you to indicate data about the construct of text construct that is contained interior the problem. It additionally helps specify the diploma of instruct for rendering the contained text.',
  fields: [
    /* all the fields */
  ],
  blockEditor: {
    icon: () => '🗣',
    render: props => {props.young other folks} 🗣,
  },
};

The customized SSML editor
The editor with our custom SSML marks (Massive preview)

Now you are going to also unbiased like an editor for editing text that is also stale by declare assistants. However wouldn’t it be kinda necessary if editors additionally may perhaps presumably preview how the text actually will sound like?

Adding A Preview Button The usage of Google’s Textual allege-to-Speech

Native speech synthesis pork up is de facto on its manner for browsers. However in this tutorial, we’ll spend Google’s Textual allege-to-Speech API which supports SSML. Constructing this preview efficiency will additionally be a demonstration of the manner you serialize Transportable Textual allege into SSML in whatever provider you should desire to make spend of this for.

Wrapping The Editor In A React Ingredient

We launch with opening the SSMLeditor.js file and add the next code:

// SSMLeditor.js
import React, { Fragment } from 'react';
import { BlockEditor } from 'fragment:@sanity/construct-builder';

export default feature SSMLeditor(props) {
  return (
    
      
    
  );
}

We like now wrapped the editor in our own React instruct. Your total props it wishes, collectively with the info it incorporates, are handed down in right-time. To actually spend this instruct, you should import it into your speech.js file:

// speech.js
import React from 'react'
import SSMLeditor from './SSMLeditor.js'

export default {
  name: 'speech',
  form: 'array',
  title: 'SSML Editor',
  inputComponent: SSMLeditor,
  of: [
    {
      type: 'block',
      styles: [],
      lists: [],
      marks: {
        decorators: [],
        annotations: [
          { type: 'alias' },
          { type: 'emphasis' },
          { type: 'prosody' },
          { type: 'sayAs' },
        ],
      },
    },
  ],
}

While you happen to place this and the studio reloads, it will possibly presumably also unbiased light gape slightly grand exactly the the same, however that’s because of we haven’t started tweaking the editor yet.

Convert Transportable Textual allege To SSML

The editor will place the allege as Transportable Textual allege, an array of objects in JSON that makes it easy to convert rich text into whatever structure you wish it to be. While you happen to convert Transportable Textual allege into one other syntax or structure, we call that “serialization”. Therefore, “serializers” are the recipes for how the rich text must be transformed. On this fragment, we can add serializers for speech synthesis.

It is doubtless you’ll presumably presumably also unbiased like already made the blocksToSSML.js file. Now we’ll have to add our first dependency. Birth by running the terminal account for npm init -y contained in the ssml-editor folder. This will add a kit.json where the editor’s dependencies will be listed.

Once that’s accomplished, you are going to be in a region to creep npm set up @sanity/block-allege-to-html to get a library that makes it more uncomplicated to serialize Transportable Textual allege. We’re the spend of the HTML-library because of SSML has the the same XML syntax with tags and attributes.

It is miles a bunch of code, so attain for tear feel free to reproduction-paste it. I’ll show shroud the sample unbiased appropriate below the snippet:

// blocksToSSML.js
import blocksToHTML, { h } from '@sanity/block-allege-to-html'

const serializers = {
  marks: {
    prosody: ({ young other folks, place: { price, pitch, quantity } }) =>
      h('prosody', { attrs: { price, pitch, quantity } }, young other folks),
    alias: ({ young other folks, place: { text } }) =>
      h('sub', { attrs: { alias: text } }, young other folks),
    sayAs: ({ young other folks, place: { interpretAs } }) =>
      h('speak-as', { attrs: { 'define-as': interpretAs } }, young other folks),
    ruin: ({ young other folks, place: { time, energy } }) =>
      h('ruin', { attrs: { time: '${time}ms', energy } }, young other folks),
    emphasis: ({ young other folks, place: { diploma } }) =>
      h('emphasis', { attrs: { diploma } }, young other folks)
  }
}

export const blocksToSSML = blocks => blocksToHTML({ blocks, serializers })

This code will export a feature that takes the array of blocks and loop via them. At any time when a block incorporates a place, this could look for a serializer for the form. While you happen to may perhaps presumably also unbiased like marked some text to love emphasis, it this feature from the serializers object:

emphasis: ({ young other folks, place: { diploma } }) =>
      h('emphasis', { attrs: { diploma } }, young other folks)

Maybe you watch the parameter from where we outlined the schema? The h() feature lets us outlined an HTML instruct, that is, right here we “cheat” and makes it return an SSML instruct known as . We additionally give it the attribute diploma if that is printed, and residing the young other folks parts interior it — which in most circumstances could be the text you are going to also unbiased like marked up with emphasis.

{
    "_type": "block",
    "_key": "f2c4cf1ab4e0",
    "trend": "identical old",
    "markDefs": [
        {
            "_type": "emphasis",
            "_key": "99b28ed3fa58",
            "level": "strong"
        }
    ],
    "young other folks": [
        {
            "_type": "span",
            "_key": "f2c4cf1ab4e01",
            "text": "Say this strongly!",
            "marks": [
                "99b28ed3fa58"
            ]
        }
    ]
}

That is how the above structure in Transportable Textual allege will get serialized to this SSML:

Convey this strongly

While you happen to have to love pork up for added SSML tags, you are going to be in a region as a way to add extra annotations in the schema, and add the annotation kinds to the marks fragment in the serializers.

Now we like now got a feature that returns SSML markup from our marked up rich text. The final fragment is to compose a button that lets us send this markup to a text-to-speech provider.

Adding A Preview Button That Speaks Lend a hand To You

Ideally, we would also unbiased light like stale the browser’s speech synthesis capabilities in the Net API. That manner, we’d like gotten away with much less code and dependencies.

As of early 2019, on the opposite hand, native browser pork up for speech synthesis is light in its early stages. It feels like pork up for SSML is on the manner, and there is proof of concepts of consumer-aspect JavaScript implementations for it.

Likelihood is that you just are going to make spend of this allege with a declare assistant anyways. Both Google Assistant and Amazon Echo (Alexa) pork up SSML as responses in a fulfillment. On this tutorial, we can spend Google’s text-to-speech API, which additionally sounds appropriate and pork up lots of languages.

Commence by obtaining an API key by signing up for Google Cloud Platform (this could well also be free for the first 1 million characters you course of). If you’re signed up, you are going to be in a region to compose a brand fresh API key on this web allege.

Now you are going to be in a region to launch your PreviewButton.js file, and add this code to it:

// PreviewButton.js
import React from 'react'
import Button from 'fragment:@sanity/parts/buttons/default'
import { blocksToSSML } from './blocksToSSML'

// It is advisable be cautious with sharing this key
// I place it right here to defend the code easy
const API_KEY = ''
const GOOGLE_TEXT_TO_SPEECH_URL = 'https://texttospeech.googleapis.com/v1beta1/text:synthesize?key=' + API_KEY

const communicate = async blocks => {
  // Serialize blocks to SSML
  const ssml = blocksToSSML(blocks)
  // Prepare the Google Textual allege-to-Speech configuration
  const physique = JSON.stringify({
    enter: { ssml },
    // Capture the language code and declare name (A-F)
    declare: { languageCode: 'en-US', name: 'en-US-Wavenet-A' },
    // Exercise MP3 in relate to play in browser
    audioConfig: { audioEncoding: 'MP3' }
  })
  // Ship the SSML string to the API
  const res = look ahead to in discovering(GOOGLE_TEXT_TO_SPEECH_URL, {
    technique: 'POST',
    physique
  }).then(res => res.json())
  // Play the returned audio with the Browser’s Audo API
  const audio = fresh Audio('data:audio/wav;base64,' + res.audioContent)
  audio.play()
}

export default feature PreviewButton (props) {
  return 
}

I’ve stored this preview button code to a minimal to compose it more uncomplicated to practice this tutorial. In the end, you are going to possess it out by adding negate to indicate if the preview is processing or compose it doubtless to preview with the assorted voices that Google’s API supports.

Add the button to SSMLeditor.js:

// SSMLeditor.js
import React, { Fragment } from 'react';
import { BlockEditor } from 'fragment:@sanity/construct-builder';
import PreviewButton from './PreviewButton';

export default feature SSMLeditor(props) {
  return (
    
      
      
    
  );
}

Now strive with a aim to place up your text with the assorted annotations, and hear the consequence when pushing “Deny text”. Cold, isn’t it?

You’ve Created A Speech Synthesis Editor, And Now What?

While you happen to may perhaps presumably also unbiased like followed this tutorial, you are going to also unbiased had been via the manner you are going to be in a region to spend the editor for Transportable Textual allege in Sanity Studio to compose custom annotations and customize the editor. You presumably can spend these abilities for all forms of things, no longer easiest to compose a speech synthesis editor. It is doubtless you’ll presumably presumably also unbiased like additionally been via tips on how to serialize Transportable Textual allege into the syntax you wish. Clearly, this is additionally at hand in case you’re constructing frontends in React or Vue. You presumably could spend these abilities to generate Markdown from Transportable Textual allege.

We haven’t covered the manner you positively spend this along with a declare assistant. While you happen to have to desire to identify out, you are going to be in a region to spend grand of the the same logic as with the preview button in a serverless feature, and feature it as the API endpoint for a fulfillment the spend of webhooks, e.g. with Dialogflow.

While you happen to’d like me to jot down an tutorial on tips on how to make spend of the speech synthesis editor with a declare assistant, for tear feel free to give me a splash on Twitter or fragment in the feedback fragment below.

Extra Reading on SmashingMag:

Smashing Editorial(dm, ra, yk, il)

Copyright © 2019 Double UP. All Rights Reserved. | Fotografie Blog by Catch Themes