├── .eslintignore
├── .eslintrc.cjs
├── .gitignore
├── .npmrc
├── .prettierignore
├── .prettierrc
├── .vscode
└── settings.json
├── README.md
├── docs
├── API.md
├── COMPONENTS.md
├── POLYFILLS.md
└── logos
│ ├── microsoft.png
│ └── speechly.png
├── package.json
├── pnpm-lock.yaml
├── postcss.config.cjs
├── src
├── app.css
├── app.d.ts
├── app.html
├── global.d.ts
├── hooks.ts
├── lib
│ ├── NativeSpeechRecognition.ts
│ ├── RecognitionManager.ts
│ ├── SpeechRecognition.ts
│ ├── components
│ │ ├── Button.svelte
│ │ ├── Listen.svelte
│ │ └── Stop.svelte
│ ├── constants.ts
│ ├── index.ts
│ ├── isAndroid.ts
│ ├── reducers.ts
│ ├── stores.ts
│ ├── types.ts
│ └── utils.ts
└── routes
│ ├── Dictaphones.svelte
│ ├── _Dictaphone
│ ├── Dictaphone.svelte
│ ├── DictaphoneWidgetA.svelte
│ └── DictaphoneWidgetB.svelte
│ ├── __layout.svelte
│ ├── components
│ ├── Dictaphones.svelte
│ ├── _Dictaphone
│ │ ├── Dictaphone.svelte
│ │ ├── DictaphoneWidgetA.svelte
│ │ └── DictaphoneWidgetB.svelte
│ └── index.svelte
│ └── index.svelte
├── static
├── favicon.png
└── robots.txt
├── svelte.config.js
├── tailwind.config.cjs
└── tsconfig.json
/.eslintignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | package.json
12 | pnpm-lock.yaml
13 | package-lock.json
14 | yarn.lock
15 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: '@typescript-eslint/parser',
4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
5 | plugins: ['svelte3', '@typescript-eslint'],
6 | ignorePatterns: ['*.cjs'],
7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
8 | settings: {
9 | 'svelte3/typescript': () => require('typescript')
10 | },
11 | parserOptions: {
12 | sourceType: 'module',
13 | ecmaVersion: 2020
14 | },
15 | env: {
16 | browser: true,
17 | es2017: true,
18 | node: true
19 | },
20 | rules: {
21 | "prefer-rest-params": "off",
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 | .vercel
10 | .output
11 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | package.json
12 | pnpm-lock.yaml
13 | package-lock.json
14 | yarn.lock
15 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "useTabs": true,
3 | "singleQuote": true,
4 | "trailingComma": "none",
5 | "printWidth": 100
6 | }
7 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true,
3 | "files.autoSave": "onFocusChange",
4 | "[svelte]": {
5 | "editor.defaultFormatter": "svelte.svelte-vscode",
6 | "editor.codeActionsOnSave": [
7 | "source.fixAll",
8 | "source.sortImports"
9 | ]
10 | },
11 | "typescript.tsserver.experimental.enableProjectDiagnostics": true,
12 | "editor.quickSuggestions": {
13 | "strings": true
14 | },
15 | "eslint.validate": [
16 | "javascript",
17 | "javascriptreact",
18 | "svelte"
19 | ]
20 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # svelte-speech-recognition
2 | [](https://www.npmjs.com/package/svelte-speech-recognition)
3 | [](https://www.npmjs.com/package/svelte-speech-recognition)
4 | [](https://svelte-speech-recognition.netlify.app/)
5 | [](https://github.com/jhubbardsf/svelte-speech-recognition)
6 |
7 |
8 | A Svelte library that converts speech from the microphone to text and makes it available to your Svelte components. Originally based off the [react-speech-recognition](https://github.com/JamesBrill/react-speech-recognition) library.
9 |
10 | NOTE: This is a WIP and still in alpha. There's still a bit of work to do before v1. That being said it's functional and any testing would be appreciated.
11 |
12 | ## How it works
13 | `useSpeechRecognition` is a Svelte hook that gives a component access to a transcript of speech picked up from the user's microphone.
14 |
15 | `SpeechRecognition` manages the global state of the Web Speech API, exposing functions to turn the microphone on and off.
16 |
17 | Under the hood,
18 | it uses [Web Speech API](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition). Note that browser support for this API is currently limited, with Chrome having the best experience - see [supported browsers](#supported-browsers) for more information.
19 |
20 | ## Useful links
21 |
22 | * [Basic example](#basic-example)
23 | * [Why you should use a polyfill with this library](#why-you-should-use-a-polyfill-with-this-library)
24 | * [Cross-browser example](#cross-browser-example)
25 | * [Svelte-Components](docs/COMPONENTS.md)
26 | * [Polyfills](docs/POLYFILLS.md)
27 | * [API docs](docs/API.md)
28 |
29 | ## Installation
30 |
31 | To install:
32 |
33 | `npm install --save-dev svelte-speech-recognition`
34 |
35 | To import in your Svelte code:
36 |
37 | `import SpeechRecognition, { useSpeechRecognition } from 'svelte-speech-recognition/SpeechRecognition'`
38 |
39 | ## Basic example
40 |
41 | The most basic example of a component using this hook would be:
42 |
43 | ```sv
44 |
54 |
55 | This is the final transcript:
56 | {$transcriptStore.finalTranscript}
57 |
58 | This is the interim transcript:
59 | {$transcriptStore.interimTranscript}
60 | ```
61 |
62 | You can see more examples in the example Svelte app attached to this repo. See [Developing](#developing).
63 |
64 | ## Why you should use a polyfill with this library
65 |
66 | By default, speech recognition is not supported in all browsers, with the best native experience being available on desktop Chrome. To avoid the limitations of native browser speech recognition, it's recommended that you combine `svelte-speech-recognition` with a [speech recognition polyfill](docs/POLYFILLS.md). Why? Here's a comparison with and without polyfills:
67 | * ✅ With a polyfill, your web app will be voice-enabled on all modern browsers (except Internet Explorer)
68 | * ❌ Without a polyfill, your web app will only be voice-enabled on the browsers listed [here](#supported-browsers)
69 | * ✅ With a polyfill, your web app will have a consistent voice experience across browsers
70 | * ❌ Without a polyfill, different native implementations will produce different transcriptions, have different levels of accuracy, and have different formatting styles
71 | * ✅ With a polyfill, you control who is processing your users' voice data
72 | * ❌ Without a polyfill, your users' voice data will be sent to big tech companies like Google or Apple to be transcribed
73 | * ✅ With a polyfill, `svelte-speech-recognition` will be suitable for use in commercial applications
74 | * ❌ Without a polyfill, `svelte-speech-recognition` will still be fine for personal projects or use cases where cross-browser support is not needed
75 |
76 | `svelte-speech-recognition` currently supports polyfills for the following cloud providers:
77 |
78 |
87 |
88 | ## Cross-browser example
89 |
90 | You can find the full guide for setting up a polyfill [here](docs/POLYFILLS.md). Alternatively, here is a quick (and free) example using Speechly:
91 | * Install `@speechly/speech-recognition-polyfill` in your web app
92 | * You will need a Speechly app ID. To get one of these, sign up for free with Speechly and follow [the guide here](https://docs.speechly.com/quick-start/stt-only/)
93 | * Here's a component for a push-to-talk button. The basic example above would also work fine.
94 | ```sv
95 |
112 |
113 | {#if (!browserSupportsSpeechRecognition)}
114 | Browser doesn't support speech recognition
115 | {:else}
116 |
117 |
Microphone: {listening ? 'on' : 'off'}
118 |
124 |
{$transcriptStore.finalTranscript}
125 |
126 | {/if}
127 | ```
128 |
129 | ## Detecting browser support for Web Speech API
130 |
131 | If you choose not to use a polyfill, this library still fails gracefully on browsers that don't support speech recognition. It is recommended that you render some fallback content if it is not supported by the user's browser:
132 |
133 | ```sv
134 | {#if (!browserSupportsSpeechRecognition)}
135 | // Render some fallback content
136 | {/if}
137 | ```
138 |
139 | ### Supported browsers
140 |
141 | Without a polyfill, the Web Speech API is largely only supported by Google browsers. As of May 2022, the following browsers support the Web Speech API:
142 |
143 | * Chrome (desktop)
144 | * Safari
145 | * Microsoft Edge
146 | * Chrome (Android): a word of warning about this platform, which is that there can be an annoying beeping sound when turning the microphone on. This is part of the Android OS and cannot be controlled from the browser
147 | * Android webview
148 | * Samsung Internet
149 |
150 | For all other browsers, you can render fallback content using the `SpeechRecognition.browserSupportsSpeechRecognition` function described above. Alternatively, as mentioned before, you can integrate a [polyfill](docs/POLYFILLS.md).
151 |
152 | ## Detecting when the user denies access to the microphone
153 |
154 | Even if the browser supports the Web Speech API, the user still has to give permission for their microphone to be used before transcription can begin. They are asked for permission when `svelte-speech-recognition` first tries to start listening. At this point, you can detect when the user denies access via the `isMicrophoneAvailable` state. When this becomes `false`, it's advised that you disable voice-driven features and indicate that microphone access is needed for them to work.
155 |
156 | ```sv
157 | {#if (!isMicrophoneAvailable)}
158 | // Render some fallback content
159 | {/if}
160 | ```
161 |
162 | ## Controlling the microphone
163 |
164 | Before consuming the transcript, you should be familiar with `SpeechRecognition`, which gives you control over the microphone. The state of the microphone is global, so any functions you call on this object will affect _all_ components using `useSpeechRecognition`.
165 |
166 | ### Turning the microphone on
167 |
168 | To start listening to speech, call the `startListening` function.
169 |
170 | ```sv
171 | SpeechRecognition.startListening()
172 | ```
173 |
174 | This is an asynchronous function, so it will need to be awaited if you want to do something after the microphone has been turned on.
175 |
176 | ### Turning the microphone off
177 |
178 | To turn the microphone off, but still finish processing any speech in progress, call `stopListening`.
179 |
180 | ```sv
181 | SpeechRecognition.stopListening()
182 | ```
183 |
184 | To turn the microphone off, and cancel the processing of any speech in progress, call `abortListening`.
185 |
186 | ```sv
187 | SpeechRecognition.abortListening()
188 | ```
189 |
190 | ## Consuming the microphone transcript
191 |
192 | To make the microphone transcript available as a Svelte store in your component. It has the interimTranscript and finalTranscript object, simply add:
193 |
194 | ```sv
195 | const { transcriptStore } = useSpeechRecognition()
196 | ```
197 |
198 | ## Resetting the microphone transcript
199 |
200 | To set the transcript to an empty string, you can call the `resetTranscript` function provided by `useSpeechRecognition`. Note that this is local to your component and does not affect any other components using Speech Recognition.
201 |
202 | ```sv
203 | const { resetTranscript } = useSpeechRecognition()
204 | ```
205 |
206 | ## Commands
207 |
208 | To respond when the user says a particular phrase, you can pass in a list of commands to the `useSpeechRecognition` hook. Each command is an object with the following properties:
209 | - `command`: This is a string or `RegExp` representing the phrase you want to listen for. If you want to use the same callback for multiple commands, you can also pass in an array here, with each value being a string or `RegExp`
210 | - `callback`: The function that is executed when the command is spoken. The last argument that this function receives will always be an object containing the following properties:
211 | - `command`: The command phrase that was matched. This can be useful when you provide an array of command phrases for the same callback and need to know which one triggered it
212 | - `resetTranscript`: A function that sets the transcript to an empty string
213 | - `matchInterim`: Boolean that determines whether "interim" results should be matched against the command. This will make your component respond faster to commands, but also makes false positives more likely - i.e. the command may be detected when it is not spoken. This is `false` by default and should only be set for simple commands.
214 | - `isFuzzyMatch`: Boolean that determines whether the comparison between speech and `command` is based on similarity rather than an exact match. Fuzzy matching is useful for commands that are easy to mispronounce or be misinterpreted by the Speech Recognition engine (e.g. names of places, sports teams, restaurant menu items). It is intended for commands that are string literals without special characters. If `command` is a string with special characters or a `RegExp`, it will be converted to a string without special characters when fuzzy matching. The similarity that is needed to match the command can be configured with `fuzzyMatchingThreshold`. `isFuzzyMatch` is `false` by default. When it is set to `true`, it will pass four arguments to `callback`:
215 | - The value of `command` (with any special characters removed)
216 | - The speech that matched `command`
217 | - The similarity between `command` and the speech
218 | - The object mentioned in the `callback` description above
219 | - `fuzzyMatchingThreshold`: If the similarity of speech to `command` is higher than this value when `isFuzzyMatch` is turned on, the `callback` will be invoked. You should set this only if `isFuzzyMatch` is `true`. It takes values between `0` (will match anything) and `1` (needs an exact match). The default value is `0.8`.
220 | - `bestMatchOnly`: Boolean that, when `isFuzzyMatch` is `true`, determines whether the callback should only be triggered by the command phrase that _best_ matches the speech, rather than being triggered by all matching fuzzy command phrases. This is useful for fuzzy commands with multiple command phrases assigned to the same callback function - you may only want the callback to be triggered once for each spoken command. You should set this only if `isFuzzyMatch` is `true`. The default value is `false`.
221 |
222 | ### Command symbols
223 |
224 | To make commands easier to write, the following symbols are supported:
225 | - Splats: this is just a `*` and will match multi-word text:
226 | - Example: `'I would like to order *'`
227 | - The words that match the splat will be passed into the callback, one argument per splat
228 | - Named variables: this is written `:` and will match a single word:
229 | - Example: `'I am :height metres tall'`
230 | - The one word that matches the named variable will be passed into the callback
231 | - Optional words: this is a phrase wrapped in parentheses `(` and `)`, and is not required to match the command:
232 | - Example: `'Pass the salt (please)'`
233 | - The above example would match both `'Pass the salt'` and `'Pass the salt please'`
234 |
235 | ### Example with commands
236 | ```sv
237 |
284 |
285 | {#if browserSupportsSpeechRecognition}
286 |
287 |
{message}
288 |
{$transcriptStore.finalTranscript}
289 |
290 | {:else}
291 |
Browser does not support speech recognition.
292 | {/if}
293 | ```
--------------------------------------------------------------------------------
/docs/API.md:
--------------------------------------------------------------------------------
1 | # API docs
2 |
3 | ## Interface
4 |
5 | * [useSpeechRecognition](#useSpeechRecognition)
6 | * [SpeechRecognition](#SpeechRecognition)
7 |
8 | ## useSpeechRecognition
9 |
10 | Hook for consuming speech recorded by the microphone. Import with:
11 |
12 | ```sv
13 | import { useSpeechRecognition } from 'svelte-speech-recognition/SpeechRecognition'
14 | ```
15 |
16 | ### Input props
17 |
18 | These are passed as an object argument to `useSpeechRecognition`:
19 |
20 | ```sv
21 | useSpeechRecognition({ transcribing, clearTranscriptOnListen, commands })
22 | ```
23 |
24 | #### transcribing [Writable]
25 |
26 | Writable svelte store. Is this component collecting a transcript or not? This is independent of the global `listening` state of the microphone. `true` by default.
27 |
28 | #### clearTranscriptOnListen [Writable]
29 |
30 | Writable svelte store. Does this component clear its transcript when the microphone is turned on? Has no effect when continuous listening is enabled. `true` by default.
31 |
32 | #### commands [list]
33 |
34 | See [Commands](../README.md#Commands).
35 |
36 | ### Output state
37 |
38 | These are returned from `useSpeechRecognition`:
39 |
40 | ```sv
41 | const {
42 | transcriptStore,
43 | interimTranscript
44 | finalTranscript,
45 | clearTranscriptOnListen,
46 | resetTranscript,
47 | listening,
48 | browserSupportsSpeechRecognition,
49 | isMicrophoneAvailable,
50 | } = useSpeechRecognition()
51 | ```
52 |
53 | #### transcriptStore [Readable<{ interimTranscript: string, finalTranscript: string[] }>]
54 |
55 | Transcription store with a finalTranscript and interimTranscript object.
56 |
57 | #### resetTranscript [() => void]
58 |
59 | Sets `transcriptStore.finalTranscript` to empty array & `transcriptStore.interimTranscript` to an empty string.
60 |
61 | #### listening [Readable]
62 |
63 | Svelte store that is updated when the Web Speech API is listening to speech from the microphone.
64 |
65 | #### transcriptStore.interimTranscript [string]
66 |
67 | Transcription of speech that the Web Speech API is still processing (i.e. it's still deciding what has just been spoken).
68 |
69 | For the current words being spoken, the interim transcript reflects each successive guess made by the transcription algorithm. When the browser’s confidence in its guess is maximized, it is added to the final transcript.
70 |
71 | The difference between interim and final transcripts can be illustrated by an example over four iterations of the transcription algorithm:
72 |
73 | | Final transcript | Interim transcript |
74 | | ------------------- | ------------------ |
75 | | 'Hello, I am' | 'jam' |
76 | | 'Hello, I am' | 'jams' |
77 | | 'Hello, I am' | 'James' |
78 | | 'Hello, I am James' | '' |
79 |
80 | #### transcriptStore.finalTranscript [string]
81 |
82 | Transcription of speech that the Web Speech API has finished processing.
83 |
84 | #### browserSupportsSpeechRecognition [bool]
85 |
86 | The Web Speech API is not supported on all browsers, so it is recommended that you render some fallback content if it is not supported by the user's browser:
87 |
88 | ```sv
89 | {#if (!browserSupportsSpeechRecognition)}
90 | // Render some fallback content
91 | {/if}
92 | ```
93 |
94 | #### browserSupportsContinuousListening [bool]
95 |
96 | Continuous listening is not supported on all browsers, so it is recommended that you apply some fallback behaviour if your web app uses continuous listening and is running on a browser that doesn't support it:
97 |
98 | ```sv
99 | {#if (browserSupportsContinuousListening)}
100 | SpeechRecognition.startListening({ continuous: true })
101 | {:else}
102 | // Fallback behaviour
103 | {/if}
104 | ```
105 |
106 | #### isMicrophoneAvailable [bool]
107 |
108 | The user has to give permission for their microphone to be used before transcription can begin. They are asked for permission when `svelte-speech-recognition` first tries to start listening. This state will become `false` if they deny access. In this case, it's advised that you disable voice-driven features and indicate that microphone access is needed for them to work.
109 |
110 | ```sv
111 | {#if (!isMicrophoneAvailable)}
112 | // Render some fallback content
113 | {/if}
114 | ```
115 |
116 | ## SpeechRecognition
117 |
118 | Object providing functions to manage the global state of the microphone. Import with:
119 |
120 | ```sv
121 | import SpeechRecognition from 'svelte-speech-recognition/SpeechRecognition'
122 | ```
123 |
124 | ### Functions
125 |
126 | #### startListening (async)
127 |
128 | Start listening to speech.
129 |
130 | ```sv
131 | SpeechRecognition.startListening()
132 | ```
133 |
134 | This is an asynchronous function, so it will need to be awaited if you want to do something after the microphone has been turned on.
135 |
136 | It can be called with an options argument. For example:
137 |
138 | ```sv
139 | SpeechRecognition.startListening({
140 | continuous: true,
141 | language: 'zh-CN'
142 | })
143 | ```
144 |
145 | The following options are available:
146 |
147 | ##### continuous [bool]
148 |
149 | By default, the microphone will stop listening when the user stops speaking (`continuous: false`). This reflects the approach taken by "press to talk" buttons on modern devices.
150 |
151 | If you want to listen continuously, set the `continuous` property to `true` when calling `startListening`. The microphone will continue to listen, even after the user has stopped speaking.
152 |
153 | ```sv
154 | SpeechRecognition.startListening({ continuous: true })
155 | ```
156 |
157 | #### language [string]
158 |
159 | To listen for a specific language, you can pass a language tag (e.g. `'zh-CN'` for Chinese) when calling `startListening`.
160 |
161 | ```sv
162 | SpeechRecognition.startListening({ language: 'zh-CN' })
163 | ```
164 |
165 | Some known supported languages (based on [this Stack Overflow post](http://stackoverflow.com/a/14302134/338039)):
166 |
167 | * Afrikaans `af`
168 | * Basque `eu`
169 | * Bulgarian `bg`
170 | * Catalan `ca`
171 | * Arabic (Egypt) `ar-EG`
172 | * Arabic (Jordan) `ar-JO`
173 | * Arabic (Kuwait) `ar-KW`
174 | * Arabic (Lebanon) `ar-LB`
175 | * Arabic (Qatar) `ar-QA`
176 | * Arabic (UAE) `ar-AE`
177 | * Arabic (Morocco) `ar-MA`
178 | * Arabic (Iraq) `ar-IQ`
179 | * Arabic (Algeria) `ar-DZ`
180 | * Arabic (Bahrain) `ar-BH`
181 | * Arabic (Lybia) `ar-LY`
182 | * Arabic (Oman) `ar-OM`
183 | * Arabic (Saudi Arabia) `ar-SA`
184 | * Arabic (Tunisia) `ar-TN`
185 | * Arabic (Yemen) `ar-YE`
186 | * Czech `cs`
187 | * Dutch `nl-NL`
188 | * English (Australia) `en-AU`
189 | * English (Canada) `en-CA`
190 | * English (India) `en-IN`
191 | * English (New Zealand) `en-NZ`
192 | * English (South Africa) `en-ZA`
193 | * English(UK) `en-GB`
194 | * English(US) `en-US`
195 | * Finnish `fi`
196 | * French `fr-FR`
197 | * Galician `gl`
198 | * German `de-DE`
199 | * Greek `el-GR`
200 | * Hebrew `he`
201 | * Hungarian `hu`
202 | * Icelandic `is`
203 | * Italian `it-IT`
204 | * Indonesian `id`
205 | * Japanese `ja`
206 | * Korean `ko`
207 | * Latin `la`
208 | * Mandarin Chinese `zh-CN`
209 | * Taiwanese `zh-TW`
210 | * Cantonese `zh-HK`
211 | * Malaysian `ms-MY`
212 | * Norwegian `no-NO`
213 | * Polish `pl`
214 | * Pig Latin `xx-piglatin`
215 | * Portuguese `pt-PT`
216 | * Portuguese (Brasil) `pt-br`
217 | * Romanian `ro-RO`
218 | * Russian `ru`
219 | * Serbian `sr-SP`
220 | * Slovak `sk`
221 | * Spanish (Argentina) `es-AR`
222 | * Spanish (Bolivia) `es-BO`
223 | * Spanish (Chile) `es-CL`
224 | * Spanish (Colombia) `es-CO`
225 | * Spanish (Costa Rica) `es-CR`
226 | * Spanish (Dominican Republic) `es-DO`
227 | * Spanish (Ecuador) `es-EC`
228 | * Spanish (El Salvador) `es-SV`
229 | * Spanish (Guatemala) `es-GT`
230 | * Spanish (Honduras) `es-HN`
231 | * Spanish (Mexico) `es-MX`
232 | * Spanish (Nicaragua) `es-NI`
233 | * Spanish (Panama) `es-PA`
234 | * Spanish (Paraguay) `es-PY`
235 | * Spanish (Peru) `es-PE`
236 | * Spanish (Puerto Rico) `es-PR`
237 | * Spanish (Spain) `es-ES`
238 | * Spanish (US) `es-US`
239 | * Spanish (Uruguay) `es-UY`
240 | * Spanish (Venezuela) `es-VE`
241 | * Swedish `sv-SE`
242 | * Turkish `tr`
243 | * Zulu `zu`
244 |
245 | #### stopListening (async)
246 |
247 | Turn the microphone off, but still finish processing any speech in progress.
248 |
249 | ```sv
250 | SpeechRecognition.stopListening()
251 | ```
252 |
253 | This is an asynchronous function, so it will need to be awaited if you want to do something after the microphone has been turned off.
254 |
255 | #### abortListening (async)
256 |
257 | Turn the microphone off, and cancel the processing of any speech in progress.
258 |
259 | ```sv
260 | SpeechRecognition.abortListening()
261 | ```
262 |
263 | This is an asynchronous function, so it will need to be awaited if you want to do something after the microphone has been turned off.
264 |
265 | #### getRecognition
266 |
267 | This returns the underlying [object](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition) used by Web Speech API.
268 |
269 | #### applyPolyfill
270 |
271 | Replace the native Speech Recognition engine (if there is one) with a custom implementation of the [W3C SpeechRecognition specification](https://wicg.github.io/speech-api/#speechreco-section). If there is a Speech Recognition implementation already listening to the microphone, this will be turned off. See [Polyfills](./POLYFILLS.md) for more information on how to use this.
272 |
273 | ```sv
274 | SpeechRecognition.applyPolyfill(SpeechRecognitionPolyfill)
275 | ```
--------------------------------------------------------------------------------
/docs/COMPONENTS.md:
--------------------------------------------------------------------------------
1 | # Svelte Components
2 |
3 | Below are the listen of Svelte components, their props, and what they can do. For code examples please look in [src/routes/components/Dictaphones.svelte](../src/routes/components/Dictaphones.svelte). Components come with a default button for testing but have a slot you can customize.
4 |
5 | - [Svelte Components](#svelte-components)
6 | - [Example w/ Ponyfill](#example-w-ponyfill)
7 | - [Listen](#listen)
8 | - [Stop](#stop)
9 |
10 | ---
11 |
12 | ## Example w/ Ponyfill
13 |
14 | ```sv
15 |
31 |
32 |
54 | ```
55 |
56 | ---
57 | ## Listen
58 | Props:
59 | * `language: string` Speech Recognition API language (support types [here](./API.md#language))
60 | * `continuous: boolean` Whether it will listen continuously or for one phrase
61 | * `SpeechRecognition` Instance of SpeechRecognition object
62 | * `buttonText: string` String you can customize for default button text
63 |
64 | Use:
65 |
66 | When the user clicks on this component the Speech Recognition API will start listening for text/commands.
67 |
68 | ---
69 |
70 | ## Stop
71 | Props:
72 | * `SpeechRecognition` Instance of SpeechRecognition object
73 |
74 | Use:
75 |
76 | When the clicks on this component the Speech Recognition API will stop.
77 |
78 |
--------------------------------------------------------------------------------
/docs/POLYFILLS.md:
--------------------------------------------------------------------------------
1 | # Polyfills
2 |
3 | If you want `svelte-speech-recognition` to work on more browsers than just Chrome, you can integrate a polyfill. This is a piece of code that fills in some missing feature in browsers that don't support it.
4 |
5 | Under the hood, Web Speech API in Chrome uses Google's speech recognition servers. To replicate this functionality elsewhere, you will need to host your own speech recognition service and implement the Web Speech API using that service. That implementation, which is essentially a polyfill, can then be plugged into `svelte-speech-recognition`. You can write that polyfill yourself, but it's recommended you use one someone else has already made.
6 |
7 | # Basic usage
8 |
9 | The `SpeechRecognition` class exported by `svelte-speech-recognition` has the method `applyPolyfill`. This can take an implementation of the [W3C SpeechRecognition specification](https://wicg.github.io/speech-api/#speechreco-section). From then on, that implementation will used by `svelte-speech-recognition` to transcribe speech picked up by the microphone.
10 |
11 | ```sv
12 | SpeechRecognition.applyPolyfill(SpeechRecognitionPolyfill)
13 | ```
14 |
15 | Note that this type of polyfill that does not pollute the global scope is known as a "ponyfill" - the distinction is explained [here](https://ponyfoo.com/articles/polyfills-or-ponyfills). `svelte-speech-recognition` will also pick up traditional polyfills - just make sure you import them before `svelte-speech-recognition`.
16 |
17 | ## Usage recommendations
18 | * Call this as early as possible to minimise periods where fallback content, which you should render while the polyfill is loading, is rendered. Also note that if there is a Speech Recognition implementation already listening to the microphone, this will be turned off when the polyfill is applied, so make sure the polyfill is applied before rendering any buttons to start listening
19 | * After `applyPolyfill` has been called, `browserSupportsSpeechRecognition` will be `true` on _most_ browsers, but there are still exceptions. Browsers like Internet Explorer do not support the APIs needed for polyfills - in these cases where `browserSupportsSpeechRecognition` is `false`, you should still have some suitable fallback content
20 | * Do not rely on polyfills being perfect implementations of the Speech Recognition specification - make sure you have tested them in different browsers and are aware of their individual limitations
21 |
22 | # Polyfill libraries
23 |
24 | Rather than roll your own, you should use a ready-made polyfill for a cloud provider's speech recognition service. `svelte-speech-recognition` currently supports polyfills for the following cloud providers:
25 |
26 | ## Speechly
27 |
28 |
29 |
30 |
31 |
32 | [Speechly](https://www.speechly.com/) specialises in enabling developers to create voice-driven UIs and provides a speech recognition API with a generous free tier to get you started. Their web speech recognition polyfill was developed with `react-speech-recognition` (the original fork for this library) in mind so is a great choice to combine with this library.
33 |
34 | * Polyfill repo: [speech-recognition-polyfill](https://github.com/speechly/speech-recognition-polyfill)
35 | * Polyfill author: [speechly](https://github.com/speechly)
36 | * Requirements:
37 | * Install `@speechly/speech-recognition-polyfill` in your web app
38 | * You will need a Speechly app ID. To get one of these, sign up with Speechly and follow [the guide here](https://docs.speechly.com/quick-start/stt-only/)
39 |
40 | Here is a basic example combining `speech-recognition-polyfill` and `svelte-speech-recognition` to get you started. This code worked with version 1.0.0 of the polyfill in May 2021 - if it has become outdated due to changes in the polyfill or in Speechly, please raise a GitHub issue or PR to get this updated.
41 |
42 | ```sv
43 |
59 |
60 | {#if (!browserSupportsSpeechRecognition)}
61 | Browser doesn't support speech recognition
62 | {:else}
63 |
64 |
Microphone: {listening ? 'on' : 'off'}
65 |
71 |
{$transcriptStore.finalTranscript}
72 |
73 | {/if}
74 | ```
75 |
76 | ### Limitations
77 | * The `lang` property is currently unsupported, defaulting to English transcription. In `svelte-speech-recognition`, this means that the `language` property in `startListening` cannot be used to change languages when using this polyfill. New languages will be coming soon!
78 | * Transcripts are generated in uppercase letters without punctuation. If needed, you can transform them using [toLowerCase()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase)
79 |
80 |
81 |
82 |
83 | ## Microsoft Azure Cognitive Services
84 |
85 |
86 |
87 |
88 |
89 | This is Microsoft's offering for speech recognition (among many other features). The free trial gives you $200 of credit to get started. It's pretty easy to set up - see the [documentation](https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/).
90 |
91 | * Polyfill repo: [web-speech-cognitive-services](https://github.com/compulim/web-speech-cognitive-services)
92 | * Polyfill author: [compulim](https://github.com/compulim)
93 | * Requirements:
94 | * Install `web-speech-cognitive-services` and `microsoft-cognitiveservices-speech-sdk` in your web app for this polyfill to function
95 | * You will need two things to configure this polyfill: the name of the Azure region your Speech Service is deployed in, plus a subscription key (or better still, an authorization token). [This doc](https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/overview#find-keys-and-region) explains how to find those
96 |
97 | Here is a basic example combining `web-speech-cognitive-services` and `svelte-speech-recognition` to get you started (do not use this in production; for a production-friendly version, read on below). This code worked with version 7.1.0 of the polyfill in February 2021 - if it has become outdated due to changes in the polyfill or in Azure Cognitive Services, please raise a GitHub issue or PR to get this updated.
98 |
99 | ```sv
100 |
122 |
123 | {#if (!browserSupportsSpeechRecognition)}
124 | Browser doesn't support speech recognition
125 | {:else}
126 |
44 | Some commands to try saying: "YOUR_NAME is my name.", "The weather is CONDITION today.", "My
45 | top sports are TEAM and TEAM", "clear". Look in
46 | src/routes/_Dictaphone/DictaphoneWidgetA.svelte and
47 | src/routes/_Dictaphone/DictaphoneWidgetb.svelte to see more commands and how they work.
48 |
44 | Some commands to try saying: "YOUR_NAME is my name.", "The weather is CONDITION today.", "My
45 | top sports are TEAM and TEAM", "clear". Look in
46 | src/routes/_Dictaphone/DictaphoneWidgetA.svelte and
47 | src/routes/_Dictaphone/DictaphoneWidgetb.svelte to see more commands and how they work.
48 |