Stream dictation through the platform speech recognizer
One.Speech provides dictation through the platform recognizer on iOS and Android, and the Web Speech API in browsers. It has isAvailable(), getPermissions(), requestPermissions(), and start(options, onEvent).
import { One } from 'one'
export async function dictate(onText: (text: string) => void) { if (!One.Speech.isAvailable()) return null
const permissions = await One.Speech.requestPermissions() if (!permissions.granted) return null
return One.Speech.start({ lang: 'en-US' }, (event) => { if (event.type === 'transcript' || event.type === 'end') onText(event.transcript) if (event.type === 'error') console.error(event.error, event.message) })}isAvailable() returns a boolean synchronously. The permission methods resolve { status, granted, canAskAgain }, where status is 'granted', 'denied', or 'undetermined'. On iOS, restricted: true means Screen Time or device management blocks speech recognition.
start takes an optional BCP-47 lang, which defaults to the device language, and returns a session with stop() and abort(). A session emits start, full transcript updates, then exactly one end or error. Every event carries the whole transcript so far. stop() finishes listening and the final transcript arrives in end. abort() ends silently. Starting another session replaces the previous one; its callback and session handle no longer affect the new recognizer.
Error events carry one of not-allowed, service-not-allowed, language-not-supported, audio-capture, interrupted, network, busy, or unknown, plus an optional message.
Set native.app.speech so prebuild writes the iOS usage descriptions (NSSpeechRecognitionUsageDescription and NSMicrophoneUsageDescription) and the Android recognition service query:
import { one } from 'one/vite'
export default { plugins: [ one({ native: { app: { name: 'MyApp', speech: { recognition: 'Dictate notes by voice', microphone: 'Dictate notes by voice', }, }, }, }), ],}On web, SpeechRecognition or webkitSpeechRecognition supplies dictation where
present. isAvailable() reflects constructor availability; the browser’s
recognition service can still reject a session, including network failures.
Permission methods check or request microphone access. A denied recognition
service also marks permission denied. Browsers may prompt again when recognition
starts and may require a user gesture. Recognition errors use the same codes.
Without a recognizer, permission reads report denied and start throws
Speech.start needs an iOS or Android build. SSR has the same unavailable
contract. Browser service availability and actual transcription still depend on
the browser, network, language, and device.
Edit this page on GitHub.