vue-transcribe

1.2.2 • Public • Published

vue-transcribe

A lightweight Vue 2 & Vue 3 compatible component + service bundle for adding a real-time speech-to-text transcription and voice command execution using WebSocket-based services like Amazon Transcribe.

You can:

  • Use a drop-in <VoiceButton /> for command-style or text-generation mic capture
  • Control everything via a lightweight API

This package offers a robust solution for speech-to-text functionality with two key benefits:

  • No Data Storage: We don't collect, store, or process any user data. You're responsible for managing/generating your AWS Transcribe's presigned URLs and ensuring data security.
  • Efficient Audio Processing: Our package utilizes Audio Worklet, offloading audio processing to a new thread and keeping your main thread free from blocking operations. This ensures a seamless and efficient experience for your users.

📦 Installation

npm install vue-transcribe

⚠️ Requirements

This package requires material design icons to function properly. It is expected that you have this setup in the consuming project. If you don't have it setup yet, do the following:

1. Install @mdi/font:

npm install @mdi/font

2. Import the css as a global style. (typically within main.js):

import '@mdi/font/css/materialdesignicons.css';

// or

import '@mdi/font/css/materialdesignicons.min.css';

🔧 Setup

Step 1 – Provide the Presigned URL

You must generate and provide a presigned WebSocket URL to start any transcription. Example (using AWS Transcribe):

import { TranscribeAPI } from 'vue-transcribe';
import axios from 'axios';

async function configure() {
  const { data } = await axios.get('/api/transcribe-url'); // Replace with the presignedURL generation endpoint in your setup
  TranscribeAPI.setURL(data.url);
  TranscribeAPI.setConfigured(true); // ✅ Don't forget this
}

// AWS Transcribe presigned URLs expire every 5 minutes
configure();
setInterval(configure, 5 * 60 * 1000);

⚠️ setConfigured(true) is required to indicate that a valid transcription URL is available. Without this, the component will not render. This can be used to filter envs as well. e.g TranscribeAPI.setConfigured(process.env.NODE_ENV !== 'development')


Step 2 - Use <VoiceButton /> Component

This button provides a quick way to interact with the API, and can be used in 2 modes - generate and command

Text Generation Mode

If there is an input/textrea HTMLElement you wish to populate with texts when you speak, the <VoiceButton /> component relies on an enclosing parent HTMLElement to be able to find the input element of interest. With that, you should have the input or textarea of interest, together with the <VoiceButton />, enclosed within any parent HTMLElement. The order and styling is up to you:

<template>
  <div class="input-voice-container">
    <textarea class="input"></textarea>

    <VoiceButton
      :max-recording-time="10000"
      :disabled="isDisabled"
      mode="generate"
      language-code="en-US"
      theme="primary-transparent"
      microphone="solid"
    />
  </div>
</template>

<script>
import { VoiceButton } from 'vue-transcribe';

export default {
  components: {
    VoiceButton
  },

  data() {
    return {
      isDisabled: false
    }
  }
};
</script>

You can also grab the transcript and use it elsewhere without having to work with input fields. For this, use @partial for real time transcript and/or @final for final transcript (emitted when the session ends):

<template>
  <VoiceButton
    :max-recording-time="10000"
    mode="generate"
    microphone="solid"
    @partial="showTranscription($event)"
    @final="sendMessage($event)"
  />
</template>
<script>
import { VoiceButton } from 'vue-transcribe';

export default {
  components: {
    VoiceButton
  },

  methods: {
    showTranscription(transcript) {
      console.log(transcript);
    },

    sendMessage(transcript) {
      console.log(transcript);
    }
  }
};
</script>

Command Mode

In command mode, your app can execute tasks based on matched phrases. You have to setup the command mapping first of all:

TranscribeAPI.setCommandMap([
  {
    command: 'clear input',
    task: () => {
      const el = document.querySelector('input');
      if (el) el.value = '';
    }
  },
  {
    command: 'submit form',
    task: () => {
      document.querySelector('form')?.submit();
    }
  },
  {
    command: 'shut down app',
    task: () => {
      this.application.shutdown(); // assumption
    }
  }
]);

Once the command mapping is configured, use the component in your templates like so:

