Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Espeak on LInux and OSX #116

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.idea
node_modules
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const say = require('say')

// or, override the platform
const Say = require('say').Say
const say = new Say('darwin' || 'win32' || 'linux')
const say = new Say('darwin' || 'win32' || 'linux' || 'espeak')

// Use default system voice and speed
say.speak('Hello!')
Expand Down
46 changes: 46 additions & 0 deletions examples/espeak-demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env node
const Say = require('..').Say
const say = new Say('espeak')

let voices = [
{ voice: 'en-us', text: 'Good morning', speed: 1 },
{ voice: 'nb', text: 'God morgen', speed: 1 },
{ voice: 'en-us', text: 'Good morning', speed: 2 },
{ voice: 'nb', text: 'God morgen', speed: 0.5 }
]

sayIt(0)

say.export('whats up, dog?', 'en-us', 0.5, './exported.wav', (error) => {
if (error) {
return console.log(error)
}

console.log('export complete')
})

say.getInstalledVoices((err, voices) => {
if (err) {
console.error(err)
}
console.log(voices)
})

function sayIt (voice) {
let v = voices[voice]
console.log(v.voice, 'at speed', v.speed)

say.speak(v.text, v.voice, v.speed, (err) => {
voice++

if (err) {
console.error(err)
}

if (voice >= voices.length) {
process.exit(0)
}

sayIt(voice)
})
}
4 changes: 4 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
const SayLinux = require('./platform/linux.js')
const SayMacos = require('./platform/darwin.js')
const SayWin32 = require('./platform/win32.js')
const SayEspeak = require('./platform/espeak.js')

const MACOS = 'darwin'
const LINUX = 'linux'
const WIN32 = 'win32'
const ESPEAK = 'espeak'

class Say {
constructor (platform) {
Expand All @@ -18,6 +20,8 @@ class Say {
return new SayLinux()
} else if (platform === WIN32) {
return new SayWin32()
} else if (platform === ESPEAK) {
return new SayEspeak()
}

throw new Error(`new Say(): unsupported platorm! ${platform}`)
Expand Down
9 changes: 7 additions & 2 deletions platform/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class SayPlatformBase {
constructor () {
this.child = null
this.baseSpeed = 0
this.voicesSep = '\r\n'
}

/**
Expand Down Expand Up @@ -147,6 +148,10 @@ class SayPlatformBase {
return Math.ceil(this.baseSpeed * speed)
}

filterVoices(voices){
return voices
}

/**
* Get Installed voices on system
* @param {Function} callback A callback of type function(err,voices) to return.
Expand Down Expand Up @@ -177,12 +182,12 @@ class SayPlatformBase {
return callback(new Error(`say.getInstalledVoices(): could not get installed voices, had an error [code: ${code}] [signal: ${signal}]`))
}
if (voices.length > 0) {
voices = voices.split('\r\n')
voices = voices.split(this.voicesSep)
voices = (voices[voices.length - 1] === '') ? voices.slice(0, voices.length - 1) : voices
}
this.child = null

callback(null, voices)
callback(null, this.filterVoices(voices))
})

this.child.stdin.end()
Expand Down
72 changes: 72 additions & 0 deletions platform/espeak.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
const SayPlatformBase = require('./base.js')

const BASE_SPEED = 175
const COMMAND = 'espeak'

class SayPlatformEspeak extends SayPlatformBase {
constructor () {
super()
this.baseSpeed = BASE_SPEED
this.voicesSep = '\n'
}

buildSpeakCommand ({ text, voice, speed }) {
let args = []
let pipedData = ''
let options = {}

if (!voice) {
args.push(text)
} else {
args.push('-v', voice, text)
}

if (speed) {
args.push('-s', this.convertSpeed(speed))
}

return { command: COMMAND, args, pipedData, options }
}

buildExportCommand ({ text, voice, speed, filename }) {
let args = []
let pipedData = ''
let options = {}

if (!voice) {
args.push(text)
} else {
args.push('-v', voice, text)
}

if (speed) {
args.push('-s', this.convertSpeed(speed))
}

if (filename) {
args.push('-w', filename)
}

return { command: COMMAND, args, pipedData, options }
}

runStopCommand () {
this.child.stdin.pause()
this.child.kill()
}

filterVoices (voices) {
return voices.slice(1).map(
line => { return line.split(/[ ,]+/)[4] }
)
}

getVoices () {
let args = []
let psCommand = '--voices'
args.push(psCommand)
return { command: COMMAND, args }
}
}

module.exports = SayPlatformEspeak