React SpeechToText - Getting Started

jQuery
NOTE
Before you start the tutorial, ensure DevExtreme is installed in your application.
Angular
NOTE
Before you start the tutorial, ensure DevExtreme is installed in your application.
Vue
NOTE
Before you start the tutorial, ensure DevExtreme is installed in your application.
React
NOTE
Before you start the tutorial, ensure DevExtreme is installed in your application.

This tutorial guides you through the following steps:

  • Add a SpeechToText to a page.
  • Integrate SpeechToText with a text editor (TextArea).
  • Handle transcription errors.
  • Customize SpeechRecognition options.

Each section in this tutorial covers a single configuration step. You can find the complete source code in the following GitHub repository:

View on GitHub

Create SpeechToText

jQuery

Add DevExtreme to your jQuery application and use the following code to create a SpeechToText:

index.js
index.html
$(function() {
    $("#speech-to-text").dxSpeechToText({});
});
<html>
    <head>
        <!-- ... -->
        <script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
        <link rel="stylesheet" href="https://unpkg.com/devextreme@25.2-next/dist/css/dx.fluent.blue.light.css">
        <script type="text/javascript" src="https://unpkg.com/devextreme@25.2-next/dist/js/dx.all.js"></script>
        <script type="text/javascript" src="index.js"></script>
    </head>
    <body>
        <div id="speech-to-text"></div>
    </body>
</html>
Angular

Add DevExtreme to your Angular application and use the following code to create a SpeechToText:

app.component.html
app.component.ts
app.module.ts
angular.json
<dx-speech-to-text></dx-speech-to-text>
import { Component } from '@angular/core';
import { type DxSpeechToTextTypes } from 'devextreme-angular/ui/speech-to-text';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { DxSpeechToTextModule } from 'devextreme-angular';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        AppRoutingModule,
        DxSpeechToTextModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }
{
    // ...
    "styles": [
        "node_modules/devextreme/dist/css/dx.fluent.blue.light.css",
    ],
}
Vue

Add DevExtreme to your Vue application and use the following code to create a SpeechToText:

App.vue
<template>
    <DxSpeechToText />
</template>

<script setup lang="ts">
import { DxSpeechToText, type DxSpeechToTextTypes } from 'devextreme-vue/speech-to-text';
import 'devextreme/dist/css/dx.fluent.blue.light.css';

</script>
React

Add DevExtreme to your React application and use the following code to create a SpeechToText:

App.tsx
import React, { JSX, useState } from 'react';
import { SpeechToText, type SpeechToTextTypes } from 'devextreme-react/speech-to-text';
import 'devextreme/dist/css/dx.fluent.blue.light.css';

export default function App(): JSX.Element {
    return (
        <SpeechToText />
    );
}

Integrate with a Text Editor

SpeechToText returns transcription results in the onResult handler. Final transcriptions are nested within the onResult parameter (a ResultEvent object). To access final transcriptions, implement the following code:

onResult(e) {
    const resultText = Object.values(e.event.results)
        .map((resultItem) => resultItem[0].transcript)
        .join(' ');
},

To integrate the component with a text input (for instance, DevExtreme TextArea), update the input's value in onResult:

jQuery
index.js
$(function() {
    const textArea = $('#textarea-container').dxTextArea({
        placeholder: 'Transcribed text will appear here...',
    }).dxTextArea('instance');

    $("#speech-to-text").dxSpeechToText({
        onResult(e) {
            const resultText = Object.values(e.event.results)
                .map((resultItem) => resultItem[0].transcript)
                .join(' ');

            textArea.option('value', resultText);
        },
    });
});
Angular
app.component.html
app.component.ts
<dx-speech-to-text
    (onResult)="handleResult($event)"
></dx-speech-to-text>
<dx-text-area
    placeholder="Transcribed text will appear here..."
    [(value)]="textAreaValue"
></dx-text-area>
import { Component } from '@angular/core';
import { type DxSpeechToTextTypes } from 'devextreme-angular/ui/speech-to-text';

// ...
export class AppComponent {
    textAreaValue = '';

    handleResult(e: SpeechToTextTypes.ResultEvent): void {
        const resultText = Object.values(e.event.results)
            .map((resultItem: unknown) => (resultItem as SpeechRecognitionResult)[0].transcript)
            .join(' ');

        this.textAreaValue = resultText;
    }
}
Vue
App.vue
<template>
    <DxSpeechToText
        @result="handleResult"
    />
    <DxTextArea
        placeholder="Transcribed text will appear here..."
        v-model:value="textAreaValue"
    />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { DxSpeechToText, type DxSpeechToTextTypes } from 'devextreme-vue/speech-to-text';
import 'devextreme/dist/css/dx.fluent.blue.light.css';

const textAreaValue = ref<string>('');

function handleResult(e: DxSpeechToTextTypes.ResultEvent): void {
    const resultText = Object.values(e.event.results)
        .map((resultItem: unknown) => (resultItem as SpeechRecognitionResult)[0].transcript)
        .join(' ');

    textAreaValue.value = resultText;
}

</script>
React
App.tsx
import React, { JSX, useCallback, useState } from 'react';
import { SpeechToText, type SpeechToTextTypes } from 'devextreme-react/speech-to-text';
import 'devextreme/dist/css/dx.fluent.blue.light.css';

const [textAreaValue, setTextAreaValue] = useState<string>('');

const handleResult = useCallback((e: SpeechToTextTypes.ResultEvent): void => {
    const resultText = Object.values(e.event.results)
        .map((result: unknown) => (result as SpeechRecognitionResult)[0].transcript)
        .join('');

    setTextAreaValue(resultText);
}, []);