<template>
  <VoiceButton
    :disabled="isDisabled"
    :max-recording-time="3000"
    :threshold="0.7"
    mode="command"
    language-code="en-US"
    theme="primary"
    microphone="solid"
  />
</template>

<script>
import { VoiceButton } from 'vue-transcribe';

export default {
  components: {
    VoiceButton
  },

  data() {
    return {
      isDisabled: false
    }
  }
};
</script>

VoiceButton Props

Prop Type Required Description
mode string Transcription mode - text-generation or custom commands. generate / command.
language-code string BCP-47 language code (default en-US).
max-recording-time number Max mic capture time in ms (default: 5000).
microphone string Microphone's style (solid or outline). default solid.
disabled boolean If button should be disabled. default false.
theme string Predefined themes that can be applied - primary (default), secondary, danger and bland. Append -transparent to any of the first three themes to get a button with transparent background. bland has a transparent button by design.
expanded boolean To show or hide label. default is false.
append boolean Whether to replace or append to existing text input. For generate mode. Will only work if <VoiceButton /> and input element are enclosed together.
trim-punctuation boolean Whether to remove trailing punctuations from transcript.
threshold number Command matching threshold using Fuse.js. Defaults to 0.6. The lower the threshold, the stricter the matching. It accepts values between 0 and 1 inclusive. For command mode.

VoiceButton Events

Event Name Payload Required Description
@partial string Emitted when a transcript is generating in real time
@final string Emitted when a transcription session ends.


TranscribeAPI

Method Description
setURL(url: string) Sets the active transcription WebSocket URL
setConfigured(boolean) Enables/disables voice capture
isConfigured() Returns current config state
setCommandMap(array) Registers global voice commands
on(event, callback) Subscribe to 'error' event
off(event, callback) Unsubscribe from events

Stylable Classes

Classes (top to bottom) Location
vue-transcribe-command-container This is on the top-most div enclosing all other elements
vue-transcribe-command-button This is on the button element
vue-transcribe-loading-circle This is on the revolving div
vue-transcribe-listening-animation This is on the listening animation

Example: Handling Errors

TranscribeAPI.on('error', (error) => {
  console.error('Transcribe error:', error);
});


// Error event structure
{
  code: ErrorCodes,
  message: String,
  details?: ErrorEvent
}

// enum ErrorCodes {
//     WS_CONNECTION_FAILED: 'WS_CONNECTION_FAILED',
//     AUDIO_CAPTURE_ERROR: 'AUDIO_CAPTURE_ERROR',
//     NO_MATCHING_COMMAND: 'NO_MATCHING_COMMAND'
// };


// To unsubscribe
TranscribeAPI.off('error', callback);

Example Setup (Vue 2)

import Vue from 'vue';
import {
  VoiceButton
  TranscribeAPI
} from 'vue-transcribe';
import axios from 'axios';

TranscribeAPI.setCommandMap([
  {
    command: 'clear input',
    task: () => {
      const el = document.querySelector('input');
      if (el) el.value = '';
    }
  },
]);

function setURL() {
  axios.get('/api/transcribe-url') // You are to set up this endpoint
    .then(res => TranscribeAPI.setURL(res.data.url));
}

setURL();
setInterval(setURL, 5 * 60 * 1000);


TranscribeAPI.on('error', err => {
  console.error('Transcription error:', err);
  // You can trigger a toast, log or do anything of choice here
});

TranscribeAPI.setConfigured(true)

Vue.component('VoiceButton', VoiceButton); // Global registration

Requirements & Notes

  • You must manually refresh AWS presigned URLs every 5 minutes
  • VoiceButton only renders when: TranscribeAPI.isConfigured() is true
  • Command Map must be an array of { command, task }
  • Use TranscribeAPI.on('error', cb) to listen for transcription/command errors

References


License

MIT


Contributing

Merge Requests welcome! Please follow existing code style and include docs for any new features or events.


Author

Charles Ugbana

Package Sidebar

Install

npm i vue-transcribe

Weekly Downloads

3

Version

1.2.2

License

MIT

Unpacked Size

190 kB

Total Files

4

Last publish

Collaborators

  • cugbana