-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathspeak.js
More file actions
executable file
·78 lines (66 loc) · 2.63 KB
/
Copy pathspeak.js
File metadata and controls
executable file
·78 lines (66 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/env node
const fs = require('fs');
const { spawn } = require('child_process');
const TTS_API_BASE_URL = process.env.TTS_API_BASE_URL || 'https://api.openai.com/v1';
const TTS_API_KEY = process.env.TTS_API_KEY || process.env.OPENAI_API_KEY;
const TTS_MODEL = process.env.TTS_MODEL;
const TTS_VOICE = process.env.TTS_VOICE;
const TTS_LANG = process.env.TTS_LANG;
const TTS_AUDIO_FORMAT = process.env.TTS_AUDIO_FORMAT || 'mp3'
const TTS_DEBUG = process.env.TTS_DEBUG;
const speak = async (input) => {
const model = TTS_MODEL || 'kokoro';
const voice = TTS_VOICE || 'af_bella';
const format = TTS_AUDIO_FORMAT;
const lang = TTS_LANG;
const response_format = format;
const speed = 1.0;
const body = { input, model, voice, format, response_format, speed, lang };
const auth = (TTS_API_KEY) ? { 'Authorization': `Bearer ${TTS_API_KEY}` } : {};
const url = `${TTS_API_BASE_URL}/audio/speech`;
try {
const timestamp = Date.now();
TTS_DEBUG && console.log(`Generating audio from text: ${input.length} characters...`)
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...auth },
body: JSON.stringify(body),
});
if (!response.ok) {
throw new Error(`HTTP error with the status: ${response.status} ${response.statusText}`);
}
const buffer = await response.arrayBuffer();
const elapsed = Date.now() - timestamp;
TTS_DEBUG && console.log(`Audio generation took ${elapsed} ms.`);
return buffer;
} catch (e) {
TTS_DEBUG && console.error(`Error`, e);
throw e;
}
};
(async () => {
const args = process.argv.slice(2);
let input = args.join(' ');
if (input.trim().length <= 0) {
const chunks = [];
for await (const chunk of process.stdin) {
chunks.push(chunk);
}
input = Buffer.concat(chunks).toString('utf8').trim();
}
if (input.trim().length <= 0) {
console.log('Usage:');
consolel.log()
console.log('/speak.js "How are you?"');
console.log('echo "Good morning" | ./speak.js');
process.exit(1);
}
const filename = `${(new Date()).toISOString().slice(0, 16).replace(/[-:T]/g, '')}.${TTS_AUDIO_FORMAT}`;
const buffer = await speak(input);
fs.writeFileSync(filename, Buffer.from(buffer));
TTS_DEBUG && console.log(`Saved ${buffer.byteLength} bytes to ${filename}`);
const speaker = spawn('play', [filename]);
speaker.on('error', (err) => {
console.error(`Failed to play audio: ${err.message}`);
});
})();