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) {
...