@ssml-builder-js/azure-tts-client 2.5.0 → 2.7.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/CHANGELOG.md +8 -0
- package/package.json +1 -1
- package/test/synthesis.test.ts +100 -0
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test, { type TestContext } from "node:test";
|
|
3
|
+
import * as SpeechSDK from "microsoft-cognitiveservices-speech-sdk";
|
|
4
|
+
import { synthesizeSpeech } from "../src/index.ts";
|
|
5
|
+
|
|
6
|
+
const endpoint = "https://speech.example.test/cognitiveservices/v1";
|
|
7
|
+
const subscriptionKey = "subscription-key";
|
|
8
|
+
const region = "japaneast";
|
|
9
|
+
|
|
10
|
+
function installHangingSynthesisMock(
|
|
11
|
+
testContext: TestContext,
|
|
12
|
+
onResult: (callback: (result: SpeechSDK.SpeechSynthesisResult) => void) => void,
|
|
13
|
+
onClose: () => void,
|
|
14
|
+
): void {
|
|
15
|
+
const originalFromEndpoint = SpeechSDK.SpeechConfig.fromEndpoint;
|
|
16
|
+
testContext.mock.method(SpeechSDK.SpeechConfig, "fromEndpoint", (speechEndpoint, key) =>
|
|
17
|
+
originalFromEndpoint(speechEndpoint, String(key)),
|
|
18
|
+
);
|
|
19
|
+
testContext.mock.method(SpeechSDK.SpeechSynthesizer.prototype, "speakSsmlAsync", (_ssml, callback) => {
|
|
20
|
+
if (callback) onResult(callback);
|
|
21
|
+
});
|
|
22
|
+
testContext.mock.method(SpeechSDK.SpeechSynthesizer.prototype, "close", onClose);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
test("synthesizeSpeech aborts the SDK request and settles its promise", async (t) => {
|
|
26
|
+
const controller = new AbortController();
|
|
27
|
+
let closeCount = 0;
|
|
28
|
+
let resultCallback: ((result: SpeechSDK.SpeechSynthesisResult) => void) | undefined;
|
|
29
|
+
installHangingSynthesisMock(
|
|
30
|
+
t,
|
|
31
|
+
(callback) => (resultCallback = callback),
|
|
32
|
+
() => (closeCount += 1),
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const promise = synthesizeSpeech("<speak>Hello</speak>", {
|
|
36
|
+
endpoint,
|
|
37
|
+
subscriptionKey,
|
|
38
|
+
region,
|
|
39
|
+
signal: controller.signal,
|
|
40
|
+
});
|
|
41
|
+
controller.abort();
|
|
42
|
+
|
|
43
|
+
await assert.rejects(promise, /Speech synthesis was cancelled/);
|
|
44
|
+
assert.equal(closeCount, 1);
|
|
45
|
+
|
|
46
|
+
resultCallback?.({
|
|
47
|
+
audioData: new ArrayBuffer(1),
|
|
48
|
+
errorDetails: "",
|
|
49
|
+
reason: SpeechSDK.ResultReason.SynthesizingAudioCompleted,
|
|
50
|
+
} as SpeechSDK.SpeechSynthesisResult);
|
|
51
|
+
assert.equal(closeCount, 1);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("synthesizeSpeech aborts the SDK request on timeout and settles its promise", async (t) => {
|
|
55
|
+
let closeCount = 0;
|
|
56
|
+
let resultCallback: ((result: SpeechSDK.SpeechSynthesisResult) => void) | undefined;
|
|
57
|
+
installHangingSynthesisMock(
|
|
58
|
+
t,
|
|
59
|
+
(callback) => (resultCallback = callback),
|
|
60
|
+
() => (closeCount += 1),
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const promise = synthesizeSpeech("<speak>Hello</speak>", {
|
|
64
|
+
endpoint,
|
|
65
|
+
subscriptionKey,
|
|
66
|
+
region,
|
|
67
|
+
timeoutMs: 10,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
await assert.rejects(promise, /Speech synthesis timed out after 10 ms/);
|
|
71
|
+
assert.equal(closeCount, 1);
|
|
72
|
+
|
|
73
|
+
resultCallback?.({
|
|
74
|
+
audioData: new ArrayBuffer(1),
|
|
75
|
+
errorDetails: "",
|
|
76
|
+
reason: SpeechSDK.ResultReason.SynthesizingAudioCompleted,
|
|
77
|
+
} as SpeechSDK.SpeechSynthesisResult);
|
|
78
|
+
assert.equal(closeCount, 1);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const azureKey = process.env.AZURE_SPEECH_KEY;
|
|
82
|
+
const azureRegion = process.env.AZURE_SPEECH_REGION;
|
|
83
|
+
|
|
84
|
+
test("synthesizeSpeech reaches the Azure Speech API when credentials are configured", {
|
|
85
|
+
skip: !azureKey || !azureRegion,
|
|
86
|
+
timeout: 60_000,
|
|
87
|
+
}, async () => {
|
|
88
|
+
if (!azureKey || !azureRegion) return;
|
|
89
|
+
|
|
90
|
+
const audio = await synthesizeSpeech(
|
|
91
|
+
'<speak version="1.0" xml:lang="en-US"><voice name="en-US-JennyNeural">Connectivity check.</voice></speak>',
|
|
92
|
+
{
|
|
93
|
+
subscriptionKey: azureKey,
|
|
94
|
+
region: azureRegion,
|
|
95
|
+
timeoutMs: 30_000,
|
|
96
|
+
},
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
assert.ok(audio.byteLength > 0);
|
|
100
|
+
});
|