음성 합성 편집기를 만드는 방법

게시 됨: 2022-03-10
요약 요약 ↬ 음성 비서는 사람들의 집, 손목, 주머니로 이동 중입니다. 즉, 디지털 음성 합성의 도움으로 일부 콘텐츠가 큰 소리로 말해질 것입니다. 이 튜토리얼에서는 Sanity.io의 Portable Text용 편집기를 사용하여 음성 합성을 위한 WYGIWYH(What You Get Is What You Hear) 편집기를 만드는 방법을 배웁니다.

1984년 스티브 잡스가 매킨토시를 발표했을 때 매킨토시는 무대에서 우리에게 “안녕하세요”라고 인사했습니다. 그 당시에도 음성 합성은 실제로 새로운 기술이 아니었습니다. Bell Labs는 이미 30년대 후반에 보코더를 개발했으며 음성 보조 컴퓨터의 개념은 Stanley Kubrick이 보코더를 음성으로 만들었을 때 사람들의 인식을 만들었습니다. 2001년 HAL9000: 스페이스 오디세이 (1968).

2015년 중반에 Apple의 Siri, Amazon Echo 및 Google Assistant가 도입되기 전에는 음성 인터페이스가 실제로 더 넓은 대중의 집, 손목 및 주머니에 침투했습니다. 우리는 아직 채택 단계에 있지만 이러한 음성 도우미는 계속 남아 있을 것 같습니다.

즉, 웹은 더 이상 화면에 표시되는 수동적인 텍스트가 아닙니다 . 웹에디터와 UX디자이너는 소리내어 말해야 할 콘텐츠와 서비스를 만드는 데 익숙해져야 합니다.

우리는 이미 머리 없이 API를 통해 콘텐츠를 처리할 수 있는 콘텐츠 관리 시스템을 사용하는 방향으로 빠르게 움직이고 있습니다. 마지막 부분은 음성에 맞게 콘텐츠를 더 쉽게 맞춤화할 수 있는 편집 인터페이스를 만드는 것입니다. 그럼 그냥 해보자!

점프 후 더! 아래에서 계속 읽기 ↓

SSML이란?

웹 브라우저는 문서를 시각적으로 렌더링하기 위해 W3C의 HTML(HyperText Markup Language) 사양을 사용하는 반면, 대부분의 음성 도우미는 음성을 생성할 때 SSML(Speech Synthesis Markup Language)을 사용합니다.

루트 요소 <speak> , 단락( <p> ) 및 문장( <s> ) 태그를 사용하는 최소한의 예:

 <speak> <p> <s>This is the first sentence of the paragraph.</s> <s>Here's another sentence.</s> </p> </speak>
스니펫을 들으려면 재생을 누르세요.

SSML이 존재하는 곳은 <emphasis><prosody> (pitch)에 대한 태그를 도입할 때입니다.

 <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에는 더 많은 기능이 있지만 이 정도면 기본 사항을 이해하기에 충분합니다. 이제 음성 합성 편집 인터페이스를 만드는 데 사용할 편집기를 자세히 살펴보겠습니다.

휴대용 텍스트 편집기

이 편집기를 만들기 위해 Sanity.io에 있는 Portable Text용 편집기를 사용할 것입니다. 이식 가능한 텍스트는 SSML과 같은 모든 마크업 언어로 직렬화할 수 있는 서식 있는 텍스트 편집을 위한 JSON 사양입니다. 즉, 다른 마크업 언어를 사용하여 여러 위치에서 동일한 텍스트 스니펫을 쉽게 사용할 수 있습니다.

Sanity.io의 Portable Text용 기본 편집기
Sanity.io의 Portable Text용 기본 편집기(큰 미리보기)

Sanity 설치

Sanity.io는 React.js로 구축된 오픈 소스 편집 환경과 함께 제공되는 구조화된 콘텐츠용 플랫폼입니다. 모든 것을 시작하고 실행하는 데 2분이 걸립니다.

