-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathfile.js
executable file
·112 lines (101 loc) · 3.41 KB
/
file.js
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#! /usr/bin/env node
//
// Copyright 2024 Picovoice Inc.
//
// You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
// file accompanying this source.
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
//
'use strict';
const { program } = require('commander');
const fs = require('fs');
const { WaveFile } = require('wavefile');
const { Orca, OrcaActivationLimitReachedError } = require('@picovoice/orca-node');
program
.requiredOption(
'-a, --access_key <string>',
'AccessKey obtain from the Picovoice Console (https://console.picovoice.ai/)',
)
.requiredOption(
'-t, --text <string>',
'Text to be synthesized',
)
.requiredOption(
'-o, --output_path <string>',
'Absolute path to .wav file where the generated audio will be stored',
)
.option(
'-l, --library_file_path <string>',
'Absolute path to dynamic library',
)
.option(
'-m, --model_file_path <string>',
'Absolute path to Orca model',
)
.option(
'-v, --verbose',
'Verbose mode, prints metadata',
);
if (process.argv.length < 3) {
program.help();
}
program.parse(process.argv);
function fileDemo() {
let accessKey = program['access_key'];
let text = program['text'];
let outputPath = program['output_path'];
let libraryFilePath = program['library_file_path'];
let modelFilePath = program['model_file_path'];
let verbose = program['verbose'];
let orca = new Orca(
accessKey,
{
'modelPath': modelFilePath,
'libraryPath': libraryFilePath,
},
);
const loadPcm = (audioFile) => {
const waveBuffer = fs.readFileSync(audioFile);
const waveAudioFile = new WaveFile(waveBuffer);
return waveAudioFile.getSamples(false, Int16Array);
};
try {
const startTime = performance.now();
const alignments = orca.synthesizeToFile(text, outputPath);
const endTime = performance.now();
const processingTime = ((endTime - startTime) / 1000).toFixed(2);
const pcm = loadPcm(outputPath);
const lengthSec = (pcm.length / orca.sampleRate).toFixed(2);
console.log(`Orca took ${processingTime} seconds to synthesize ${lengthSec} seconds of speech which is ~${(lengthSec / processingTime).toFixed(2)} times faster than real-time.`);
console.log(`Audio written to ${outputPath}.`);
if (verbose) {
console.table(
alignments?.flatMap(alignment =>
alignment.phonemes.map((phoneme, i) => {
const row = {};
if (i === 0) {
row['Word'] = alignment.word;
row['Word Start time (s)'] = alignment.startSec.toFixed(2);
row['Word End time (s)'] = alignment.endSec.toFixed(2);
}
row['Phoneme'] = phoneme.phoneme;
row['Phoneme Start time (s)'] = phoneme.startSec.toFixed(2);
row['Phoneme End time (s)'] = phoneme.endSec.toFixed(2);
return row;
}),
),
);
}
} catch (err) {
if (err instanceof OrcaActivationLimitReachedError) {
console.error(`AccessKey '${accessKey}' has reached it's processing limit.`);
} else {
console.error(err);
}
}
orca.release();
}
fileDemo();