@readium/speech 0.4.0 → 0.5.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 +8 -4
- package/build/SpeechServer/chunkText.d.ts +6 -0
- package/build/SpeechServer/errors.d.ts +20 -0
- package/build/SpeechServer/index.d.ts +7 -0
- package/build/SpeechServer/selectFormat.d.ts +18 -0
- package/build/SpeechServer/speechServerEngine.d.ts +91 -0
- package/build/SpeechServer/speechServerEngineProvider.d.ts +16 -0
- package/build/SpeechServer/speechServerVoiceMapping.d.ts +3 -0
- package/build/SpeechServer/types.d.ts +56 -0
- package/build/WebSpeech/index.d.ts +0 -1
- package/build/WebSpeech/webSpeechEngineProvider.d.ts +1 -1
- package/build/engine.d.ts +1 -0
- package/build/index.cjs +28 -28
- package/build/index.d.ts +3 -0
- package/build/index.js +1866 -1256
- package/build/navigator.d.ts +1 -1
- package/build/providerRegistry.d.ts +19 -0
- package/build/{WebSpeech/TmpNavigator.d.ts → speechNavigator.d.ts} +6 -6
- package/build/voices/types.d.ts +13 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ The outline of this work has been explored in a [GitHub discussion](https://gith
|
|
|
24
24
|
In the second phase, we focused on implementing a WebSpeech API-based solution with an architecture designed for future extensibility:
|
|
25
25
|
|
|
26
26
|
- **Engine Layer**: Core TTS functionality through `ReadiumSpeechPlaybackEngine`
|
|
27
|
-
- **Navigator Layer**: Content and playback management via
|
|
27
|
+
- **Navigator Layer**: Content and playback management via `ReadiumSpeechNavigator`
|
|
28
28
|
- **Current Implementation**: WebSpeech API with cross-browser compatibility
|
|
29
29
|
- **Future-Proof Design**: Architecture prepared for additional TTS service adapters
|
|
30
30
|
|
|
@@ -32,7 +32,9 @@ Key features include advanced voice selection, cross-browser playback control, f
|
|
|
32
32
|
|
|
33
33
|
In the third phase, we added highlighting: content currently being spoken (e.g. the current word or sentence) can be highlighted as playback progresses. See the [Highlighting guide](docs/Highlighting.md).
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
In the fourth phase, we extracted [Guided Navigation objects](https://readium.org/guided-navigation) from a document (or a fragment of a document), and generated utterances from these objects.
|
|
36
|
+
|
|
37
|
+
We are now on the fifth phase: a second `ReadiumSpeechPlaybackEngine` implementation, backed by [speech-server](https://github.com/readium/speech-server) instead of the browser's Web Speech API.
|
|
36
38
|
|
|
37
39
|
## Demos
|
|
38
40
|
|
|
@@ -78,7 +80,8 @@ yarn add @readium/speech
|
|
|
78
80
|
```typescript
|
|
79
81
|
import {
|
|
80
82
|
WebSpeechVoiceManager,
|
|
81
|
-
|
|
83
|
+
WebSpeechEngine,
|
|
84
|
+
ReadiumSpeechNavigator,
|
|
82
85
|
setupDecorations,
|
|
83
86
|
DecorationStyleType,
|
|
84
87
|
} from "@readium/speech";
|
|
@@ -92,7 +95,7 @@ const voiceManager = await WebSpeechVoiceManager.initialize({
|
|
|
92
95
|
const voice = await voiceManager.getDefaultVoice("en-US");
|
|
93
96
|
|
|
94
97
|
// Create a navigator instance
|
|
95
|
-
const navigator = new
|
|
98
|
+
const navigator = new ReadiumSpeechNavigator(new WebSpeechEngine());
|
|
96
99
|
await navigator.setVoice(voice);
|
|
97
100
|
|
|
98
101
|
const content = document.getElementById("content");
|
|
@@ -137,6 +140,7 @@ Documentation provides guides for:
|
|
|
137
140
|
- [Highlighting](docs/Highlighting.md)
|
|
138
141
|
- [Guided Navigation](docs/GuidedNavigation.md) — extracting [Guided Navigation objects](https://readium.org/guided-navigation) from HTML/XHTML content
|
|
139
142
|
- [Utterance Extraction](docs/UtteranceExtraction.md) — extracting utterances from Guided Navigation objects
|
|
143
|
+
- [Provider Registry](docs/ProviderRegistry.md) — using more than one `ReadiumSpeechEngineProvider` (e.g. WebSpeech and speech-server) side by side
|
|
140
144
|
|
|
141
145
|
## Development
|
|
142
146
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface SpeechServerProblemDetails {
|
|
2
|
+
type: string;
|
|
3
|
+
title: string;
|
|
4
|
+
status: number;
|
|
5
|
+
detail: string;
|
|
6
|
+
instance?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class SpeechServerError extends Error {
|
|
9
|
+
readonly status: number;
|
|
10
|
+
readonly type?: string;
|
|
11
|
+
readonly title?: string;
|
|
12
|
+
readonly instance?: string;
|
|
13
|
+
constructor(message: string, options: {
|
|
14
|
+
status: number;
|
|
15
|
+
type?: string;
|
|
16
|
+
title?: string;
|
|
17
|
+
instance?: string;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export declare function toSpeechServerError(response: Response): Promise<SpeechServerError>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SpeechServerAudioFormat } from './types';
|
|
2
|
+
export type CanPlayTypeResult = "probably" | "maybe" | "";
|
|
3
|
+
export type CanPlayType = (mime: string) => CanPlayTypeResult;
|
|
4
|
+
export declare function mimeTypeForFormat(format: string): string;
|
|
5
|
+
export interface SpeechServerFormatOptions {
|
|
6
|
+
preferredFormat?: SpeechServerAudioFormat | (string & {});
|
|
7
|
+
strategy?: "quality" | "bandwidth";
|
|
8
|
+
adaptBitrateToNetwork?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function selectFormat(output: {
|
|
11
|
+
formats: string[];
|
|
12
|
+
default: string;
|
|
13
|
+
}, options: Pick<SpeechServerFormatOptions, "preferredFormat" | "strategy">, canPlay: CanPlayType): string;
|
|
14
|
+
export interface NetworkInfo {
|
|
15
|
+
saveData?: boolean;
|
|
16
|
+
effectiveType?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function selectBitrate(format: string, adaptBitrateToNetwork: boolean, network: NetworkInfo | undefined): number | undefined;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { ReadiumSpeechPlaybackEngine } from '../engine';
|
|
2
|
+
import { ReadiumSpeechPlaybackEvent, ReadiumSpeechPlaybackState } from '../navigator';
|
|
3
|
+
import { ReadiumSpeechUtterance } from '../utterance';
|
|
4
|
+
import { ReadiumSpeechVoice } from '../voices/types';
|
|
5
|
+
import { SpeechServerFormatOptions } from './selectFormat';
|
|
6
|
+
export interface SpeechServerEndpoints {
|
|
7
|
+
voices: string;
|
|
8
|
+
synthesize: string;
|
|
9
|
+
service: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SpeechServerEngineOptions {
|
|
12
|
+
endpoints: SpeechServerEndpoints;
|
|
13
|
+
fetch?: typeof fetch;
|
|
14
|
+
prefetchWindow?: number;
|
|
15
|
+
readyBufferChars?: number;
|
|
16
|
+
overLengthText?: "split" | "error";
|
|
17
|
+
format?: SpeechServerFormatOptions;
|
|
18
|
+
}
|
|
19
|
+
export declare class SpeechServerEngine implements ReadiumSpeechPlaybackEngine {
|
|
20
|
+
private endpoints;
|
|
21
|
+
private fetchImpl;
|
|
22
|
+
private currentVoice;
|
|
23
|
+
private voices;
|
|
24
|
+
private serviceInfo;
|
|
25
|
+
private serviceInfoPromise;
|
|
26
|
+
private currentUtterances;
|
|
27
|
+
private currentUtteranceIndex;
|
|
28
|
+
private playbackState;
|
|
29
|
+
private eventListeners;
|
|
30
|
+
private speakInContentLanguage;
|
|
31
|
+
private speakGeneration;
|
|
32
|
+
private loadGeneration;
|
|
33
|
+
private readonly prefetchWindow;
|
|
34
|
+
private readonly readyBufferChars;
|
|
35
|
+
private readonly overLengthText;
|
|
36
|
+
private readonly formatOptions;
|
|
37
|
+
private readonly canPlayType;
|
|
38
|
+
private prefetchCache;
|
|
39
|
+
private prefetchChainTail;
|
|
40
|
+
private audioContext;
|
|
41
|
+
private masterGain;
|
|
42
|
+
private scheduledChunks;
|
|
43
|
+
private boundaryRafHandle;
|
|
44
|
+
private rate;
|
|
45
|
+
private pitch;
|
|
46
|
+
private volume;
|
|
47
|
+
constructor(options: SpeechServerEngineOptions);
|
|
48
|
+
setAvailableVoices(voices: ReadiumSpeechVoice[]): void;
|
|
49
|
+
loadUtterances(contents: ReadiumSpeechUtterance[]): void;
|
|
50
|
+
private bufferUntilReady;
|
|
51
|
+
private indexCoveringChars;
|
|
52
|
+
setVoice(voice: ReadiumSpeechVoice | string): void;
|
|
53
|
+
getCurrentVoice(): ReadiumSpeechVoice | null;
|
|
54
|
+
getAvailableVoices(): Promise<ReadiumSpeechVoice[]>;
|
|
55
|
+
private getServiceInfo;
|
|
56
|
+
private fetchServiceInfo;
|
|
57
|
+
setSpeakInContentLanguage(enabled: boolean): void;
|
|
58
|
+
getSpeakInContentLanguage(): boolean;
|
|
59
|
+
speak(utteranceIndex?: number): void;
|
|
60
|
+
private synthesizeAndPlay;
|
|
61
|
+
private resolveSynthesisStream;
|
|
62
|
+
private fillPrefetchWindow;
|
|
63
|
+
private queuePrefetch;
|
|
64
|
+
private clearPrefetchCache;
|
|
65
|
+
private synthesizeStream;
|
|
66
|
+
private synthesizeChunk;
|
|
67
|
+
private ensureAudioContext;
|
|
68
|
+
private scheduleChunksStreaming;
|
|
69
|
+
private handleUtteranceEnded;
|
|
70
|
+
private startBoundaryPolling;
|
|
71
|
+
private stopBoundaryPolling;
|
|
72
|
+
private checkBoundaries;
|
|
73
|
+
private stopAudio;
|
|
74
|
+
pause(): void;
|
|
75
|
+
resume(): void;
|
|
76
|
+
stop(): void;
|
|
77
|
+
setRate(rate: number): void;
|
|
78
|
+
getRate(): number;
|
|
79
|
+
setPitch(pitch: number): void;
|
|
80
|
+
getPitch(): number;
|
|
81
|
+
setVolume(volume: number): void;
|
|
82
|
+
getVolume(): number;
|
|
83
|
+
getState(): ReadiumSpeechPlaybackState;
|
|
84
|
+
getCurrentUtteranceIndex(): number;
|
|
85
|
+
setCurrentUtteranceIndex(index: number, onComplete?: (success: boolean) => void): void;
|
|
86
|
+
getUtteranceCount(): number;
|
|
87
|
+
on(event: ReadiumSpeechPlaybackEvent["type"], callback: (event: ReadiumSpeechPlaybackEvent) => void): () => void;
|
|
88
|
+
private emitEvent;
|
|
89
|
+
private setState;
|
|
90
|
+
destroy(): Promise<void>;
|
|
91
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ReadiumSpeechEngineProvider } from '../provider';
|
|
2
|
+
import { ReadiumSpeechPlaybackEngine } from '../engine';
|
|
3
|
+
import { ReadiumSpeechVoice } from '../voices/types';
|
|
4
|
+
import { SpeechServerEngineOptions } from './speechServerEngine';
|
|
5
|
+
export type SpeechServerEngineProviderOptions = SpeechServerEngineOptions;
|
|
6
|
+
export declare class SpeechServerEngineProvider implements ReadiumSpeechEngineProvider {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly name: string;
|
|
9
|
+
private options;
|
|
10
|
+
private fetchImpl;
|
|
11
|
+
private voices;
|
|
12
|
+
constructor(options: SpeechServerEngineProviderOptions);
|
|
13
|
+
getVoices(): Promise<ReadiumSpeechVoice[]>;
|
|
14
|
+
createEngine(voice?: ReadiumSpeechVoice | string): Promise<ReadiumSpeechPlaybackEngine>;
|
|
15
|
+
destroy(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { TGender, TQuality, TServerVoiceControls } from '../voices/types';
|
|
2
|
+
export interface SpeechServerVoice {
|
|
3
|
+
name: string;
|
|
4
|
+
originalName: string;
|
|
5
|
+
provider: string;
|
|
6
|
+
identifier: string;
|
|
7
|
+
language: string;
|
|
8
|
+
otherLanguages?: string[];
|
|
9
|
+
gender?: TGender | null;
|
|
10
|
+
quality?: TQuality;
|
|
11
|
+
controls?: TServerVoiceControls;
|
|
12
|
+
}
|
|
13
|
+
export interface SpeechServerTimingMark {
|
|
14
|
+
name: "word" | "sentence";
|
|
15
|
+
charIndex: number;
|
|
16
|
+
charLength: number;
|
|
17
|
+
elapsedTime: number;
|
|
18
|
+
}
|
|
19
|
+
export type SpeechServerAudioFormat = "wav" | "mp3" | "opus" | "aac" | "flac" | "ogg" | "webm" | "m4a";
|
|
20
|
+
export interface SpeechServerSynthesizeRequest {
|
|
21
|
+
id?: string;
|
|
22
|
+
text: string;
|
|
23
|
+
ssml?: boolean;
|
|
24
|
+
language?: string;
|
|
25
|
+
voice?: string;
|
|
26
|
+
prev_utterance?: string;
|
|
27
|
+
next_utterance?: string;
|
|
28
|
+
publication_id?: string;
|
|
29
|
+
boundary?: boolean;
|
|
30
|
+
output?: {
|
|
31
|
+
format?: SpeechServerAudioFormat;
|
|
32
|
+
bitrate?: number | null;
|
|
33
|
+
sample_rate?: number | null;
|
|
34
|
+
speed?: number;
|
|
35
|
+
pitch?: number | null;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export interface SpeechServerSynthesizeBoundaryResponse {
|
|
39
|
+
audio: string;
|
|
40
|
+
format: SpeechServerAudioFormat;
|
|
41
|
+
boundaries: SpeechServerTimingMark[] | null;
|
|
42
|
+
}
|
|
43
|
+
export interface SpeechServerServiceInfo {
|
|
44
|
+
output: {
|
|
45
|
+
formats: SpeechServerAudioFormat[];
|
|
46
|
+
default: SpeechServerAudioFormat;
|
|
47
|
+
};
|
|
48
|
+
limits: {
|
|
49
|
+
maxTextLength: number;
|
|
50
|
+
maxConcurrentSyntheses: number;
|
|
51
|
+
};
|
|
52
|
+
providers: {
|
|
53
|
+
id: string;
|
|
54
|
+
installedLanguages: string[];
|
|
55
|
+
}[];
|
|
56
|
+
}
|
|
@@ -4,7 +4,7 @@ import { ReadiumSpeechVoice } from '../voices/types';
|
|
|
4
4
|
export declare class WebSpeechEngineProvider implements ReadiumSpeechEngineProvider {
|
|
5
5
|
readonly id: string;
|
|
6
6
|
readonly name: string;
|
|
7
|
-
private
|
|
7
|
+
private voiceEngine;
|
|
8
8
|
getVoices(): Promise<ReadiumSpeechVoice[]>;
|
|
9
9
|
createEngine(voice?: ReadiumSpeechVoice | string): Promise<ReadiumSpeechPlaybackEngine>;
|
|
10
10
|
destroy(): Promise<void>;
|
package/build/engine.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { ReadiumSpeechPlaybackEvent, ReadiumSpeechPlaybackState } from './naviga
|
|
|
2
2
|
import { ReadiumSpeechUtterance } from './utterance';
|
|
3
3
|
import { ReadiumSpeechVoice } from './voices/types';
|
|
4
4
|
export interface ReadiumSpeechPlaybackEngine {
|
|
5
|
+
initialize?(): Promise<unknown>;
|
|
5
6
|
loadUtterances(contents: ReadiumSpeechUtterance[]): void;
|
|
6
7
|
setVoice(voice: ReadiumSpeechVoice | string): void;
|
|
7
8
|
getCurrentVoice(): ReadiumSpeechVoice | null;
|