터미널에 npm i -g @sanity/cli && sanity init 를 입력하고 지침을 따릅니다. 프로젝트 템플릿을 묻는 메시지가 나타나면 "비어 있음"을 선택합니다.

이 튜토리얼을 따르고 이 편집기를 처음부터 만들고 싶지 않다면 이 튜토리얼의 코드를 복제하고 README.md 의 지침을 따를 수도 있습니다.

편집기가 다운로드되면 프로젝트 폴더에서 sanity start 를 실행하여 시작합니다. 파일을 편집할 때 변경 사항을 업데이트하기 위해 Hot Module Reloading을 사용하는 개발 서버를 시작합니다.

Sanity Studio에서 스키마를 구성하는 방법

편집기 파일 만들기

/schemas 폴더에 ssml-editor 라는 폴더를 만드는 것으로 시작하겠습니다. 해당 폴더에 몇 가지 빈 파일을 넣습니다.

 /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

이제 이 파일에 콘텐츠 스키마를 추가할 수 있습니다. 콘텐츠 스키마 는 서식 있는 텍스트의 데이터 구조를 정의하고 Sanity Studio에서 편집 인터페이스를 생성하는 데 사용합니다. 그것들은 대부분 nametype 만 필요한 간단한 JavaScript 객체입니다.

titledescription 을 추가하여 편집자에게 좀 더 보기 좋게 만들 수도 있습니다. 예를 들어 다음은 title 에 대한 간단한 텍스트 필드에 대한 스키마입니다.

 export default { name: 'title', type: 'string', title: 'Title', description: 'Titles should be short and descriptive' } 
제목 필드와 휴대용 텍스트 편집기가 있는 Sanity Studio
제목 필드와 기본 편집기가 있는 스튜디오(큰 미리보기)

Portable Text는 서식 있는 텍스트를 데이터로 사용한다는 아이디어를 기반으로 합니다. 이것은 서식 있는 텍스트를 쿼리하고 원하는 거의 모든 마크업으로 변환할 수 있기 때문에 강력합니다.

"단락"이라고 생각할 수 있는 "블록"이라는 객체의 배열입니다. 블록에는 자식 범위의 배열이 있습니다. 각 블록은 하위 범위에 분산된 데이터 구조를 설명하는 스타일과 일련의 마크 정의를 가질 수 있습니다.

Sanity.io는 Portable Text를 읽고 쓸 수 있는 편집기와 함께 제공되며 다음과 같이 array 필드 안에 block 유형을 배치하여 활성화됩니다.

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

배열은 여러 유형이 될 수 있습니다. SSML 편집기의 경우 오디오 파일에 대한 블록이 될 수 있지만 이는 이 자습서의 범위를 벗어납니다.

마지막으로 이 편집기를 사용할 수 있는 콘텐츠 유형을 추가하고 싶습니다. 대부분의 어시스턴트는 "의도" 및 "이행"의 간단한 콘텐츠 모델을 사용합니다.

  • 의도
    일반적으로 AI 모델에서 사용자가 수행하려는 작업을 설명하는 데 사용하는 문자열 목록입니다.
  • 이행
    이것은 "의도"가 식별될 때 발생합니다. 이행은 종종 - 또는 적어도 - 일종의 응답과 함께 제공됩니다.

그럼 음성 합성 편집기를 사용하는 fulfillment 라는 간단한 콘텐츠 유형을 만들어 보겠습니다. fulfillment.js 라는 새 파일을 만들고 /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' } ] }

파일을 저장하고 schema.js 를 엽니다. 다음과 같이 스튜디오에 추가합니다.

 // 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, ]) })

이제 프로젝트의 루트 폴더 내 명령줄 인터페이스에서 sanity start 을 실행하면 스튜디오가 로컬로 시작되고 이행 항목을 추가할 수 있습니다. 파일을 저장할 때 새로운 변경 사항이 자동으로 다시 로드되므로 계속 진행하는 동안 스튜디오를 계속 실행할 수 있습니다.

편집기에 SSML 추가

