@bestcodes/edge-tts 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -10
- package/dist/index.d.ts +34 -11
- package/dist/index.mjs +8 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,9 +21,9 @@ bun add @bestcodes/edge-tts
|
|
|
21
21
|
### Get audio buffer
|
|
22
22
|
|
|
23
23
|
```ts
|
|
24
|
-
import {
|
|
24
|
+
import { generateSpeech } from "@bestcodes/edge-tts";
|
|
25
25
|
|
|
26
|
-
const audio = await
|
|
26
|
+
const audio = await generateSpeech({
|
|
27
27
|
text: "Hello, world!",
|
|
28
28
|
voice: "en-US-EmmaMultilingualNeural",
|
|
29
29
|
});
|
|
@@ -34,9 +34,9 @@ const audio = await streamSpeech({
|
|
|
34
34
|
### Save to file
|
|
35
35
|
|
|
36
36
|
```ts
|
|
37
|
-
import {
|
|
37
|
+
import { generateSpeechToFile } from "@bestcodes/edge-tts";
|
|
38
38
|
|
|
39
|
-
await
|
|
39
|
+
await generateSpeechToFile({
|
|
40
40
|
text: "Hello, world!",
|
|
41
41
|
outputPath: "./output.mp3",
|
|
42
42
|
});
|
|
@@ -45,14 +45,65 @@ await streamSpeechToFile({
|
|
|
45
45
|
### With subtitles
|
|
46
46
|
|
|
47
47
|
```ts
|
|
48
|
-
import {
|
|
48
|
+
import { generateSpeechWithSubtitlesToFile } from "@bestcodes/edge-tts";
|
|
49
49
|
|
|
50
|
-
const { audio, subtitles } = await
|
|
50
|
+
const { audio, subtitles } = await generateSpeechWithSubtitlesToFile({
|
|
51
51
|
text: "This text will have subtitles.",
|
|
52
52
|
subtitlePath: "./subtitles.srt",
|
|
53
53
|
});
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
## Real-time Streaming
|
|
57
|
+
|
|
58
|
+
### Stream audio chunks
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { streamSpeech } from "@bestcodes/edge-tts";
|
|
62
|
+
|
|
63
|
+
for await (const chunk of streamSpeech({
|
|
64
|
+
text: "Hello, world!",
|
|
65
|
+
voice: "en-US-EmmaMultilingualNeural",
|
|
66
|
+
})) {
|
|
67
|
+
if (chunk.type === "audio" && chunk.data) {
|
|
68
|
+
// Process audio chunk in real-time
|
|
69
|
+
console.log(`Received ${chunk.data.length} bytes`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Stream directly to file with progress
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { streamSpeechToFile } from "@bestcodes/edge-tts";
|
|
78
|
+
|
|
79
|
+
for await (const progress of streamSpeechToFile({
|
|
80
|
+
text: "Hello, world!",
|
|
81
|
+
outputPath: "./output.mp3",
|
|
82
|
+
})) {
|
|
83
|
+
console.log(
|
|
84
|
+
`Written: ${progress.bytesWritten} bytes (chunk: ${progress.chunkSize})`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Stream with subtitles (real-time updates)
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { streamSpeechWithSubtitlesToFile } from "@bestcodes/edge-tts";
|
|
93
|
+
|
|
94
|
+
for await (const chunk of streamSpeechWithSubtitlesToFile({
|
|
95
|
+
text: "This text will have subtitles.",
|
|
96
|
+
subtitlePath: "./subtitles.srt",
|
|
97
|
+
})) {
|
|
98
|
+
if (chunk.type === "audio" && chunk.data) {
|
|
99
|
+
// Process audio chunk
|
|
100
|
+
} else if (chunk.subtitles) {
|
|
101
|
+
// Subtitles file updated in real-time
|
|
102
|
+
console.log("Subtitles updated:", chunk.subtitles);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
56
107
|
## Options
|
|
57
108
|
|
|
58
109
|
```ts
|
|
@@ -66,8 +117,8 @@ const { audio, subtitles } = await streamSpeechWithSubtitles({
|
|
|
66
117
|
proxy?: string; // Optional proxy URL
|
|
67
118
|
connectTimeoutSeconds?: number; // Default: 10
|
|
68
119
|
receiveTimeoutSeconds?: number; // Default: 60
|
|
69
|
-
outputPath?: string; // For streamSpeechToFile
|
|
70
|
-
subtitlePath?: string; // For
|
|
120
|
+
outputPath?: string; // For generateSpeechToFile/streamSpeechToFile
|
|
121
|
+
subtitlePath?: string; // For generateSpeechWithSubtitlesToFile/streamSpeechWithSubtitlesToFile
|
|
71
122
|
}
|
|
72
123
|
```
|
|
73
124
|
|
|
@@ -87,9 +138,9 @@ const englishVoices = await findVoices({ Locale: "en-US" });
|
|
|
87
138
|
## Low-level API
|
|
88
139
|
|
|
89
140
|
```ts
|
|
90
|
-
import {
|
|
141
|
+
import { Experimental_Raw } from "@bestcodes/edge-tts";
|
|
91
142
|
|
|
92
|
-
const communicate = new
|
|
143
|
+
const communicate = new Experimental_Raw.Communicate(
|
|
93
144
|
"Hello!",
|
|
94
145
|
"en-US-EmmaMultilingualNeural",
|
|
95
146
|
);
|
package/dist/index.d.ts
CHANGED
|
@@ -94,7 +94,7 @@ declare class VoicesManager {
|
|
|
94
94
|
static create(customVoices?: Voice[]): Promise<VoicesManager>;
|
|
95
95
|
find(options: VoicesManagerFindOptions): VoicesManagerVoice[];
|
|
96
96
|
}
|
|
97
|
-
export declare const
|
|
97
|
+
export declare const Experimental_Raw: {
|
|
98
98
|
Communicate: typeof Communicate;
|
|
99
99
|
SubMaker: typeof SubMaker;
|
|
100
100
|
VoicesManager: typeof VoicesManager;
|
|
@@ -104,9 +104,9 @@ export declare const Raw: {
|
|
|
104
104
|
utils: typeof utils;
|
|
105
105
|
};
|
|
106
106
|
/**
|
|
107
|
-
* Options for
|
|
107
|
+
* Options for generating speech.
|
|
108
108
|
*/
|
|
109
|
-
export interface
|
|
109
|
+
export interface GenerateSpeechOptions {
|
|
110
110
|
/** The text to convert to speech */
|
|
111
111
|
text: string;
|
|
112
112
|
/** Voice to use for synthesis (default: "en-US-EmmaMultilingualNeural") */
|
|
@@ -129,35 +129,35 @@ export interface StreamSpeechOptions {
|
|
|
129
129
|
/**
|
|
130
130
|
* Options for generating speech and writing to a file.
|
|
131
131
|
*/
|
|
132
|
-
export interface
|
|
132
|
+
export interface GenerateSpeechToFileOptions extends GenerateSpeechOptions {
|
|
133
133
|
/** Output file path for the generated audio */
|
|
134
134
|
outputPath: string;
|
|
135
135
|
}
|
|
136
136
|
/**
|
|
137
|
-
* Options for
|
|
137
|
+
* Options for generating speech with subtitles.
|
|
138
138
|
*/
|
|
139
|
-
export interface
|
|
139
|
+
export interface GenerateSpeechWithSubtitlesOptions extends GenerateSpeechOptions {
|
|
140
140
|
/** Output file path for the generated subtitles (SRT format) */
|
|
141
141
|
subtitlePath: string;
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
144
|
-
*
|
|
144
|
+
* Generate speech audio from text.
|
|
145
145
|
* @param options - Configuration options for speech synthesis
|
|
146
146
|
* @returns Promise resolving to the audio buffer
|
|
147
147
|
*/
|
|
148
|
-
export declare function
|
|
148
|
+
export declare function generateSpeech(options: GenerateSpeechOptions): Promise<Buffer>;
|
|
149
149
|
/**
|
|
150
150
|
* Generate speech from text and save it to a file.
|
|
151
151
|
* @param options - Configuration options including the output file path
|
|
152
152
|
* @returns Promise that resolves when the file is written
|
|
153
153
|
*/
|
|
154
|
-
export declare function
|
|
154
|
+
export declare function generateSpeechToFile(options: GenerateSpeechToFileOptions): Promise<void>;
|
|
155
155
|
/**
|
|
156
|
-
*
|
|
156
|
+
* Generate speech audio with generated subtitles.
|
|
157
157
|
* @param options - Configuration options including the subtitle file path
|
|
158
158
|
* @returns Promise resolving to the audio buffer and subtitles string
|
|
159
159
|
*/
|
|
160
|
-
export declare function
|
|
160
|
+
export declare function generateSpeechWithSubtitlesToFile(options: GenerateSpeechWithSubtitlesOptions): Promise<{
|
|
161
161
|
audio: Buffer;
|
|
162
162
|
subtitles: string;
|
|
163
163
|
}>;
|
|
@@ -179,6 +179,29 @@ export declare function findVoices(options: {
|
|
|
179
179
|
Language?: string;
|
|
180
180
|
ShortName?: string;
|
|
181
181
|
}, proxy?: string): Promise<VoicesManagerVoice[]>;
|
|
182
|
+
/**
|
|
183
|
+
* Stream speech audio in real-time from text.
|
|
184
|
+
* @param options - Configuration options for speech synthesis
|
|
185
|
+
* @returns AsyncGenerator yielding audio and metadata chunks as they arrive
|
|
186
|
+
*/
|
|
187
|
+
export declare function streamSpeech(options: GenerateSpeechOptions): AsyncGenerator<TTSChunk>;
|
|
188
|
+
/**
|
|
189
|
+
* Stream speech audio with subtitles in real-time.
|
|
190
|
+
* @param options - Configuration options including the subtitle file path
|
|
191
|
+
* @returns AsyncGenerator yielding audio chunks and subtitle data as they arrive
|
|
192
|
+
*/
|
|
193
|
+
export declare function streamSpeechWithSubtitlesToFile(options: GenerateSpeechWithSubtitlesOptions): AsyncGenerator<TTSChunk & {
|
|
194
|
+
subtitles?: string;
|
|
195
|
+
}>;
|
|
196
|
+
/**
|
|
197
|
+
* Stream speech audio directly to a file in real-time.
|
|
198
|
+
* @param options - Configuration options including the output file path
|
|
199
|
+
* @returns AsyncGenerator yielding progress information as chunks are written
|
|
200
|
+
*/
|
|
201
|
+
export declare function streamSpeechToFile(options: GenerateSpeechToFileOptions): AsyncGenerator<{
|
|
202
|
+
bytesWritten: number;
|
|
203
|
+
chunkSize: number;
|
|
204
|
+
}>;
|
|
182
205
|
|
|
183
206
|
declare namespace utils {
|
|
184
207
|
export { connectId, dateToString, escapeXml, getHeadersAndData, removeIncompatibleCharacters, splitTextByByteLength, unescapeXml };
|
package/dist/index.mjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
var
|
|
2
|
-
`);for(let F of
|
|
1
|
+
var a=Object.defineProperty;var t=(E,$)=>{for(var U in $)a(E,U,{get:$[U],enumerable:!0,configurable:!0,set:(_)=>$[U]=()=>_})};import*as w from"fs";import*as A from"path";import{HttpsProxyAgent as S0}from"https-proxy-agent";import F0 from"ws";var m="6A5AA1D4EAFF4E9FB37E23D68491D6F4",n="wss://speech.platform.bing.com/consumer/speech/synthesize/readaloud/edge/v1?TrustedClientToken=6A5AA1D4EAFF4E9FB37E23D68491D6F4",k="https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list?trustedclienttoken=6A5AA1D4EAFF4E9FB37E23D68491D6F4",p="en-US-EmmaMultilingualNeural";var Q="130.0.2849.68".split(".")[0],R="1-130.0.2849.68",u={"User-Agent":`Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${Q}.0.0.0 Safari/537.36 Edg/${Q}.0.0.0`,"Accept-Encoding":"gzip, deflate, br, zstd","Accept-Language":"en-US,en;q=0.9"},s={...u,Pragma:"no-cache","Cache-Control":"no-cache",Origin:"chrome-extension://jdiccldimpdaibmpdkjnbmckianbfold","Sec-WebSocket-Version":"13"},d={...u,Authority:"speech.platform.bing.com","Sec-CH-UA":`" Not;A Brand";v="99", "Microsoft Edge";v="${Q}", "Chromium";v="${Q}"`,"Sec-CH-UA-Mobile":"?0",Accept:"*/*","Sec-Fetch-Site":"none","Sec-Fetch-Mode":"cors","Sec-Fetch-Dest":"empty"};import*as P from"crypto";class q extends Error{constructor(E){super(E);this.name="EdgeTTSException"}}class x extends q{constructor(E){super(E);this.name="UnknownResponse"}}class Z extends q{constructor(E){super(E);this.name="UnexpectedResponse"}}class y extends q{constructor(E){super(E);this.name="NoAudioReceived"}}class D extends q{constructor(E){super(E);this.name="SkewAdjustmentError"}}var e=11644473600;class W{static clockSkewSeconds=0;static adjustClockSkewSeconds(E){W.clockSkewSeconds+=E}static getUnixTimestamp(){return Date.now()/1000+W.clockSkewSeconds}static parseRFC2616Date(E){let $=Date.parse(E);if(isNaN($))return null;return $/1000}static handleClientResponseError(E){let $=E.date||E.Date;if(!$||typeof $!=="string")throw new D("No server date in headers.");let U=W.parseRFC2616Date($);if(U===null)throw new D(`Failed to parse server date: ${$}`);let _=W.getUnixTimestamp();W.adjustClockSkewSeconds(U-_)}static generateSecMsGec(){let E=W.getUnixTimestamp();E+=e,E-=E%300,E*=1e7;let $=`${E.toFixed(0)}${m}`;return P.createHash("sha256").update($,"ascii").digest("hex").toUpperCase()}static generateMuid(){return P.randomBytes(16).toString("hex").toUpperCase()}static headersWithMuid(E){return{...E,Cookie:`muid=${W.generateMuid()};`}}}class L{voice;rate;volume;pitch;boundary;constructor(E,$="+0%",U="+0%",_="+0Hz",S="SentenceBoundary"){this.voice=E,this.rate=$,this.volume=U,this.pitch=_,this.boundary=S,this.validate()}validateStringParam(E,$,U){if(!U.test($))throw Error(`Invalid ${E} '${$}'.`)}validate(){let E=this.voice.match(/^([a-z]{2,})-([A-Z]{2,})-(.+Neural)$/);if(E){let $=E[1],U=E[2],_=E[3];if(_&&_.includes("-"))U=`${U}-${_.split("-")[0]}`,_=_.split("-")[1];this.voice=`Microsoft Server Speech Text to Speech Voice (${$}-${U}, ${_})`}this.validateStringParam("voice",this.voice,/^Microsoft Server Speech Text to Speech Voice \(.+,.+\)$/),this.validateStringParam("rate",this.rate,/^[+-]\d+%$/),this.validateStringParam("volume",this.volume,/^[+-]\d+%$/),this.validateStringParam("pitch",this.pitch,/^[+-]\d+Hz$/)}toSSML(E){return`<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis' xml:lang='en-US'><voice name='${this.voice}'><prosody pitch='${this.pitch}' rate='${this.rate}' volume='${this.volume}'>${E}</prosody></voice></speak>`}}var c={};t(c,{unescapeXml:()=>v,splitTextByByteLength:()=>h,removeIncompatibleCharacters:()=>l,getHeadersAndData:()=>f,escapeXml:()=>b,dateToString:()=>g,connectId:()=>V});import{v4 as E0}from"uuid";function V(){return E0().replace(/-/g,"")}function b(E){return E.replace(/[<>&'"]/g,($)=>{switch($){case"<":return"<";case">":return">";case"&":return"&";case"'":return"'";case'"':return""";default:return $}})}function v(E){return E.replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&").replace(/'/g,"'").replace(/"/g,'"')}function g(){return new Date().toUTCString()}function l(E){return(Buffer.isBuffer(E)?E.toString("utf-8"):E).split("").map((U)=>{let _=U.charCodeAt(0);if(_>=0&&_<=8||_>=11&&_<=12||_>=14&&_<=31)return" ";return U}).join("")}function $0(E,$){let U=E.subarray(0,$),_=U.lastIndexOf(10);if(_<0)_=U.lastIndexOf(32);return _}function U0(E){let $=E.length;while($>0){let U=E.subarray(0,$);try{let _=U[U.length-1];if(_!==void 0&&(_&128)===0)return $;let S=U.toString("utf-8");if(Buffer.from(S).length===U.length&&!S.endsWith("�"))return $;$--}catch(_){$--}}return $}function _0(E,$){let U=E.subarray(0,$),_=U.lastIndexOf(38);if(_>-1){if(U.indexOf(59,_)===-1)return _}return $}function*h(E,$){let U=Buffer.isBuffer(E)?E:Buffer.from(E,"utf-8");if($<=0)throw Error("byteLength must be > 0");while(U.length>$){let S=$0(U,$);if(S<0)S=U0(U.subarray(0,$));if(S=_0(U,S),S<=0)throw Error("Maximum byte length too small for text structure");let F=U.subarray(0,S).toString("utf-8").trim();if(F.length>0)yield Buffer.from(F);U=U.subarray(S+(S>0?0:1))}let _=U.toString("utf-8").trim();if(_.length>0)yield Buffer.from(_)}function f(E,$){let U={},_=E.subarray(0,$),S=E.subarray($+2),N=_.toString("utf-8").split(`\r
|
|
2
|
+
`);for(let F of N){let[O,r]=F.split(":",2);if(O&&r)U[O.trim()]=r.trim()}return{headers:U,data:S}}class G{ttsConfig;texts;options;state;constructor(E,$=p,U={}){this.options={rate:"+0%",volume:"+0%",pitch:"+0Hz",boundary:"SentenceBoundary",connectTimeoutSeconds:10,receiveTimeoutSeconds:60,...U},this.ttsConfig=new L($,this.options.rate,this.options.volume,this.options.pitch,this.options.boundary);let _=l(E),S=b(_);this.texts=Array.from(h(S,4096)),this.state={partialText:Buffer.alloc(0),offsetCompensation:0,lastDurationOffset:0,streamWasCalled:!1}}parseMetadata(E){let $=E.toString("utf-8"),U=JSON.parse($);for(let _ of U.Metadata){let S=_.Type;if(S==="WordBoundary"||S==="SentenceBoundary"){let N=_.Data.Offset+this.state.offsetCompensation,F=_.Data.Duration;return{type:S,offset:N,duration:F,text:v(_.Data.text.Text)}}if(S==="SessionEnd")continue;throw new x(`Unknown metadata type: ${S}`)}throw new Z("No boundary metadata found")}async*streamInternal(E){let $=this,U=!1,_=()=>{let C=$.ttsConfig.boundary==="WordBoundary",z=C?"true":"false",K=!C?"true":"false",H=`X-Timestamp:${g()}\r
|
|
3
3
|
Content-Type:application/json; charset=utf-8\r
|
|
4
4
|
Path:speech.config\r
|
|
5
5
|
\r
|
|
6
|
-
{"context":{"synthesis":{"audio":{"metadataoptions":{"sentenceBoundaryEnabled":"${
|
|
6
|
+
{"context":{"synthesis":{"audio":{"metadataoptions":{"sentenceBoundaryEnabled":"${K}","wordBoundaryEnabled":"${z}"},"outputFormat":"audio-24khz-48kbitrate-mono-mp3"}}}}`;E.send(H)},S=()=>{let C=V(),z=g(),K=$.ttsConfig.toSSML($.state.partialText.toString("utf-8")),H=`X-RequestId:${C}\r
|
|
7
7
|
Content-Type:application/ssml+xml\r
|
|
8
|
-
X-Timestamp:${
|
|
8
|
+
X-Timestamp:${z}Z\r
|
|
9
9
|
Path:ssml\r
|
|
10
10
|
\r
|
|
11
|
-
`+
|
|
11
|
+
`+K;E.send(H)};_(),S();let N=[],F=null,O=null,r=!1;E.on("message",(C,z)=>{if(r)return;if(N.push({data:C,isBinary:z}),F)F(),F=null}),E.on("error",(C)=>{if(r)return;if(O)O(C);r=!0}),E.on("close",()=>{if(r=!0,F)F()});while(!r||N.length>0){if(N.length===0){if(await new Promise((K,H)=>{F=K,O=H}),r&&N.length===0)break}let{data:C,isBinary:z}=N.shift();if(!z){let K=Buffer.from(C),H=K.indexOf(`\r
|
|
12
12
|
\r
|
|
13
|
-
`),{headers:
|
|
14
|
-
${
|
|
13
|
+
`),{headers:Y,data:I}=f(K,H),J=Y.Path;if(J==="audio.metadata"){let T=$.parseMetadata(I);yield T,$.state.lastDurationOffset=(T.offset||0)+(T.duration||0)}else if(J==="turn.end"){$.state.offsetCompensation=$.state.lastDurationOffset+8750000;break}}else{let K=C;if(K.length<2)throw new Z("Binary message too short for header length");let H=K.readUInt16BE(0);if(H>K.length)throw new Z("Header length greater than data length");let{headers:Y,data:I}=f(K,H);if(Y.Path!=="audio")throw new Z("Binary message path is not audio");let J=Y["Content-Type"];if(!J&&I.length===0)continue;if(J!=="audio/mpeg"&&J!==void 0)throw new Z(`Unexpected Content-Type: ${J}`);if(!J&&I.length>0)throw new Z("No Content-Type but got data");if(I.length===0)throw new Z("Audio data is empty");U=!0,yield{type:"audio",data:I}}}if(!U)throw new y("No audio received from service.")}async*stream(){if(this.state.streamWasCalled)throw Error("stream() can only be called once.");this.state.streamWasCalled=!0;let E=this.options.proxy?new S0(this.options.proxy):void 0,$=`${n}&ConnectionId=${V()}&Sec-MS-GEC=${W.generateSecMsGec()}&Sec-MS-GEC-Version=${R}`;for(let U of this.texts){this.state.partialText=U;let _=0;while(!0)try{let S=new F0($,{headers:W.headersWithMuid(s),agent:E,perMessageDeflate:!1});await new Promise((F,O)=>{S.once("open",F),S.once("error",O)});let N=this.streamInternal(S);for await(let F of N)yield F;S.close();break}catch(S){if(S.name==="UnexpectedServerResponse"&&S.code===403&&_===0)throw S;throw S}}}}function i(E){let $=new Date(E),U=Math.floor(E/3600000),_=$.getUTCMinutes(),S=$.getUTCSeconds(),N=$.getUTCMilliseconds();return`${U.toString().padStart(2,"0")}:${_.toString().padStart(2,"0")}:${S.toString().padStart(2,"0")},${N.toString().padStart(3,"0")}`}class X{cues=[];type=null;feed(E){if(E.type!=="WordBoundary"&&E.type!=="SentenceBoundary")throw Error("Invalid message type, expected 'WordBoundary' or 'SentenceBoundary'.");if(this.type===null)this.type=E.type;else if(this.type!==E.type)throw Error(`Expected message type '${this.type}', but got '${E.type}'.`);if(E.offset===void 0||E.duration===void 0||E.text===void 0)return;let $=E.offset/1e4,U=E.duration/1e4;this.cues.push({index:this.cues.length+1,start:$,end:$+U,content:E.text})}getSrt(){return this.cues.map((E)=>{return`${E.index}
|
|
14
|
+
${i(E.start)} --> ${i(E.end)}
|
|
15
15
|
${E.content}
|
|
16
16
|
|
|
17
|
-
`}).join("")}}import
|
|
17
|
+
`}).join("")}}import o from"axios";import{HttpsProxyAgent as N0}from"https-proxy-agent";async function K0(E){let $=`${k}&Sec-MS-GEC=${W.generateSecMsGec()}&Sec-MS-GEC-Version=${R}`,U=W.headersWithMuid(d),_=E?new N0(E):void 0,S=await o.get($,{headers:U,httpsAgent:_,proxy:!1,validateStatus:(N)=>N<500});if(S.status===403){W.handleClientResponseError(S.headers);let N=`${k}&Sec-MS-GEC=${W.generateSecMsGec()}&Sec-MS-GEC-Version=${R}`;return(await o.get(N,{headers:W.headersWithMuid(d),httpsAgent:_,proxy:!1})).data}if(S.status>=400)throw Error(`Failed to list voices: ${S.status} ${S.statusText}`);return S.data}async function M(E){let $=await K0(E);return $.forEach((U)=>{if(!U.VoiceTag)U.VoiceTag={ContentCategories:[],VoicePersonalities:[]};if(!U.VoiceTag.ContentCategories)U.VoiceTag.ContentCategories=[];if(!U.VoiceTag.VoicePersonalities)U.VoiceTag.VoicePersonalities=[]}),$}class j{voices=[];createCalled=!1;static async create(E){let $=new j,U=E||await M();return $.voices=U.map((_)=>({..._,Language:_.Locale.split("-")[0]??""})),$.createCalled=!0,$}find(E){if(!this.createCalled)throw Error("VoicesManager.find() called before VoicesManager.create()");return this.voices.filter(($)=>{let U=!0;if(E.Gender&&$.Gender!==E.Gender)U=!1;if(E.Locale&&$.Locale!==E.Locale)U=!1;if(E.Language&&$.Language!==E.Language)U=!1;if(E.ShortName&&$.ShortName!==E.ShortName)U=!1;return U})}}var x0={Communicate:G,SubMaker:X,VoicesManager:j,listVoices:M,DRM:W,TTSConfig:L,utils:c};async function H0(E){let{text:$,voice:U="en-US-EmmaMultilingualNeural",rate:_="+0%",volume:S="+0%",pitch:N="+0Hz",boundary:F="SentenceBoundary",proxy:O,connectTimeoutSeconds:r,receiveTimeoutSeconds:C}=E,z=new G($,U,{rate:_,volume:S,pitch:N,boundary:F,proxy:O,connectTimeoutSeconds:r,receiveTimeoutSeconds:C}),K=[];for await(let H of z.stream())if(H.type==="audio"&&H.data)K.push(H.data);return Buffer.concat(K)}async function y0(E){let{outputPath:$,...U}=E,_=await H0(U),S=A.dirname($);if(!w.existsSync(S))w.mkdirSync(S,{recursive:!0});w.writeFileSync($,_)}async function b0(E){let{text:$,voice:U="en-US-EmmaMultilingualNeural",rate:_="+0%",volume:S="+0%",pitch:N="+0Hz",boundary:F="WordBoundary",proxy:O,connectTimeoutSeconds:r,receiveTimeoutSeconds:C,subtitlePath:z}=E,K=new G($,U,{rate:_,volume:S,pitch:N,boundary:F,proxy:O,connectTimeoutSeconds:r,receiveTimeoutSeconds:C}),H=new X,Y=[];for await(let B of K.stream())if(B.type==="audio"&&B.data)Y.push(B.data);else if(B.type==="WordBoundary"||B.type==="SentenceBoundary")H.feed(B);let I=Buffer.concat(Y),J=H.getSrt(),T=A.dirname(z);if(!w.existsSync(T))w.mkdirSync(T,{recursive:!0});return w.writeFileSync(z,J),{audio:I,subtitles:J}}async function v0(E){return M(E)}async function l0(E,$){return(await j.create($?await M($):void 0)).find(E)}async function*C0(E){let{text:$,voice:U="en-US-EmmaMultilingualNeural",rate:_="+0%",volume:S="+0%",pitch:N="+0Hz",boundary:F="SentenceBoundary",proxy:O,connectTimeoutSeconds:r,receiveTimeoutSeconds:C}=E,z=new G($,U,{rate:_,volume:S,pitch:N,boundary:F,proxy:O,connectTimeoutSeconds:r,receiveTimeoutSeconds:C});for await(let K of z.stream())yield K}async function*h0(E){let{text:$,voice:U="en-US-EmmaMultilingualNeural",rate:_="+0%",volume:S="+0%",pitch:N="+0Hz",boundary:F="WordBoundary",proxy:O,connectTimeoutSeconds:r,receiveTimeoutSeconds:C,subtitlePath:z}=E,K=new G($,U,{rate:_,volume:S,pitch:N,boundary:F,proxy:O,connectTimeoutSeconds:r,receiveTimeoutSeconds:C}),H=new X,Y=A.dirname(z);if(!w.existsSync(Y))w.mkdirSync(Y,{recursive:!0});for await(let I of K.stream())if(I.type==="audio"&&I.data)yield I;else if(I.type==="WordBoundary"||I.type==="SentenceBoundary"){H.feed(I);let J=H.getSrt();w.writeFileSync(z,J),yield{...I,subtitles:J}}}async function*c0(E){let{outputPath:$,...U}=E,_=A.dirname($);if(!w.existsSync(_))w.mkdirSync(_,{recursive:!0});let S=w.createWriteStream($),N=0;try{for await(let F of C0(U))if(F.type==="audio"&&F.data)S.write(F.data),N+=F.data.length,yield{bytesWritten:N,chunkSize:F.data.length}}finally{S.end()}}export{h0 as streamSpeechWithSubtitlesToFile,c0 as streamSpeechToFile,C0 as streamSpeech,v0 as getVoices,b0 as generateSpeechWithSubtitlesToFile,y0 as generateSpeechToFile,H0 as generateSpeech,l0 as findVoices,x0 as Experimental_Raw};
|