React-Native-Voice, How to concatenate new speech result with the previous speech recognition result?

1.9k Views Asked by At

I am using react-native-voice to convert speech to text in a React Native Application but i am not able to get the previously recognised text to concatenate with the latest recognised test.

Every-time a new sentence is recognised it replaces the previously recognised text what i want to achieve is it should recognise and concatenate the previous with the latest recognised test.

Here goes the code

react-native-voice code

async _startDefectDescriptionRecognition(e) {
    this.setState({
        recognized: '',
        started: '',
    });

    try {
        await Voice.start('en-UK');
    } catch (e) {
        console.error(e);
    }
}
onSpeechStart(e) {
    this.setState({
        started: '√',
    });
}
onSpeechRecognized(e) {
    this.setState({
        recognized: '√',
    });
}

onSpeechResults(e) {
    this.setState({
        defectDescriptionSpeechResult: e.value,
    });
}
updateDefectDescription(defectSpeech) {
    this.state.conditionDefectDescription = defectSpeech
}

Render Code

{this.state.defectDescriptionSpeechResult.map((result, index) => this.updateDefectDescription(result))}
<View style={{ width: '45%', }}>
    <TextInput
        placeholder="Defect Description"
        ref={input => { this.defectDescriptionClear = input }}
        multiline={true}
        onChangeText={(conditionDefectDescription) => this.setState({ conditionDefectDescription: conditionDefectDescription })}
        style={[styles.TextInputStyle, { height: 90, width: '100%', textAlign: 'center', fontSize: 15 }]}>
        {this.state.conditionDefectDescription}
    </TextInput>   
</View>
<TouchableOpacity style={{ paddingLeft: '0.5%', paddingRight: '1.5%' }}
    onPress={this._startDefectDescriptionRecognition.bind(this)}>    
    <Icons name='microphone-outline' style={this.state.demo1 == true ? { fontSize: 50, color: '#f12711' } : { fontSize: 50, color: '#23C3F0' }} />
</TouchableOpacity>

Output: The new text recognised is replacing the old text

Expected Output: The new text recognised should concatenate the old text

The full documentation of react-native-voice can be found here

Working Example of react-native-voice can be found here

2

There are 2 best solutions below

0
On

it is only a matter of re-binding the listeners on runtime, something like this:

export class _VoiceRecorder extends React.PureComponent<IInner> {
  private startRecording = async () => {
    const { setIsRecording, t } = this.props;
      try {
        Voice.onSpeechResults = this.onSpeechResultsHandler;
        Voice.onSpeechError = this.onSpeechErrorHandler;
        Voice.onSpeechEnd = this.onSpeechEndHandler;

        // @TODO: Needs to be i18ned
        await Voice.start('de-DE');
        setIsRecording(true);
      } catch (e) {
        log.warn('Something went wrong voice recording', e);
      }
  };

  private stopRecording = async (e?: React.SyntheticEvent) => {
    const { setIsRecording } = this.props;
    e?.stopPropagation();

    try {
      await Voice.stop();
      await Voice.cancel();
    } catch (e) {
    } finally {
      setIsRecording(false);
    }
  };

  private onSpeechResultsHandler = ({ value }: { value: string[] }) => {
    if (value[0]) {
      this.props.setTempResult(value[0]);
      if (Platform.OS === 'android') {
        this.onSpeechEndHandler();
      }
    }
  };

  private onSpeechEndHandler = () => {
    this.props.setIsRecording(false);
    this.props.onChange(this.props.tempResult);
    this.props.setTempResult('');
  };

  private onSpeechErrorHandler = (e: any) => {
    this.props.setIsRecording(false);
    this.props.setTempResult('');
  };

  public render() {
// component UI code comes here
}
0
On

For me this worked best

    ...
    const text = useRef('')
    ...
    const onSpeechResults = (e: any) => {
        //Invoked when SpeechRecognizer is finished recognizing
        text.current = text.current +' '+ e.value[0]
        setValue(text.current);
     };
     ...
     return (
      ...
      <TextInput
            style={{height: '100%', width: '95%',}}
            underlineColorAndroid="transparent"
            placeholder="Digite..."
            placeholderTextColor={"#CCC"}
            numberOfLines={6}
            multiline={true}
            onChangeText={(text) => setValue(text)}
            value={value}
      />
      ...
   )