pimatic-tts
Version:
Pimatic plugin providing Text-to-Speech capability
117 lines (95 loc) • 4.23 kB
text/coffeescript
module.exports = (env) ->
_ = env.require 'lodash'
commons = require('pimatic-plugin-commons')(env)
t = env.require('decl-api').types
Promise = env.require 'bluebird'
TTSDevice = require("./TTSDevice")(env)
GoogleAPI = require('google-tts-api')
Request = require('request')
fs = require('fs')
#
# define the audio decoder module source here if needed
#
decoder = require('<decoder module')
class GoogleTTSDevice extends TTSDevice
constructor: (@config, lastState) ->
@id = @config.id
@name = @config.name
@actions = _.cloneDeep @actions
@attributes = _.cloneDeep @attributes
# Define Getter methods specific to this subclass
@actions.getAttribute = {
description: "Define additional getter methods here"
returns:
speed:
type: t.number}
# Define Attributes specific to this subclass
@attributes.attrib = {
description: "Define additional attributes here"
type: t.number
acronym: 'Attribute:'
discrete: true}
#
# Define additional options here or overload properties from the parent class
# These can be also be loaded from the device config, if you define these as a setting there
#
# REQUIRED: .AudioDecoder must point to the ClassName of the decoder you use
# REQUIRED: .AudioFormat must contain a file extension such as mp3,wav, etc. Depends on the TTS and decoder you use
@_options = {
device_option: @config.device_option ? '<default>'
audioDecoder: decoder.Decoder
audioFormat: 'mp3'
}
super()
# Implement Getter methods for defined Getters
getSpeed: -> Promise.resolve(@_options.speed)
#
# REQUIRED: generateResource: (file) -> Promise(resolve file, reject error)
#
# This method is the specific TTS resource generator, which should output an audio resource on disk with filename <file>
#
# The subClass must implement this method accepting a filename (string) as input
# It must return a Promise
# resolving with the same file (string) after successfully generating the TTS audio resource
# reject with an error on failure
#
# This Subclass inherits @_data and @_options objects which can be accessed in your method to generate the resource
#
# @_data = {
# text: {
# input: <string> -> Text string with unparsed variables
# static: <boolean> -> Indicates whether the string contains variables
# parsed: <string> -> Text string with resolved variables, to be used for generating TTS
# }
# }
#
# @_options.language = <string> -> BCP-47 language identifier
# @_options.volume = <number> -> Integer between 1 and 100
#
generateResource: (file) =>
return new Promise( (resolve, reject) =>
# Example implementation
ttsAPI(@_data.text.parsed, @_options.language).then( (resource) =>
readStream = Request.get(resource)
.on('error', (error) =>
msg = __("%s: Failure reading audio resource '%s'. Error: %s", @id, resource, error)
env.logger.debug msg
@base.rejectWithErrorString Promise.reject, msg
)
fsWrite = fs.createWriteStream(file)
.on('finish', () =>
fsWrite.close( () =>
env.logger.info __("%s: Speech resource for '%s' successfully generated.", @id, @_data.text.parsed)
resolve file
)
)
.on('error', (error) =>
fs.unlink(file)
@base.rejectWithErrorString Promise.reject, error
)
readStream.pipe(fsWrite)
).catch( (error) => @base.rejectWithErrorString Promise.reject, error )
).catch( (error) => @base.rejectWithErrorString Promise.reject, error )
destroy: () ->
super()
return GoogleTTSDevice