Saturday 13 October 2018

react speech synthesis

project linkhttp://chuanshuoge1-react-speech-synthesis.surge.sh/



app.js

import React, { Component } from 'react';
import './App.css';

import speakingImg from './speaking.gif';
import speakerImg from './speaker.png';

import 'antd/dist/antd.css';  // or 'antd/dist/antd.less';
import { Slider, Select, Row, Col, Input, Button } from 'antd';
const Option = Select.Option;
const { TextArea } = Input;

class App extends Component {

  constructor(props) {
    super(props)
    
    this.state={
      rate: 1,
      pitch: 1,
      voicesOption: [],
      voicesObj: [],
      selectedVoice: '',
      text: '',
      speaking: false,
    }
  }

  addVoiceOption = (item, index) =>{
    this.setState(prev=>{
      return{voicesOption: prev.voicesOption.concat(
        <Option key= {index} value={item.name}>{item.name} {item.lang}</Option>
      )}
    })
  }

  addVoiceObj = (voices) => {
    this.setState({voicesObj: voices});
  }

  voiceChange = (e) => {
    this.setState({selectedVoice: e});
  }

  textChange = (e) =>{
    this.setState({text: e.target.value});
  }

  rateChange = (e) =>{
    this.setState({rate: e});
  }

  pitchChange = (e) =>{
    this.setState({pitch: e});
  }

  speak = () =>{

    if(synth.speaking){
      console.error('busy speaking');
      return
    }

    if(this.state.selectedVoice===''){
      alert('please select a voice');
      return;
    }
    else{
      //is speaking
      this.setState({speaking: true});

      //speech synthesis the text
      const speechSynth = new SpeechSynthesisUtterance(this.state.text);

      //speak end
      speechSynth.onend = e => {
        this.setState({speaking: false});
      }

      //speak error
      speechSynth.onerror = e => {
        console.error('something went wrong');
      }

      //speak voice
      const voice = this.state.voicesObj.filter(x=>x.name === this.state.selectedVoice);
      speechSynth.voice = voice[0];

      //speak pitch and rate
      speechSynth.rate = this.state.rate;
      speechSynth.pitch = this.state.pitch;

      //speak
      synth.speak(speechSynth);
    }
  }

  render() {  

    let voices = [];

    //populate voices dropdown list
    const getVoices = () => {
      voices = synth.getVoices();  

      if(voices.length > 0){
        //clear voiceoptions
        this.setState({voicesOption:[]});
        //add voice options
        voices.map((item,index) => this.addVoiceOption(item, index));

        //add voice object
        this.addVoiceObj(voices);
      }
    }

    //speech synth is an async function, wait for voices to be added
    if(synth.onvoiceschanged !== undefined){
      synth.onvoiceschanged = getVoices;     
    }

    return (
      <div>
        <Row>
          <Col style={{marginLeft: 40}}>
            <img src={this.state.speaking? speakingImg: speakerImg}
               alt='speaker'></img>
          </Col>
          <Col>
            text input: <br/>
            <TextArea placeholder="Autosize height based on content lines"
              style={{width: 300}} autosize onChange={(e)=>this.textChange(e)}/>
          </Col>
          <Col>          
            rate:
            <Slider min={0} max={2} defaultValue={1} step={0.1} style={{width: 300}}
              onChange={(e)=>this.rateChange(e)}></Slider>
          </Col>
          <Col>
            pitch:
            <Slider min={0} max={2} defaultValue={1} step={0.1} style={{width: 300}}
              onChange={(e)=>this.pitchChange(e)}></Slider>
          </Col>
          <Col>
            voice: <br/>
            <Select defaultValue = 'select a voice' style={{width: 300}}
              onChange={(e)=>this.voiceChange(e)}>
              {this.state.voicesOption}
            </Select>            
          </Col>
          <Col>
            <br/>
            <Button type="primary" style={{width: 300}} 
              onClick={()=>this.speak()}>Speak</Button>
          </Col>
          <Col>
            <br/>
            browser may not support this browser api
          </Col>
        </Row>
      </div>
    );
  }
}

const synth = window.speechSynthesis;

export default App;

------------------------------------------------------

package.json

{
  "name": "speech-synthesis",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "antd": "^3.10.1",
    "react": "^16.5.2",
    "react-dom": "^16.5.2",
    "react-scripts": "2.0.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

---------------------------------------
reference:

No comments:

Post a Comment