@mikroways/reveal-md-common
Version:
Default configuration to work with Mikroways presentations
181 lines (158 loc) • 6.34 kB
JavaScript
require('axios-debug-log')({
request: function (debug, config) {
const axios = require('axios')
var url = axios.getUri(config)
debug(`Request ${url}\n headers:${config.headers}\n data:${JSON.stringify(config.data)}`);
}
})
const minimist = require('minimist'),
chalk = require('chalk'),
ElevenLabs = require("elevenlabs-node"),
fs = require('fs'),
{
glob,
globSync,
globStream,
globStreamSync,
Glob,
} = require('glob')
var opts = minimist(process.argv, {
boolean: ['force', 'help', 'user-subscription'],
string: [
'voice-stability',
'voice-similarity-boost',
'voice-style',
'voice-speacker-boost',
],
defaults: {
force: false,
'user-subscription': false
},
alias: {
"api-key": 'k',
voice: 'v',
model: 'm',
force: 'f',
'user-subscription': 'u',
help: 'h'
}
});
function help() {
console.error("text2voice [opts] input-file1.text input-file2.text");
console.error("Options:");
console.error(" --api-key | -k key");
console.error(" --api-key | -k key");
console.error(" --force | -f Force audio generation when is not needed");
console.error(" --voice | -v voiceId. Use help to list available voices");
console.error(" --model | -m modelId. Use help to list available models");
console.error(" --voice-stability Number. Override voice default value");
console.error(" --voice-similarity-boost Number. Override voice default value");
console.error(" --voice-style Number. Override voice default value");
console.error(" --voice-speacker-boost true|false. Override voice default value");
console.error("\n --user-subscription | -u If this option is given show user subscription");
}
function error(msg) {
console.error(chalk.red(`Error: ${msg}`));
help();
process.exit(2);
}
async function listVoices(el) {
let res = await el.getVoices();
console.log(chalk.yellow("\nVoices"));
console.log('\n');
console.log(res.voices.map(e =>
chalk.green(`${e.voice_id}: `) + chalk.white(`${e.name}`)).join('\n'));
}
async function listModels(el) {
let res = await el.getModels();
console.log(chalk.yellow("\nModels"));
console.log(res.map(e =>
chalk.green(`${e.model_id}: `)+ chalk.white(`${e.name}`)).join('\n'));
}
async function getVoiceSettings(el, voice) {
let voiceSettings ={},
settings = await el.getVoiceSettings({voiceId: voice});
voiceSettings.stability =
Number(voiceStability !== undefined ?
voiceStability : settings.stability);
voiceSettings.similarityBoost =
Number(voiceSimilarityBoost !== undefined ?
voiceSimilarityBoost : settings.similarity_boost);
voiceSettings.style =
Number(voiceStyle !== undefined ?
voiceStyle : settings.style);
voiceSettings.speackerBoost =
Boolean(voiceSpeakerBoost !== undefined ?
voiceSpeakerBoost : settings.use_speaker_boost);
return voiceSettings;
}
async function textfile2audiofile({el, file, voiceSettings, force}) {
let audioFile = file.replace(/\.(text|txt)$/i, "").concat(`-${voice}.mp3`);
let audioIsNewer = fs.existsSync(audioFile) &&
( fs.statSync(audioFile).mtimeMs > fs.statSync(file).mtimeMs );
if (!force && audioIsNewer) return console.error(
chalk.cyan(`Skipping file: ${file}. User -f to force`));
// Patch to avoid log errors from elevenlabs module
let disabledLogger = console.log;
console.log = function() {};
let res = await el.textToSpeech(Object.assign({
fileName: audioFile,
textInput: fs.readFileSync(file,'utf8')
},voiceSettings));
// Restore logger;
console.log = disabledLogger;
if (res && res.status && res.status.toLowerCase() == 'ok') console.log(chalk.bgGreen.bold(`OK: `)+chalk.green(file));
else console.log(chalk.bgRed.bold(`ERROR: `)+chalk.red(file));
}
async function showUserSubscription(el) {
let res = await el.getUserSubscription();
console.log(chalk.green(JSON.stringify(res, null, 4)));
}
async function start(opts) {
let textFiles = opts._.slice(2),
key = opts['api-key'] ? opts['api-key']: process.env.ELEVEN_API_KEY;
voice = opts.voice,
model = opts.model,
force = opts.force,
voiceSpeakerBoost = opts['voice-speacker-boost'],
voiceStability = opts['voice-stability'],
voiceSimilarityBoost = opts['voice-similarity-boost'],
voiceStyle = opts['voice-style'],
userSubscription = opts['user-subscription'];
if (opts.help) {
help();
process.exit(0);
}
if (!key) error("API key must be set");
let el = new ElevenLabs({ apiKey: key });
if (userSubscription) {
await showUserSubscription(el);
process.exit(0);
}
if (voice && ['?','help'].includes(voice.toLowerCase()) ) await listVoices(el);
if (model && ['?','help'].includes(model.toLowerCase()) ) await listModels(el);
/* When listVoices or listModels are called, we shalle exit */
if (
(voice && ['?','help'].includes(voice.toLowerCase())) ||
(model && ['?','help'].includes(model.toLowerCase()))
) process.exit(0);
/* Check if model and voice are set */
if (!voice && model) error("voice must be set");
if (!model) error("model must be set");
/* Get default VoiceSettings */
let voiceSettings = await getVoiceSettings(el, voice);
/* Foreach textFile (maybe glob or file, do */
for (const t of textFiles) {
let g = globSync(t,{});
for (const file of g) await textfile2audiofile({
el: el,
file: file,
voiceSettings: Object.assign(voiceSettings, {
voiceId: voice,
modelId: model
}),
force: force });
}
}
start(opts);