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