export = function (text, voice, speed, filename, callback) {
var commands, pipedData;
if (!text) {
// throw TypeError because API was used incorrectly
throw new TypeError('Must provide text parameter');
}
if (!filename) {
// throw TypeError because API was used incorrectly
throw new TypeError('Must provide a filename');
}
if (typeof callback !== 'function') {
callback = function() {};
}
// tailor command arguments to specific platforms
if (process.platform === 'darwin') {
if (!voice) {
commands = [ text ];
} else {
commands = [ '-v', voice, text];
}
if (speed) {
commands.push('-r', convertSpeed(speed));
}
if (filename){
commands.push('-o', filename, '--data-format=LEF32@32000');
}
} else {
// if we don't support the platform, callback with an error (next tick) - don't continue
return process.nextTick(function() {
callback(new Error('say.js export does not support platform ' + process.platform));
});
}
childD = child_process.spawn(say.speaker, commands);
childD.stdin.setEncoding('ascii');
childD.stderr.setEncoding('ascii');
if (pipedData) {
childD.stdin.end(pipedData);
}
childD.stderr.once('data', function(data) {
// we can't stop execution from this function
callback(new Error(data));
});
childD.addListener('exit', function (code, signal) {
if (code === null || signal !== null) {
return callback(new Error('say.js: could not talk, had an error [code: ' + code + '] [signal: ' + signal + ']'));
}
childD = null;
callback(null);
});
}...
return console.error(err);
}
console.log('Text has been spoken.');
});
// Export spoken audio to a WAV file
say.export("I'm sorry, Dave.", 'Cellos', 0.75, 'hal.wav
', function(err) {
if (err) {
return console.error(err);
}
console.log('Text has been saved to hal.wav.');
});
```
...speak = function (text, voice, speed, callback) {
var commands, pipedData;
if (typeof callback !== 'function') {
callback = function() {};
}
if (!text) {
// throw TypeError because API was used incorrectly
throw new TypeError('Must provide text parameter');
}
// tailor command arguments to specific platforms
if (process.platform === 'darwin') {
if (!voice) {
commands = [ text ];
} else {
commands = [ '-v', voice, text];
}
if (speed) {
commands.push('-r', convertSpeed(speed));
}
} else if (process.platform === 'linux') {
commands = ['--pipe'];
if (speed) {
pipedData = '(Parameter.set \'Audio_Command "aplay -q -c 1 -t raw -f s16 -r $(($SR*' + convertSpeed(speed) + '/100)) $FILE
") ';
}
if (voice) {
pipedData += '(' + voice + ') ';
}
pipedData += '(SayText \"' + text + '\")';
} else if (process.platform === 'win32') {
pipedData = text;
commands = [ 'Add-Type -AssemblyName System.speech; $speak = New-Object System.Speech.Synthesis.SpeechSynthesizer; $speak.Speak
([Console]::In.ReadToEnd())' ];
} else {
// if we don't support the platform, callback with an error (next tick) - don't continue
return process.nextTick(function() {
callback(new Error('say.js speak does not support platform ' + process.platform));
});
}
var options = (process.platform === 'win32') ? { shell: true } : undefined;
childD = child_process.spawn(say.speaker, commands, options);
childD.stdin.setEncoding('ascii');
childD.stderr.setEncoding('ascii');
if (pipedData) {
childD.stdin.end(pipedData);
}
childD.stderr.once('data', function(data) {
// we can't stop execution from this function
callback(new Error(data));
});
childD.addListener('exit', function (code, signal) {
if (code === null || signal !== null) {
return callback(new Error('say.js: could not talk, had an error [code: ' + code + '] [signal: ' + signal + ']'));
}
childD = null;
callback(null);
});
}...
## Usage
```javascript
var say = require('say');
// Use default system voice and speed
say.speak('Hello!');
// Stop the text currently being spoken
say.stop();
// More complex example (with an OS X voice) and slow speed
say.speak('whats up, dog?', 'Alex', 0.5);
...stop = function (callback) {
if (typeof callback !== 'function') {
callback = function() {};
}
if (!childD) {
return callback(new Error('No speech to kill'));
}
if (process.platform === 'linux') {
// TODO: Need to ensure the following is true for all users, not just me. Danger Zone!
// On my machine, original childD.pid process is completely gone. Instead there is now a
// childD.pid + 1 sh process. Kill it and nothing happens. There's also a childD.pid + 2
// aplay process. Kill that and the audio actually stops.
process.kill(childD.pid + 2);
} else if (process.platform === 'win32') {
childD.stdin.pause();
child_process.exec('taskkill /pid ' + childD.pid + ' /T /F')
} else {
childD.stdin.pause();
childD.kill();
}
childD = null;
callback(null);
}...
```javascript
var say = require('say');
// Use default system voice and speed
say.speak('Hello!');
// Stop the text currently being spoken
say.stop();
// More complex example (with an OS X voice) and slow speed
say.speak('whats up, dog?', 'Alex', 0.5);
// Fire a callback once the text has completed being spoken
say.speak('whats up, dog?', 'Good News', 1.0, function(err) {
if (err) {
...