기본적으로 block 유형은 제목 스타일, 강조 및 강조 표시를 위한 데코레이터 스타일, 링크 및 목록에 대한 주석이 있는 시각적 지향 서식 ​​있는 텍스트를 위한 표준 편집기를 제공합니다. 이제 SSML에 있는 청각적 개념으로 이를 재정의하려고 합니다.

우리는 annotations 에 대한 구성으로 SSMLeditorSchema.jsblock 에 추가할 편집자를 위한 유용한 설명과 함께 다양한 콘텐츠 구조를 정의하는 것으로 시작합니다. '강조', '별칭', '운율', '말하기'가 바로 그것입니다.

중요성

표시된 텍스트에 얼마나 많은 가중치를 적용할지 제어하는 ​​"강조"로 시작합니다. 사용자가 선택할 수 있는 미리 정의된 값 목록이 있는 문자열로 정의합니다.

 // 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' } ] } } ] }

별명

때로 글로 쓰는 것과 말하는 것이 다른 경우가 있습니다. 예를 들어, 서면 텍스트에서 구의 약어를 사용하고 싶지만 전체 구를 소리 내어 읽게 하려고 합니다. 예를 들어:

 <s>This is a <sub alias="Speech Synthesis Markup Language">SSML</sub> tutorial</s>
스니펫을 들으려면 재생을 누르세요.

별칭의 입력 필드는 간단한 문자열입니다.

 // 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', } ] }

작시법

prosody 속성을 사용하면 음높이, 속도 및 볼륨과 같이 텍스트가 어떻게 말해야 하는지 다양한 측면을 제어할 수 있습니다. 이에 대한 마크업은 다음과 같을 수 있습니다.

 <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>
스니펫을 들으려면 재생을 누르세요.

이 입력에는 사전 정의된 문자열 옵션이 있는 세 개의 필드가 있습니다.

 // 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' } ] } } ] }

라고 말하다

마지막으로 포함하고 싶은 것은 <say-as> 입니다. 이 태그를 사용하면 특정 정보가 발음되는 방식을 좀 더 제어할 수 있습니다. 음성 인터페이스에서 무언가를 수정해야 하는 경우 이를 사용하여 단어를 울릴 수도 있습니다. @!%& 유용합니다!

 <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' } ] } ] }

이제 이를 annotations.js 파일로 가져올 수 있어 작업이 좀 더 깔끔해집니다.

 // 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'

이제 이러한 주석 유형을 기본 스키마로 가져올 수 있습니다.

 // 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 ]) })

마지막으로 다음과 같이 편집기에 추가할 수 있습니다.

 // 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'} ] } } ] }

stylesdecorators 에도 빈 배열을 추가했습니다. 이것은 이 특정한 경우에 그다지 의미가 없기 때문에 기본 스타일과 데코레이터(굵게 및 강조와 같은)를 비활성화합니다.

모양과 느낌 사용자 정의

이제 기능이 제 위치에 있지만 아이콘을 지정하지 않았으므로 각 주석은 기본 아이콘을 사용하므로 작성자가 실제로 편집기를 사용하기 어렵습니다. 그래서 그것을 수정하자!

Portable Text용 편집기를 사용하면 아이콘과 표시된 텍스트를 렌더링하는 방법 모두에 대해 React 구성 요소를 주입할 수 있습니다. 여기에서는 일부 이모티콘이 우리를 위해 일하게 할 것이지만, 분명히 이것으로 멀리 갈 수 있어 동적 등으로 만들 수 있습니다. prosody 의 경우 선택한 볼륨에 따라 아이콘도 변경됩니다. 간결함을 위해 이 스니펫에서 필드를 생략했습니다. 로컬 파일에서 필드를 제거하면 됩니다.

 // 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>, }, }; 
맞춤형 SSML 편집기
사용자 지정 SSML 표시가 있는 편집기(큰 미리보기)

이제 음성 어시스턴트가 사용할 수 있는 텍스트 편집용 편집기가 생겼습니다. 그러나 편집자가 텍스트가 실제로 어떻게 들릴지 미리 볼 수 있다면 꽤 유용하지 않을까요?

