So erstellen Sie einen Sprachsynthese-Editor
Veröffentlicht: 2022-03-10Als Steve Jobs 1984 den Macintosh vorstellte, sagte er von der Bühne „Hallo“ zu uns. Schon damals war die Sprachsynthese keine wirklich neue Technologie: Bell Labs entwickelte den Vocoder bereits Ende der 30er Jahre, und das Konzept eines Sprachassistenten-Computers gelangte in das Bewusstsein der Menschen, als Stanley Kubrick den Vocoder zur Stimme machte HAL9000 im Jahr 2001: Odyssee im Weltraum (1968).
Erst mit der Einführung von Apples Siri, Amazon Echo und Google Assistant Mitte der 2015er Jahre fanden Sprachschnittstellen tatsächlich ihren Weg in die Haushalte, Handgelenke und Taschen einer breiteren Öffentlichkeit. Wir befinden uns noch in einer Einführungsphase, aber es scheint, dass diese Sprachassistenten hier bleiben werden.
Mit anderen Worten, das Web ist nicht mehr nur passiver Text auf einem Bildschirm . Webredakteure und UX-Designer müssen sich daran gewöhnen, Inhalte und Dienste zu erstellen, die laut ausgesprochen werden sollten.
Wir bewegen uns bereits schnell in Richtung der Verwendung von Content-Management-Systemen, mit denen wir kopflos und über APIs mit unseren Inhalten arbeiten können. Der letzte Teil besteht darin, redaktionelle Schnittstellen zu erstellen, die es einfacher machen, Inhalte für die Sprache anzupassen. Also lass uns genau das tun!
Was ist SSML
Während Webbrowser die W3C-Spezifikation für HyperText Markup Language (HTML) verwenden, um Dokumente visuell wiederzugeben, verwenden die meisten Sprachassistenten Speech Synthesis Markup Language (SSML), wenn sie Sprache erzeugen.
Ein minimales Beispiel mit dem Stammelement <speak>
und den Absatz- ( <p>
) und Satz- ( <s>
) Tags:
<speak> <p> <s>This is the first sentence of the paragraph.</s> <s>Here's another sentence.</s> </p> </speak>
Wo SSML existiert, ist, wenn wir Tags für <emphasis>
und <prosody>
(Tonhöhe) einführen:
<speak> <p> <s>Put some <emphasis strength="strong">extra weight on these words</emphasis></s> <s>And say <prosody pitch="high" rate="fast">this a bit higher and faster</prosody>!</s> </p> </speak>
SSML hat mehr Funktionen, aber das reicht aus, um ein Gefühl für die Grundlagen zu bekommen. Lassen Sie uns nun einen genaueren Blick auf den Editor werfen, mit dem wir die Sprachsynthese-Bearbeitungsschnittstelle erstellen werden.
Der Editor für portablen Text
Um diesen Editor zu erstellen, verwenden wir den Editor für Portable Text, der in Sanity.io enthalten ist. Portable Text ist eine JSON-Spezifikation für die Rich-Text-Bearbeitung, die in jede Auszeichnungssprache wie SSML serialisiert werden kann. Das bedeutet, dass Sie dasselbe Text-Snippet problemlos an mehreren Stellen mit unterschiedlichen Auszeichnungssprachen verwenden können.
Sanity installieren
Sanity.io ist eine Plattform für strukturierte Inhalte, die mit einer Open-Source-Bearbeitungsumgebung ausgestattet ist, die mit React.js erstellt wurde. Es dauert zwei Minuten, um alles zum Laufen zu bringen.
Geben Sie npm i -g @sanity/cli && sanity init
in Ihr Terminal ein und folgen Sie den Anweisungen. Wählen Sie „leer“, wenn Sie nach einer Projektvorlage gefragt werden.
Wenn Sie diesem Tutorial nicht folgen und diesen Editor von Grund auf neu erstellen möchten, können Sie auch den Code dieses Tutorials klonen und den Anweisungen in README.md
folgen.
Wenn der Editor heruntergeladen ist, führen Sie sanity start
im Projektordner aus, um ihn zu starten. Es startet einen Entwicklungsserver, der Hot Module Reloading verwendet, um Änderungen zu aktualisieren, während Sie seine Dateien bearbeiten.
So konfigurieren Sie Schemas in Sanity Studio
Erstellen der Editor-Dateien
Wir beginnen mit der Erstellung eines Ordners namens ssml-editor im Ordner /schemas . In diesem Ordner legen wir einige leere Dateien ab:
/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
Jetzt können wir Inhaltsschemata in diesen Dateien hinzufügen. Inhaltsschemata definieren die Datenstruktur für den Rich Text und werden von Sanity Studio zum Generieren der redaktionellen Benutzeroberfläche verwendet. Sie sind einfache JavaScript-Objekte, die meistens nur einen name
und einen type
benötigen.
Wir können auch einen title
und eine description
hinzufügen, um es für Redakteure etwas angenehmer zu machen. Dies ist beispielsweise ein Schema für ein einfaches Textfeld für einen title
:
export default { name: 'title', type: 'string', title: 'Title', description: 'Titles should be short and descriptive' }
Portable Text basiert auf der Idee von Rich Text als Daten. Dies ist leistungsstark, da Sie damit Ihren Rich-Text abfragen und in so ziemlich jedes gewünschte Markup konvertieren können.
Es ist eine Reihe von Objekten, die „Blöcke“ genannt werden und die Sie sich als „Absätze“ vorstellen können. In einem Block gibt es ein Array von untergeordneten Spans. Jeder Block kann einen Stil und einen Satz von Markierungsdefinitionen haben, die Datenstrukturen beschreiben, die auf die untergeordneten Spans verteilt sind.
Sanity.io wird mit einem Editor geliefert, der Portable Text lesen und schreiben kann, und wird aktiviert, indem der block
wie folgt in ein array
-Feld eingefügt wird:
// speech.js export default { name: 'speech', type: 'array', title: 'SSML Editor', of: [ { type: 'block' } ] }
Ein Array kann mehrere Typen haben. Für einen SSML-Editor könnten das Blöcke für Audiodateien sein, aber das würde den Rahmen dieses Tutorials sprengen.
Das letzte, was wir tun möchten, ist, einen Inhaltstyp hinzuzufügen, in dem dieser Editor verwendet werden kann. Die meisten Assistenten verwenden ein einfaches Inhaltsmodell von „Absichten“ und „Erfüllungen“:
- Absichten
Normalerweise eine Liste von Zeichenfolgen, die vom KI-Modell verwendet werden, um zu beschreiben, was der Benutzer erledigen möchte. - Erfüllungen
Dies geschieht, wenn eine „Absicht“ identifiziert wird. Eine Erfüllung ist oft – oder zumindest – kommt mit einer Art Reaktion.
Lassen Sie uns also einen einfachen Inhaltstyp namens fulfillment
, der den Sprachsynthese-Editor verwendet. Erstellen Sie eine neue Datei namens „ fulfillment.js “ und speichern Sie sie im Ordner „ /schema “:
// fulfillment.js export default { name: 'fulfillment', type: 'document', title: 'Fulfillment', of: [ { name: 'title', type: 'string', title: 'Title', description: 'Titles should be short and descriptive' }, { name: 'response', type: 'speech' } ] }
Speichern Sie die Datei und öffnen Sie schema.js . Fügen Sie es wie folgt zu Ihrem Studio hinzu:
// schema.js import createSchema from 'part:@sanity/base/schema-creator' import schemaTypes from 'all:part:@sanity/base/schema-type' import fullfillment from './fullfillment' import speech from './speech' export default createSchema({ name: 'default', types: schemaTypes.concat([ fullfillment, speech, ]) })
Wenn Sie jetzt sanity start
in Ihrer Befehlszeilenschnittstelle im Stammordner des Projekts ausführen, wird das Studio lokal gestartet und Sie können Einträge für Erfüllungen hinzufügen. Sie können das Studio weiterlaufen lassen, während wir weitermachen, da es automatisch mit neuen Änderungen geladen wird, wenn Sie die Dateien speichern.
Hinzufügen von SSML zum Editor
Standardmäßig gibt Ihnen der block
einen Standardeditor für visuell orientierten Rich-Text mit Überschriftenstilen, Dekorationsstilen für Hervorhebung und Stärke, Anmerkungen für Links und Listen. Jetzt wollen wir diese mit den in SSML gefundenen akustischen Konzepten überschreiben.
Wir beginnen mit der Definition der verschiedenen Inhaltsstrukturen mit hilfreichen Beschreibungen für die Editoren, die wir dem block
in SSMLeditorSchema.js als Konfigurationen für annotations
hinzufügen werden. Das sind „Betonung“, „Alias“, „Prosodie“ und „sagen als“.
Hervorhebung
Wir beginnen mit „Hervorhebung“, die steuert, wie viel Gewicht auf den markierten Text gelegt wird. Wir definieren es als eine Zeichenfolge mit einer Liste vordefinierter Werte, aus denen der Benutzer auswählen kann:
// emphasis.js export default { name: 'emphasis', type: 'object', title: 'Emphasis', description: 'The strength of the emphasis put 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
Manchmal unterscheiden sich der geschriebene und der gesprochene Begriff. Sie möchten beispielsweise die Abkürzung eines Satzes in einem geschriebenen Text verwenden, aber den ganzen Satz laut vorlesen lassen. Zum Beispiel:
<s>This is a <sub alias="Speech Synthesis Markup Language">SSML</sub> tutorial</s>
Das Eingabefeld für den Alias ist ein einfacher String:
// alias.js export default { name: 'alias', type: 'object', title: 'Alias (sub)', description: 'Replaces the contained text for pronunciation. This allows a document to contain both a spoken and written form.', fields: [ { name: 'text', type: 'string', title: 'Replacement text', } ] }
Prosodie
Mit der Prosodie-Eigenschaft können wir verschiedene Aspekte steuern, wie Text gesprochen werden soll, wie Tonhöhe, Rate und Lautstärke. Das Markup dafür kann wie folgt aussehen:
<s>Say this with an <prosody pitch="x-low">extra low pitch</prosody>, and this <prosody rate="fast" volume="loud">loudly with a fast rate</prosody></s>
Diese Eingabe enthält drei Felder mit vordefinierten Zeichenfolgenoptionen:
// prosody.js export default { name: 'prosody', type: 'object', title: 'Prosody', description: 'Control of the pitch, speaking rate, and volume', 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: 'rate', type: 'string', title: 'Rate', description: 'A change in the speaking rate for the contained text', options: { list: [ { 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: 'volume', type: 'string', title: 'Volume', description: 'The volume for the contained text.', options: { list: [ { 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' } ] } } ] }
Sagen Sie als
Das letzte, das wir einschließen möchten, ist <say-as>
. Mit diesem Tag können wir etwas mehr Kontrolle darüber ausüben, wie bestimmte Informationen ausgesprochen werden. Wir können es sogar verwenden, um Wörter auszupiepen, wenn Sie etwas in Sprachschnittstellen redigieren müssen. Das ist @!%& nützlich!
<s>Do I have to <say-as interpret-as="expletive">frakking</say-as> <say-as interpret-as="verbatim">spell</say-as> it out for you!?</s>
// sayAs.js export default { name: 'sayAs', type: 'object', title: 'Say as...', description: 'Lets you indicate information about the type of text construct that is contained within the element. It also helps specify the level of detail 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', type: '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' } ] } ] }
Jetzt können wir diese in eine annotations.js -Datei importieren, was die Sache etwas aufgeräumter macht.
// 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'
Jetzt können wir diese Anmerkungstypen in unsere Hauptschemas importieren:
// schema.js import createSchema from "part:@sanity/base/schema-creator" import schemaTypes from "all:part:@sanity/base/schema-type" import fulfillment from './fulfillment' import speech from './ssml-editor/speech' import { alias, emphasis, prosody, sayAs } from './annotations' export default createSchema({ name: "default", types: schemaTypes.concat([ fulfillment, speech, alias, emphasis, prosody, sayAs ]) })
Schließlich können wir diese jetzt wie folgt zum Editor hinzufügen:
// speech.js export default { name: 'speech', type: 'array', title: 'SSML Editor', of: [ { type: 'block', styles: [], lists: [], marks: { decorators: [], annotations: [ {type: 'alias'}, {type: 'emphasis'}, {type: 'prosody'}, {type: 'sayAs'} ] } } ] }
Beachten Sie, dass wir styles
und decorators
auch leere Arrays hinzugefügt haben. Dadurch werden die Standardstile und -dekoratoren (wie Fettdruck und Hervorhebung) deaktiviert, da sie in diesem speziellen Fall nicht sehr sinnvoll sind.
Anpassen des Aussehens und Verhaltens
Jetzt haben wir die Funktionalität eingerichtet, aber da wir keine Symbole angegeben haben, wird jede Anmerkung das Standardsymbol verwenden, was die tatsächliche Verwendung des Editors für Autoren erschwert. Also lasst uns das beheben!
Mit dem Editor für Portable Text ist es möglich, React-Komponenten sowohl für die Symbole als auch für die Darstellung des markierten Textes einzufügen. Hier lassen wir einfach einige Emoji die Arbeit für uns erledigen, aber Sie könnten damit offensichtlich weit kommen, sie dynamisch machen und so weiter. Für die prosody
ändern wir sogar das Symbol je nach ausgewählter Lautstärke. Beachten Sie, dass ich die Felder in diesen Snippets der Kürze halber weggelassen habe, Sie sollten sie nicht in Ihren lokalen Dateien entfernen.
// alias.js import React from 'react' export default { name: 'alias', type: 'object', title: 'Alias (sub)', description: 'Replaces the contained text for pronunciation. This allows a document to contain both a spoken and written form.', fields: [ /* all the fields */ ], blockEditor: { icon: () => '', render: ({ children }) => <span>{children} </span>, }, };
// emphasis.js import React from 'react' export default { name: 'emphasis', type: 'object', title: 'Emphasis', description: 'The strength of the emphasis put on the contained text', fields: [ /* all the fields */ ], blockEditor: { icon: () => '', render: ({ children }) => <span>{children} </span>, }, };
// prosody.js import React from 'react' export default { name: 'prosody', type: 'object', title: 'Prosody', description: 'Control of the pitch, speaking rate, and volume', fields: [ /* all the fields */ ], blockEditor: { icon: () => '', render: ({ children, volume }) => ( <span> {children} {['x-loud', 'loud'].includes(volume) ? '' : ''} </span> ), }, };
// sayAs.js import React from 'react' export default { name: 'sayAs', type: 'object', title: 'Say as...', description: 'Lets you indicate information about the type of text construct that is contained within the element. It also helps specify the level of detail for rendering the contained text.', fields: [ /* all the fields */ ], blockEditor: { icon: () => '', render: props => <span>{props.children} </span>, }, };
Jetzt haben Sie einen Editor zum Bearbeiten von Text, der von Sprachassistenten verwendet werden kann. Aber wäre es nicht irgendwie nützlich, wenn Redakteure auch eine Vorschau sehen könnten, wie der Text tatsächlich klingen wird?
Hinzufügen einer Vorschauschaltfläche mit Googles Text-to-Speech
Die Unterstützung nativer Sprachsynthese ist für Browser tatsächlich auf dem Weg. In diesem Tutorial verwenden wir jedoch die Text-to-Speech-API von Google, die SSML unterstützt. Das Erstellen dieser Vorschaufunktion wird auch eine Demonstration dessen sein, wie Sie Portable Text in SSML in dem Dienst, für den Sie dies verwenden möchten, serialisieren.
Einhüllen des Editors in eine React-Komponente
Wir beginnen mit dem Öffnen der Datei SSMLeditor.js und fügen den folgenden Code hinzu:
// SSMLeditor.js import React, { Fragment } from 'react'; import { BlockEditor } from 'part:@sanity/form-builder'; export default function SSMLeditor(props) { return ( <Fragment> <BlockEditor {...props} /> </Fragment> ); }
Wir haben den Editor jetzt in unsere eigene React-Komponente gehüllt. Alle benötigten Requisiten, einschließlich der darin enthaltenen Daten, werden in Echtzeit weitergegeben. Um diese Komponente tatsächlich zu verwenden, müssen Sie sie in Ihre speech.js
-Datei importieren:
// speech.js import React from 'react' import SSMLeditor from './SSMLeditor.js' export default { name: 'speech', type: 'array', title: 'SSML Editor', inputComponent: SSMLeditor, of: [ { type: 'block', styles: [], lists: [], marks: { decorators: [], annotations: [ { type: 'alias' }, { type: 'emphasis' }, { type: 'prosody' }, { type: 'sayAs' }, ], }, }, ], }
Wenn Sie dies speichern und das Studio neu lädt, sollte es ziemlich genau gleich aussehen, aber das liegt daran, dass wir noch nicht begonnen haben, den Editor zu optimieren.
Konvertieren Sie portablen Text in SSML
Der Editor speichert den Inhalt als Portable Text, ein Array von Objekten in JSON, das es einfach macht, Rich-Text in das gewünschte Format zu konvertieren. Wenn Sie Portable Text in eine andere Syntax oder ein anderes Format konvertieren, nennen wir das „Serialisierung“. Daher sind „Serializer“ die Rezepte dafür, wie der Rich Text konvertiert werden sollte. In diesem Abschnitt werden wir Serialisierer für die Sprachsynthese hinzufügen.
Sie haben bereits die Datei blocksToSSML.js erstellt. Jetzt müssen wir unsere erste Abhängigkeit hinzufügen. Beginnen Sie mit dem Ausführen des Terminalbefehls npm init -y
im Ordner ssml-editor
. Dadurch wird eine package.json hinzugefügt, in der die Abhängigkeiten des Editors aufgelistet werden.
Sobald dies erledigt ist, können Sie npm install @sanity/block-content-to-html
ausführen, um eine Bibliothek zu erhalten, die die Serialisierung von Portable Text erleichtert. Wir verwenden die HTML-Bibliothek, weil SSML die gleiche XML-Syntax mit Tags und Attributen hat.
Dies ist eine Menge Code, also zögern Sie nicht, ihn zu kopieren und einzufügen. Ich erkläre das Muster direkt unter dem Snippet:
// blocksToSSML.js import blocksToHTML, { h } from '@sanity/block-content-to-html' const serializers = { marks: { prosody: ({ children, mark: { rate, pitch, volume } }) => h('prosody', { attrs: { rate, pitch, volume } }, children), alias: ({ children, mark: { text } }) => h('sub', { attrs: { alias: text } }, children), sayAs: ({ children, mark: { interpretAs } }) => h('say-as', { attrs: { 'interpret-as': interpretAs } }, children), break: ({ children, mark: { time, strength } }) => h('break', { attrs: { time: '${time}ms', strength } }, children), emphasis: ({ children, mark: { level } }) => h('emphasis', { attrs: { level } }, children) } } export const blocksToSSML = blocks => blocksToHTML({ blocks, serializers })
Dieser Code exportiert eine Funktion, die das Array von Blöcken nimmt und sie durchläuft. Immer wenn ein Block eine mark
enthält, wird nach einem Serialisierer für den Typ gesucht. Wenn Sie einen Text markiert haben, der emphasis
werden soll, verwenden Sie diese Funktion aus dem Serializers-Objekt:
emphasis: ({ children, mark: { level } }) => h('emphasis', { attrs: { level } }, children)
Vielleicht erkennen Sie den Parameter, wo wir das Schema definiert haben? Die h()
Funktion lässt uns ein HTML-Element definieren, das heißt, hier „schummeln“ wir und lässt es ein SSML-Element namens <emphasis>
zurückgeben. Wir geben ihm auch die Attributebene level
wenn diese definiert ist, und platzieren die children
Elemente darin – in den meisten Fällen handelt es sich dabei um den Text, den Sie mit emphasis
gekennzeichnet haben.
{ "_type": "block", "_key": "f2c4cf1ab4e0", "style": "normal", "markDefs": [ { "_type": "emphasis", "_key": "99b28ed3fa58", "level": "strong" } ], "children": [ { "_type": "span", "_key": "f2c4cf1ab4e01", "text": "Say this strongly!", "marks": [ "99b28ed3fa58" ] } ] }
So wird die obige Struktur in Portable Text in diese SSML serialisiert:
<emphasis level="strong">Say this strongly</emphasis>
Wenn Sie mehr SSML-Tags unterstützen möchten, können Sie dem Schema weitere Anmerkungen hinzufügen und die Anmerkungstypen zum marks
in den Serialisierern hinzufügen.
Jetzt haben wir eine Funktion, die SSML-Markup aus unserem markierten Rich-Text zurückgibt. Der letzte Teil besteht darin, eine Schaltfläche zu erstellen, mit der wir dieses Markup an einen Text-zu-Sprache-Dienst senden können.
Hinzufügen einer Vorschau-Schaltfläche, die Sie anspricht
Idealerweise hätten wir die Sprachsynthesefunktionen des Browsers in der Web-API verwenden sollen. Auf diese Weise wären wir mit weniger Code und Abhängigkeiten davongekommen.
Anfang 2019 befindet sich die native Browserunterstützung für die Sprachsynthese jedoch noch in einem frühen Stadium. Es sieht so aus, als ob die Unterstützung für SSML auf dem Weg ist, und es gibt Proof of Concepts für clientseitige JavaScript-Implementierungen dafür.
Die Chancen stehen gut, dass Sie diese Inhalte sowieso mit einem Sprachassistenten verwenden werden. Sowohl Google Assistant als auch Amazon Echo (Alexa) unterstützen SSML als Antworten in einem Fulfillment. In diesem Tutorial verwenden wir die Text-to-Speech-API von Google, die sich ebenfalls gut anhört und mehrere Sprachen unterstützt.
Beginnen Sie damit, einen API-Schlüssel zu erhalten, indem Sie sich bei der Google Cloud Platform anmelden (er ist für die ersten 1 Million Zeichen, die Sie verarbeiten, kostenlos). Sobald Sie sich angemeldet haben, können Sie auf dieser Seite einen neuen API-Schlüssel erstellen.
Jetzt können Sie Ihre PreviewButton.js -Datei öffnen und diesen Code hinzufügen:
// PreviewButton.js import React from 'react' import Button from 'part:@sanity/components/buttons/default' import { blocksToSSML } from './blocksToSSML' // You should be careful with sharing this key // I put it here to keep the code simple const API_KEY = '<yourAPIkey>' const GOOGLE_TEXT_TO_SPEECH_URL = 'https://texttospeech.googleapis.com/v1beta1/text:synthesize?key=' + API_KEY const speak = async blocks => { // Serialize blocks to SSML const ssml = blocksToSSML(blocks) // Prepare the Google Text-to-Speech configuration const body = JSON.stringify({ input: { ssml }, // Select the language code and voice name (AF) voice: { languageCode: 'en-US', name: 'en-US-Wavenet-A' }, // Use MP3 in order to play in browser audioConfig: { audioEncoding: 'MP3' } }) // Send the SSML string to the API const res = await fetch(GOOGLE_TEXT_TO_SPEECH_URL, { method: 'POST', body }).then(res => res.json()) // Play the returned audio with the Browser's Audo API const audio = new Audio('data:audio/wav;base64,' + res.audioContent) audio.play() } export default function PreviewButton (props) { return <Button style={{ marginTop: '1em' }} onClick={() => speak(props.blocks)}>Speak text</Button> }
Ich habe diesen Code für die Vorschau-Schaltfläche auf ein Minimum beschränkt, um die Befolgung dieses Tutorials zu vereinfachen. Natürlich könnten Sie es erweitern, indem Sie einen Status hinzufügen, um anzuzeigen, ob die Vorschau verarbeitet wird, oder es möglich machen, eine Vorschau mit den verschiedenen Stimmen anzuzeigen, die die API von Google unterstützt.
Fügen Sie die Schaltfläche zu SSMLeditor.js
:
// SSMLeditor.js import React, { Fragment } from 'react'; import { BlockEditor } from 'part:@sanity/form-builder'; import PreviewButton from './PreviewButton'; export default function SSMLeditor(props) { return ( <Fragment> <BlockEditor {...props} /> <PreviewButton blocks={props.value} /> </Fragment> ); }
Jetzt sollten Sie in der Lage sein, Ihren Text mit den verschiedenen Anmerkungen zu markieren und das Ergebnis zu hören, wenn Sie auf „Text sprechen“ drücken. Cool, oder?
Sie haben einen Sprachsynthese-Editor erstellt, und was nun?
Wenn Sie diesem Tutorial gefolgt sind, haben Sie erfahren, wie Sie den Editor für Portable Text in Sanity Studio verwenden können, um benutzerdefinierte Anmerkungen zu erstellen und den Editor anzupassen. Sie können diese Fähigkeiten für alle möglichen Dinge verwenden, nicht nur, um einen Sprachsynthese-Editor zu erstellen. Sie haben auch erfahren, wie Sie Portable Text in die von Ihnen benötigte Syntax serialisieren. Dies ist natürlich auch praktisch, wenn Sie Frontends in React oder Vue erstellen. Sie können diese Fähigkeiten sogar nutzen, um Markdown aus Portable Text zu generieren.
Wir haben nicht behandelt, wie Sie dies zusammen mit einem Sprachassistenten tatsächlich verwenden. Wenn Sie es versuchen möchten, können Sie einen Großteil der gleichen Logik wie bei der Vorschauschaltfläche in einer serverlosen Funktion verwenden und sie als API-Endpunkt für eine Erfüllung mithilfe von Webhooks festlegen, z. B. mit Dialogflow.
Wenn Sie möchten, dass ich ein Tutorial zur Verwendung des Sprachsynthese-Editors mit einem Sprachassistenten schreibe, können Sie mir gerne einen Hinweis auf Twitter geben oder im Kommentarbereich unten teilen.
Weiterführende Literatur zu SmashingMag:
- Experimentieren mit Sprachsynthese
- Verbesserung der Benutzererfahrung mit der Web Speech API
- Accessibility APIs: A Key To Web Accessibility
- Erstellen eines einfachen KI-Chatbots mit Web Speech API und Node.js