SpeechRecognition

Reactive wrapper around the Speech Recognition API. Convert speech to text with Angular signals.

Loading demo...

Usage

angular-ts
import { Component, linkedSignal } from '@angular/core';
import { speechRecognition } from '@signality/core';

@Component({
  template: `
    <button (click)="toggleListening()">
      {{ recognition.isListening() ? 'Stop' : 'Start' }} Listening
    </button>
    <input [(ngModel)]="searchQuery" />
  `,
})
export class VoiceSearch {
  readonly recognition = speechRecognition({ continuous: true }); 
  readonly searchQuery = linkedSignal(() => this.recognition.text());
  
  toggleListening() {
    if (this.recognition.isListening()) {
      this.recognition.stop();
    } else {
      this.recognition.start();
    }
  }
}

Parameters

ParameterTypeDescription
optionsSpeechRecognitionOptionsOptional configuration (see Options below)

Options

OptionTypeDefaultDescription
langMaybeSignal<string>'en-US'Language for speech recognition
interimResultsbooleanfalseWhether to return interim results
continuousbooleanfalseWhether to continue recognition after speech ends
maxAlternativesnumber1Maximum number of alternative transcripts
injectorInjector-Optional injector for DI context

Return Value

The speechRecognition() function returns a SpeechRecognitionRef:

PropertyTypeDescription
isSupportedSignal<boolean>Whether Speech Recognition API is supported
isListeningSignal<boolean>Whether recognition is currently active
textSignal<string>Final transcript text
interimTextSignal<string>Interim transcript text
errorSignal<SpeechRecognitionErrorEvent | Error | null>Error object if recognition failed
start() => voidStart speech recognition
stop() => voidStop speech recognition
abort() => voidAbort speech recognition

Examples

Real-time transcription

angular-ts
import { Component } from '@angular/core';
import { speechRecognition } from '@signality/core';

@Component({
  template: `
    <div class="transcription">
      <p class="final">{{ recognition.text() }}</p>
      @if (recognition.interimText()) {
        <p class="interim">{{ recognition.interimText() }}</p>
      }
    </div>
  `,
})
export class Transcription {
  readonly recognition = speechRecognition({
    interimResults: true,
    continuous: true,
  });
  
  constructor() {
    this.recognition.start();
  }
}

Error handling

angular-ts
import { Component } from '@angular/core';
import { speechRecognition } from '@signality/core';

@Component({
  template: `
    @if (recognition.error()) {
      <div class="error">{{ recognition.error()?.message }}</div>
    }
    <button (click)="recognition.start()">Try Again</button>
  `,
})
export class ErrorHandling {
  readonly recognition = speechRecognition();
}

Browser Compatibility

The Speech Recognition API has limited browser support. Always check isSupported() before using speech recognition (see Browser API support detection):

angular-html
@if (recognition.isSupported()) {
  <button (click)="recognition.start()">Start Listening</button>
} @else {
  <p>Speech recognition is not available in this browser</p>
}

For detailed browser support information, see Can I use: Speech Recognition API.

SSR Compatibility

On the server, signals initialize with safe defaults:

  • isSupportedfalse
  • isListeningfalse
  • text''
  • interimText''
  • errornull
  • start, stop, abort → no-op functions

Type Definitions

typescript
interface SpeechRecognitionOptions extends WithInjector {
  readonly lang?: MaybeSignal<string>;
  readonly interimResults?: boolean;
  readonly continuous?: boolean;
  readonly maxAlternatives?: number;
}

interface SpeechRecognitionRef {
  readonly isSupported: Signal<boolean>;
  readonly isListening: Signal<boolean>;
  readonly text: Signal<string>;
  readonly interimText: Signal<string>;
  readonly error: Signal<SpeechRecognitionErrorEvent | Error | null>;
  readonly start: () => void;
  readonly stop: () => void;
  readonly abort: () => void;
}

function speechRecognition(options?: SpeechRecognitionOptions): SpeechRecognitionRef;
Edit this page on GitHub Last updated: Mar 19, 2026, 23:28:23