Google의 TTS(텍스트 음성 변환)를 사용하여 미리보기 버튼 추가

네이티브 음성 합성 지원은 실제로 브라우저에서 진행 중입니다. 그러나 이 자습서에서는 SSML을 지원하는 Google의 Text-to-Speech API를 사용합니다. 이 미리 보기 기능을 구축하면 이 기능을 사용하려는 서비스에서 Portable Text를 SSML로 직렬화하는 방법도 보여줍니다.

React 컴포넌트에서 에디터 래핑하기

먼저 SSMLeditor.js 파일을 열고 다음 코드를 추가합니다.

 // SSMLeditor.js import React, { Fragment } from 'react'; import { BlockEditor } from 'part:@sanity/form-builder'; export default function SSMLeditor(props) { return ( <Fragment> <BlockEditor {...props} /> </Fragment> ); }

이제 편집기를 자체 React 구성 요소에 래핑했습니다. 포함된 데이터를 포함하여 필요한 모든 소품은 실시간으로 전달됩니다. 이 구성 요소를 실제로 사용하려면 speech.js 파일로 가져와야 합니다.

 // 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' }, ], }, }, ], }

이것을 저장하고 스튜디오를 다시 로드하면 거의 똑같이 보일 것입니다. 하지만 이는 아직 편집기 조정을 시작하지 않았기 때문입니다.

휴대용 텍스트를 SSML로 변환

편집기는 서식 있는 텍스트를 원하는 형식으로 쉽게 변환할 수 있도록 하는 JSON의 개체 배열인 이식 가능한 텍스트로 콘텐츠를 저장합니다. 이식 가능한 텍스트를 다른 구문이나 형식으로 변환하는 것을 "직렬화"라고 합니다. 따라서 "직렬 변환기"는 서식 있는 텍스트를 변환하는 방법에 대한 레시피입니다. 이 섹션에서는 음성 합성을 위한 직렬 변환기를 추가합니다.

이미 blocksToSSML.js 파일을 만들었습니다. 이제 첫 번째 종속성을 추가해야 합니다. ssml-editor 폴더 내에서 터미널 명령 npm init -y 를 실행하여 시작합니다. 그러면 편집기의 종속성이 나열될 package.json 이 추가됩니다.

완료되면 npm install @sanity/block-content-to-html 을 실행하여 Portable Text를 직렬화하기 쉽게 해주는 라이브러리를 얻을 수 있습니다. SSML에는 태그와 속성이 있는 동일한 XML 구문이 있기 때문에 HTML 라이브러리를 사용하고 있습니다.

이것은 코드의 무리이므로 자유롭게 복사하여 붙여넣으십시오. 스니펫 바로 아래에서 패턴을 설명하겠습니다.

 // 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 })

이 코드는 블록 배열을 가져오고 이를 반복하는 함수를 내보냅니다. 블록에 mark 가 포함될 때마다 해당 유형의 직렬 변환기를 찾습니다. 일부 텍스트를 emphasis 표시한 경우 직렬 변환기 개체에서 다음 기능을 수행합니다.

 emphasis: ({ children, mark: { level } }) => h('emphasis', { attrs: { level } }, children)

스키마를 정의한 매개변수를 알고 있습니까? h() 함수를 사용하면 HTML 요소를 정의할 수 있습니다. 즉, 여기서 "속임수"를 사용하여 <emphasis> 라는 SSML 요소를 반환합니다. 또한 정의된 경우 속성 level 을 부여하고 그 안에 children 요소를 배치합니다. 대부분의 경우 emphasis 표시한 텍스트가 됩니다.

 { "_type": "block", "_key": "f2c4cf1ab4e0", "style": "normal", "markDefs": [ { "_type": "emphasis", "_key": "99b28ed3fa58", "level": "strong" } ], "children": [ { "_type": "span", "_key": "f2c4cf1ab4e01", "text": "Say this strongly!", "marks": [ "99b28ed3fa58" ] } ] }

