UNPKG

@nomyx/assistant-cli

Version:

A javascript-based assistant that can help you with your daily tasks

105 lines (99 loc) 5.71 kB
require('dotenv').config(); const PlayHT = require("playht"); const fs = require('fs'); var player = require('play-sound')({}) function getNonce() { return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); } module.exports = { state: { modules: [{ name: 'play.ht', description: 'Text to speech using PlayHT', version: '0.0.1', }], playHT: { defaultVoice: 'female' } }, schemas: [{ "type": 'function', "function": { "name": 'say_aloud', "description": 'say the text using text-to-speech', "parameters": { "type": 'object', "properties": { "text": { "type": 'string', "description": 'the text to say', }, "voice": { "type": 'string', "description": 'the voice to use (can be \'male\' or \'female\'). If not specified, the default female voice will be used', } }, "required": ['text'] } } }], tools: { say_aloud: async ({ text, voice }) => { var config = require('../config'); const apiKey = config.PLAYHT_AUTHORIZATION; const userId = config.PLAYHT_USER_ID; const maleVoice = config.PLAYHT_MALE_VOICE; const femaleVoice = config.PLAYHT_FEMALE_VOICE; if(!voice) voice = config.playHT.defaultVoice; if(!apiKey || !userId || !maleVoice || !femaleVoice) { const missing = []; if(!apiKey) missing.push('playHT.apiKey'); if(!userId) missing.push('playHT.userId'); if(!maleVoice) missing.push('playHT.maleVoice'); if(!femaleVoice) missing.push('playHT.femaleVoice'); return `Missing configuration: ${missing.join(', ')} in configuration file. Please ask the user to provide the missing configuration using the ask_for_data tool.`; } // Initialize PlayHT API PlayHT.init({ apiKey: apiKey, userId: userId, }); async function speakSentence(sentence, voice) { if(!sentence) return; const stream = await PlayHT.stream(sentence, { voiceEngine: "PlayHT2.0-turbo", voiceId: voice === 'male' ? maleVoice : femaleVoice, }); const chunks = []; stream.on("data", (chunk) => chunks.push(chunk)); return new Promise((resolve, reject) => { stream.on("end", () => { const buf = Buffer.concat(chunks); // save the audio to a file const filename = `${getNonce()}.mp3`; fs.writeFileSync(filename, buf); player.play(filename, function (err) { fs.unlinkSync(filename); resolve(`done`); }); }); }) } // split the text into sentences const sentences = text.split(/[.!?]/g).filter((sentence) => sentence.length > 0); const consumeSentence = async () => { return new Promise((resolve, reject) => { const loop = async ()=> { const sentence = sentences.shift(); if(!sentence) return resolve('done'); await speakSentence(sentence, voice); return await loop(); }; return loop(); }); }; await consumeSentence(); return '(aloud) ' + text; } } };