I am creating an application using Electron. Therefore, I want to output SpeechSynthesis voice to wav file.
This is only Japanese voice. (So I can't use library like meSpeak.)
And I want to use the voice installed in local PC. (like 唄詠, Softalk, etc, ...)
It was unable to output normally if it was the following code.
Although you can output the file itself, the content is unintended.
The tested environment is macOS 10.13.1.
How should I do it?
Main Process:
// This code is a part.
// Actually there are many different properties,
// This code shows only the minimum necessary part.
let obj = {
speech: "コンニチワ", // it was converted from sentence to reading katakana
cast: {
voice: {
pitch: 100,
speed: 100,
volume: 50.0,
name: ""
}
}
}
// mainWindow is BrowserWindow
mainWindow.webContents.send('record-speech', obj, "example.wav")
Renderer Process:
ipcRenderer.on('record-speech', (event, obj, path) => {
// Setup utterance
let voice = null
speechSynthesis.onvoiceschanged = () => {
voice = speechSynthesis.getVoices().find(({
name: _name
}) => _name === obj.cast.voice.name)
}
let utter = new SpeechSynthesisUtterance()
utter.lang = "ja-JP"
utter.text = obj.speech
utter.pitch = obj.cast.voice.pitch / 100
utter.rate = obj.cast.voice.speed / 20
utter.voice = voice
utter.volume = obj.cast.voice.volume / 100
let audioContext = new AudioContext()
navigator.getUserMedia({audio: true}, (stream) => {
let audioInput = audioContext.createMediaStreamSource(stream)
// Using 'wave-recorder' package of npm
let recorder = WaveRecorder(audioContext, {
channels: 2,
bitDepth: 32,
silenceDuration: 0.1
})
audioInput.connect(recorder.input)
let fileStream = fs.createWriteStream(path)
recorder.pipe(fileStream)
recorder.on('header', (header) => {
let headerStream = fs.createWriteStream(path, {
start: 0,
flags: 'w'
})
headerStream.write(header)
headerStream.end()
})
utter.onend = ((event) => {
console.log("Speak ended");
})
speechSynthesis.speak(utter)
}, (e) => { console.log(e); })
})