JamesBrill / react-speech-recognition

💬Speech recognition for your React app
https://webspeechrecognition.com/
MIT License
674 stars 120 forks source link

How to change language using recognition.lang? #8

Closed aizuddineismail closed 6 years ago

aizuddineismail commented 6 years ago

Hello ! I am a newbie programmer and I don't understand how to change the recognition.lang as stated in the documentation. Can you please clarify even more? Thank you

JamesBrill commented 6 years ago

Setting the language could be a one-time thing that you do when first rendering your component. For example, you could do this in the componentWillMount lifecycle hook - this gets called before your component gets rendered for the first time.

In here, you can get the recognition object that's injected into your component by React Speech Recognition. Once you have this object, you can set the language that it listens for. The language is represented by a locale string - these usually have a language part and a region part. For example, en-US represents "English - United States" or "American English". You can find a list of common ones here.

Let's take the example from the README and add recognition.lang to it. The following code sets the language to Chinese (zh-CN) before rendering the Dictaphone (note: I wrote this by hand and didn't test it).

import React, { PropTypes, Component } from 'react'
import SpeechRecognition from 'react-speech-recognition'

const propTypes = {
  // Props injected by SpeechRecognition
  transcript: PropTypes.string,
  recognition: PropTypes.object
}

class Dictaphone extends Component {
  componentWillMount() {
    const { recognition } = this.props
    recognition.lang = 'zh-CN'
  }

  render() {
    const { transcript } = this.props

    return (
      <div>
        <h1>Speak Chinese!</h1>
        <span>{transcript}</span>
      </div>
    )
  }
}

Dictaphone.propTypes = propTypes

export default SpeechRecognition(Dictaphone)

If you want the user to change the language, you could have an event handler inside the component that takes a locale string selected by the user and assigns it to recognition.lang:

onChangeLanguage(localeString) {
  const { recognition } = this.props
  recognition.lang = localeString
}

Hope that helps!

aizuddineismail commented 6 years ago

This is really helpful! I completely understood now. Thanks you very much! You've done such an amazing work!

JamesBrill commented 6 years ago

Thank you. 👍

Nitzahon commented 3 years ago

how would you implement this if Dictaphone in an functional component that uses callbacks. For instance, maybe I want a voice command to change the language

JamesBrill commented 3 years ago

@Nitzahon With the current API, I would just call startListening again with the new language when it is selected (either via voice command or button click). This restarts the microphone with the new language being detected.

Just for fun, I took your idea and made a dummy component that can switch languages by voice command.

import React, { useState, useEffect } from 'react'
import SpeechRecognition, { useSpeechRecognition } from '../SpeechRecognition'

const LANGUAGE_MAP = {
  'אנגלית': 'en-GB',
  'hebrew': 'he'
}
const Dictaphone = () => {
  const [language, setLanguage] = useState('en-GB')
  const commands = Object.keys(LANGUAGE_MAP).map(language => ({
    command: language,
    callback: () => {
      setLanguage(LANGUAGE_MAP[language])
      SpeechRecognition.startListening({
        continuous: true,
        language: LANGUAGE_MAP[language]
      })
    },
    matchInterim: true
  }))
  const { transcript } = useSpeechRecognition({ commands })

  useEffect(() => {
    SpeechRecognition.startListening({
      continuous: true,
      language: 'en-GB'
    })
  }, [])

  if (!SpeechRecognition.browserSupportsSpeechRecognition()) {
    return null
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column' }}>
      <span>language: {language}</span>
      <span>{transcript}</span>
    </div>
  )
}

export default Dictaphone

Using voice command to change language is not a good idea as you will need to map the name of every language to its translation in every other language. Worse still, the browser will only understand speech in the currently selected language. For example, when the browser is listening for Hebrew, it will not be able to detect the word "english", so you would have to detect אנגלית and map that to en-GB. It's possible that the user may not be able to speak the currently selected language. For example, imagine a French user arrives at this app and English is detected by default - they may not know the English word for "French". It would probably be easier to let users change their language via a dropdown menu. Fun idea though.

Nitzahon commented 3 years ago

You make a good case for not making it work via voice command. I'd probably go for a radio selection over a dropdown, since I only plan to have 2 supported languages