function App(): JSX.Element {
    return (
        <div className="demo-container">
            <SpeechToText
                onResult={handleResult}
            />
            <TextArea
                placeholder="Transcribed text will appear here..."
                value={textAreaValue}
            />
        </div>
    );
}

Handle Errors

SpeechToText returns Web Speech API errors in the onError handler. Error codes are nested within the onError parameter (an ErrorEvent object). To display these errors to users, you can implement the notify utility method:

jQuery
onError(e) {
    DevExpress.ui.notify(e.event.error);
}
Angular
import notify from 'devextreme/ui/notify';

onError(e) {
    notify(e.event.error);
}
Vue
import notify from 'devextreme/ui/notify';

onError(e) {
    notify(e.event.error);
}
React
import notify from 'devextreme/ui/notify';

onError(e) {
    notify(e.event.error);
}

This example implements an if statement to display a unique message for not-allowed errors (thrown when users deny microphone permissions) and a common message for other errors:

jQuery
index.js
$(function() {
    // ...

    $("#speech-to-text").dxSpeechToText({
        onError(e) {
            if (e.event.error === 'not-allowed') {
                DevExpress.ui.notify('Microphone access denied. Please grant microphone permissions and try again.', 'error', 5000);
            } else {
                DevExpress.ui.notify(`An error occurred during speech recognition: ${e.event.error}`, 'error', 5000);
            }
        },
    });
});
Angular
app.component.html
app.component.ts
<dx-speech-to-text ...
    (onError)="handleError($event)"
></dx-speech-to-text>
<!-- ... -->
import { Component } from '@angular/core';
import { type DxSpeechToTextTypes } from 'devextreme-angular/ui/speech-to-text';
import notify from 'devextreme/ui/notify';

// ...
export class AppComponent {
    handleError(e: SpeechToTextTypes.ErrorEvent): void {
        if (e.event.error === 'not-allowed') {
            notify('Microphone access denied. Please grant microphone permissions and try again.', 'error', 5000);
        } else {
            notify(`An error occurred during speech recognition: ${e.event.error}`, 'error', 5000);
        }
    }
}
Vue
App.vue
<template>
    <DxSpeechToText ...
        @error="handleError"
    />
    <!-- ... -->
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { DxSpeechToText, type DxSpeechToTextTypes } from 'devextreme-vue/speech-to-text';
import 'devextreme/dist/css/dx.fluent.blue.light.css';
import notify from 'devextreme/ui/notify';

// ...
function handleError(e: DxSpeechToTextTypes.ErrorEvent): void {
    if (e.event.error === 'not-allowed') {
        notify('Microphone access denied. Please grant microphone permissions and try again.', 'error', 5000);
    } else {
        notify(`An error occurred during speech recognition: ${e.event.error}`, 'error', 5000);
    }
}

</script>
React
App.tsx
import React, { JSX, useCallback, useState } from 'react';
import { SpeechToText, type SpeechToTextTypes } from 'devextreme-react/speech-to-text';
import 'devextreme/dist/css/dx.fluent.blue.light.css';
import notify from 'devextreme/ui/notify';

// ...
const handleError = useCallback((e: SpeechToTextTypes.ErrorEvent): void => {
    if (e.event.error === 'not-allowed') {
        notify('Microphone access denied. Please grant microphone permissions and try again.', 'error', 5000);
    } else {
        notify(`An error occurred during speech recognition: ${e.event.error}`, 'error', 5000);
    }
}, []);

function App(): JSX.Element {
    return (
        <div className="demo-container">
            <SpeechToText ...
                onError={handleError}
            />
            <!-- ... -->
        </div>
    );
}

Configure SpeechRecognition Options

To configure SpeechRecognition options, define the speechRecognitionConfig object. This example enables continuous recognition (transcription continues after speech ends):

jQuery
index.js
$(function() {
    // ...

    $("#speech-to-text").dxSpeechToText({
        speechRecognitionConfig: {
            continuous: true,
        },
    });
});
Angular
app.component.html
app.component.ts
<dx-speech-to-text ...
    [speechRecognitionConfig]="speechRecognitionConfig"
></dx-speech-to-text>
<!-- ... -->
import { Component } from '@angular/core';
import { type DxSpeechToTextTypes } from 'devextreme-angular/ui/speech-to-text';
import notify from 'devextreme/ui/notify';

// ...
export class AppComponent {
    speechRecognitionConfig = { continuous: true };
}
Vue
App.vue
<template>
    <DxSpeechToText ...
        :speech-recognition-config="speechRecognitionConfig"
    />
    <!-- ... -->
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { DxSpeechToText, type DxSpeechToTextTypes } from 'devextreme-vue/speech-to-text';
import 'devextreme/dist/css/dx.fluent.blue.light.css';
import notify from 'devextreme/ui/notify';

// ...
const speechRecognitionConfig = { continuous: true };

</script>
React
App.tsx
import React, { JSX, useCallback, useState } from 'react';
import { SpeechToText, type SpeechToTextTypes } from 'devextreme-react/speech-to-text';
import 'devextreme/dist/css/dx.fluent.blue.light.css';
import notify from 'devextreme/ui/notify';

// ...
const speechRecognitionConfig = { continuous: true };

function App(): JSX.Element {
    return (
        <div className="demo-container">
            <SpeechToText ...
                speechRecognitionConfig={speechRecognitionConfig}
            />
            <!-- ... -->
        </div>
    );
}