이것이 Portable Text의 위 구조가 이 SSML로 직렬화되는 방식입니다.

 <emphasis level="strong">Say this strongly</emphasis>

더 많은 SSML 태그에 대한 지원을 원하는 경우 스키마에 더 많은 주석을 추가하고 직렬 변환기의 marks 섹션에 주석 유형을 추가할 수 있습니다.

이제 마크업된 서식 있는 텍스트에서 SSML 마크업을 반환하는 함수가 있습니다. 마지막 부분은 이 마크업을 텍스트 음성 변환 서비스로 보낼 수 있는 버튼을 만드는 것입니다.

당신에게 다시 말하는 미리보기 버튼 추가

이상적으로는 Web API에서 브라우저의 음성 합성 기능을 사용해야 합니다. 그렇게 하면 코드와 종속성을 줄일 수 있습니다.

그러나 2019년 초 현재 음성 합성을 위한 기본 브라우저 지원은 아직 초기 단계입니다. SSML에 대한 지원이 진행 중인 것으로 보이며 이에 대한 클라이언트 측 JavaScript 구현의 개념에 대한 증거가 있습니다.

어쨌든 음성 도우미와 함께 이 콘텐츠를 사용할 가능성이 있습니다. Google Assistant와 Amazon Echo(Alexa)는 모두 이행의 응답으로 SSML을 지원합니다. 이 자습서에서는 소리도 좋고 여러 언어를 지원하는 Google의 텍스트 음성 변환 API를 사용합니다.

Google Cloud Platform에 가입하여 API 키를 얻는 것부터 시작하세요(처음 처리하는 100만 자는 무료입니다). 가입이 완료되면 이 페이지에서 새 API 키를 만들 수 있습니다.

이제 PreviewButton.js 파일을 열고 다음 코드를 추가할 수 있습니다.

 // 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> }

이 튜토리얼을 쉽게 따라갈 수 있도록 이 미리보기 버튼 코드를 최소한으로 유지했습니다. 물론 미리보기가 처리 중인지 표시하는 상태를 추가하거나 Google API가 지원하는 다양한 음성으로 미리 볼 수 있도록 하여 빌드할 수 있습니다.

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> ); }

이제 다른 주석으로 텍스트를 표시할 수 있어야 하며 "텍스트 말하기"를 누를 때 결과를 들을 수 있습니다. 멋지지 않나요?

음성 합성 편집기를 만들었습니다. 이제 무엇을 하시겠습니까?

이 튜토리얼을 따랐다면 Sanity Studio에서 Portable Text용 편집기를 사용하여 사용자 정의 주석을 만들고 편집기를 사용자 정의하는 방법을 배웠습니다. 음성 합성 편집기를 만드는 것뿐만 아니라 모든 종류의 작업에 이러한 기술을 사용할 수 있습니다. 또한 이식 가능한 텍스트를 필요한 구문으로 직렬화하는 방법을 살펴보았습니다. 분명히 이것은 React 또는 Vue에서 프론트엔드를 구축하는 경우에도 유용합니다. 이러한 기술을 사용하여 Portable Text에서 Markdown을 생성할 수도 있습니다.

음성 도우미와 함께 이것을 실제로 사용하는 방법은 다루지 않았습니다. 시도하려는 경우 서버리스 기능의 미리보기 버튼과 동일한 로직을 많이 사용하고 이를 Dialogflow와 같은 웹훅을 사용하여 이행을 위한 API 엔드포인트로 설정할 수 있습니다.

음성 어시스턴트와 함께 음성 합성 편집기를 사용하는 방법에 대한 자습서를 작성하려면 Twitter에서 힌트를 제공하거나 아래 댓글 섹션에서 공유해 주세요.

SmashingMag에 대한 추가 정보:

  • SpeechSynthesis 실험하기
  • Web Speech API로 사용자 경험 향상
  • 접근성 API: 웹 접근성의 핵심
  • Web Speech API와 Node.js로 간단한 AI 챗봇 만들기