@readium/speech 0.8.1 → 0.9.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 +10 -1
- package/build/SpeechServer/speechServerEngine.d.ts +5 -0
- package/build/WebSpeech/webSpeechEngine.d.ts +2 -0
- package/build/decorator/createLocator.d.ts +8 -4
- package/build/gnd/a11y.d.ts +2 -0
- package/build/gnd/converter.d.ts +35 -17
- package/build/gnd/dom.d.ts +1 -0
- package/build/gnd/domRangeGenerator.d.ts +9 -0
- package/build/gnd/elementHandlers.d.ts +5 -0
- package/build/gnd/idAllocator.d.ts +6 -0
- package/build/gnd/index.d.ts +3 -0
- package/build/gnd/makeGnd.d.ts +2 -1
- package/build/gnd/options.d.ts +15 -0
- package/build/gnd/prescan.d.ts +1 -0
- package/build/gnd/roles.d.ts +1 -6
- package/build/gnd/selectorGenerator.d.ts +2 -0
- package/build/gnd/textFragmentGenerator.d.ts +2 -0
- package/build/gnd/textrefFragment.d.ts +38 -0
- package/build/index.cjs +35 -35
- package/build/index.js +5076 -2028
- package/build/navigator.d.ts +1 -1
- package/build/preferences/Configurable.d.ts +1 -1
- package/build/preferences/index.d.ts +1 -1
- package/build/preferences/verbosityTables.d.ts +7 -1
- package/build/speechNavigator.d.ts +11 -2
- package/build/utils/clamp.d.ts +1 -0
- package/build/utterance.d.ts +3 -0
- package/build/utterances/contextualizations.d.ts +3 -0
- package/build/utterances/extractUtterances.d.ts +3 -3
- package/build/utterances/index.d.ts +2 -2
- package/build/utterances/roles.d.ts +8 -0
- package/build/utterances/tableStructure.d.ts +9 -0
- package/build/utterances/types.d.ts +11 -10
- package/package.json +8 -4
- package/build/utterances/announcements.d.ts +0 -2
package/README.md
CHANGED
|
@@ -51,7 +51,11 @@ We are now on the sixth phase: verbosity and prosody, in particular contextualiz
|
|
|
51
51
|
|
|
52
52
|
### [In-context demo](https://readium.org/speech/demo/article)
|
|
53
53
|
|
|
54
|
-
In-context reading with seamless voice selection (grouped by region and sorted based on quality), and playback control, providing an optional read-along experience that integrates naturally with the content.
|
|
54
|
+
In-context reading with seamless voice selection (grouped by region and sorted based on quality), and playback control, providing an optional read-along experience that integrates naturally with the content.
|
|
55
|
+
|
|
56
|
+
Settings include a verbosity selector (none/few/some/most) demonstrating [contextualization](docs/Preferences.md) — synthesized announcements spoken around content based on its role (entering/leaving a section, a footnote, a pullquote…) — and, for the read-along experience, independent highlight styles (highlight, underline, strikethrough, outline, text color, mask) and colors for the current utterance and the current word.
|
|
57
|
+
|
|
58
|
+
The panel alongside the article shows the [Guided Navigation](docs/GuidedNavigation.md) object and the [utterances](docs/UtteranceExtraction.md) extracted from it, live.
|
|
55
59
|
|
|
56
60
|
### [Extraction playground](https://readium.org/speech/demo/playground)
|
|
57
61
|
|
|
@@ -144,6 +148,11 @@ Documentation provides guides for:
|
|
|
144
148
|
- [Guided Navigation](docs/GuidedNavigation.md) — extracting [Guided Navigation objects](https://readium.org/guided-navigation) from HTML/XHTML content
|
|
145
149
|
- [Utterance Extraction](docs/UtteranceExtraction.md) — extracting utterances from Guided Navigation objects
|
|
146
150
|
- [Provider Registry](docs/ProviderRegistry.md) — using more than one `ReadiumSpeechEngineProvider` (e.g. WebSpeech and speech-server) side by side
|
|
151
|
+
- [WebSpeechEngine](docs/WebSpeechEngine.md) — the `ReadiumSpeechPlaybackEngine` backed by the browser's Web Speech API
|
|
152
|
+
- [SpeechServerEngine](docs/SpeechServerEngine.md) — the `ReadiumSpeechPlaybackEngine` backed by a remote [Readium Speech Server](https://github.com/readium/speech-server) instance
|
|
153
|
+
- [FallbackEngine](docs/FallbackEngine.md) — pairing a primary and fallback engine so playback swaps transparently when one is unreachable or stalls
|
|
154
|
+
|
|
155
|
+
See [CHANGELOG.md](CHANGELOG.md) for what's new in each release.
|
|
147
156
|
|
|
148
157
|
## Development
|
|
149
158
|
|
|
@@ -40,6 +40,9 @@ export declare class SpeechServerEngine implements ReadiumSpeechPlaybackEngine {
|
|
|
40
40
|
private prefetchCache;
|
|
41
41
|
private prefetchChainTail;
|
|
42
42
|
private activeControllers;
|
|
43
|
+
private liveControllers;
|
|
44
|
+
private isSpeakingInternal;
|
|
45
|
+
private restartPending;
|
|
43
46
|
private audioContext;
|
|
44
47
|
private masterGain;
|
|
45
48
|
private scheduledChunks;
|
|
@@ -66,6 +69,7 @@ export declare class SpeechServerEngine implements ReadiumSpeechPlaybackEngine {
|
|
|
66
69
|
private fillPrefetchWindow;
|
|
67
70
|
private queuePrefetch;
|
|
68
71
|
private clearPrefetchCache;
|
|
72
|
+
private abortLiveControllers;
|
|
69
73
|
private synthesizeStream;
|
|
70
74
|
private synthesizeChunk;
|
|
71
75
|
private ensureAudioContext;
|
|
@@ -85,6 +89,7 @@ export declare class SpeechServerEngine implements ReadiumSpeechPlaybackEngine {
|
|
|
85
89
|
getPitch(): number;
|
|
86
90
|
setVolume(volume: number): void;
|
|
87
91
|
getVolume(): number;
|
|
92
|
+
private scheduleRestartIfSpeaking;
|
|
88
93
|
getState(): ReadiumSpeechPlaybackState;
|
|
89
94
|
getCurrentUtteranceIndex(): number;
|
|
90
95
|
setCurrentUtteranceIndex(index: number, onComplete?: (success: boolean) => void): void;
|
|
@@ -19,6 +19,7 @@ export declare class WebSpeechEngine implements ReadiumSpeechPlaybackEngine {
|
|
|
19
19
|
private speakGeneration;
|
|
20
20
|
private resumeInfinityTimer?;
|
|
21
21
|
private isSpeakingInternal;
|
|
22
|
+
private restartPending;
|
|
22
23
|
private isPausedInternal;
|
|
23
24
|
private isAndroidPaused;
|
|
24
25
|
private pausedAtUtteranceIndex;
|
|
@@ -66,6 +67,7 @@ export declare class WebSpeechEngine implements ReadiumSpeechPlaybackEngine {
|
|
|
66
67
|
getPitch(): number;
|
|
67
68
|
setVolume(volume: number): void;
|
|
68
69
|
getVolume(): number;
|
|
70
|
+
private scheduleRestartIfSpeaking;
|
|
69
71
|
getState(): ReadiumSpeechPlaybackState;
|
|
70
72
|
getCurrentUtteranceIndex(): number;
|
|
71
73
|
setCurrentUtteranceIndex(index: number, onComplete?: (success: boolean) => void): void;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { Locator } from '@readium/shared';
|
|
2
|
+
import { DomRangeJSON } from '../gnd/textrefFragment.js';
|
|
2
3
|
export interface LocatorOptions {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
text?: {
|
|
5
|
+
highlight?: string;
|
|
6
|
+
before?: string;
|
|
7
|
+
after?: string;
|
|
8
|
+
};
|
|
9
|
+
cssSelector?: string;
|
|
10
|
+
domRange?: DomRangeJSON;
|
|
7
11
|
fragment?: string;
|
|
8
12
|
}
|
|
9
13
|
export declare function createLocator(options: LocatorOptions, wnd?: Window): Locator;
|
package/build/gnd/a11y.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { GndText } from './types.js';
|
|
2
2
|
/** Normalized (whitespace-coalesced and trimmed) text content of a node's subtree. */
|
|
3
3
|
export declare function normalizedNodeText(el: Node): string;
|
|
4
|
+
/** Same as `normalizedNodeText`, excluding explicitly-role-bearing descendants. */
|
|
5
|
+
export declare function normalizedNodeTextExcludingExplicitRoles(el: Node): string;
|
|
4
6
|
/**
|
|
5
7
|
* Computes the text that becomes a node's `GndObject.description`, and
|
|
6
8
|
* whether the node is visible in the first place. Follows the AccName
|
package/build/gnd/converter.d.ts
CHANGED
|
@@ -1,26 +1,36 @@
|
|
|
1
|
-
import { GndObject } from './types.js';
|
|
1
|
+
import { GndObject, GndRole } from './types.js';
|
|
2
|
+
import { ObjBuilder } from './object.js';
|
|
2
3
|
import { GndMediaType } from './dom.js';
|
|
4
|
+
import { GndGenerationOptions } from './options.js';
|
|
5
|
+
import { IdAllocator } from './idAllocator.js';
|
|
3
6
|
/** Walks a DOM subtree, building the Guided Navigation object tree. */
|
|
4
7
|
export declare class Converter {
|
|
5
8
|
xmlParsed: boolean;
|
|
6
9
|
ids: Map<string, Element>;
|
|
7
10
|
suppressed: Set<Element>;
|
|
8
|
-
idAlloc:
|
|
9
|
-
claimed: Set<string>;
|
|
10
|
-
counters: Map<string, number>;
|
|
11
|
-
};
|
|
11
|
+
idAlloc: IdAllocator;
|
|
12
12
|
noterefDepth: number;
|
|
13
13
|
allowNode: Element | null;
|
|
14
|
+
selectorPredicate: ((roles: GndRole[]) => boolean) | null;
|
|
15
|
+
domRangeEnabled: boolean;
|
|
16
|
+
textFragmentEnabled: boolean;
|
|
17
|
+
docRoot: Document | null;
|
|
14
18
|
private root;
|
|
15
19
|
private current;
|
|
20
|
+
private foldedCaptions;
|
|
16
21
|
private segments;
|
|
17
22
|
private textAcc;
|
|
18
23
|
private currentCtx;
|
|
19
24
|
private flowEndsWithSpace;
|
|
20
25
|
private pendingChildren;
|
|
26
|
+
private flowFirstNode;
|
|
27
|
+
private flowFirstOffset;
|
|
28
|
+
private flowLastNode;
|
|
29
|
+
private flowLastOffset;
|
|
30
|
+
private lastFlowRange;
|
|
31
|
+
private lastFlowText;
|
|
21
32
|
constructor(xmlParsed: boolean);
|
|
22
|
-
|
|
23
|
-
private claimId;
|
|
33
|
+
spawnChild(allowNode: Element, depthDelta?: number): Converter;
|
|
24
34
|
prescan(root: Element): void;
|
|
25
35
|
convert(root: Element): void;
|
|
26
36
|
convertChildren(root: Element): void;
|
|
@@ -29,24 +39,32 @@ export declare class Converter {
|
|
|
29
39
|
private appendChild;
|
|
30
40
|
private walk;
|
|
31
41
|
private head;
|
|
42
|
+
private implicitCaptionOf;
|
|
32
43
|
private tail;
|
|
44
|
+
private applyTextref;
|
|
33
45
|
private text;
|
|
34
46
|
private textContext;
|
|
35
47
|
private updateFlowSpace;
|
|
36
48
|
private closeSegment;
|
|
37
49
|
private resetFlow;
|
|
38
|
-
|
|
39
|
-
private pagebreak;
|
|
40
|
-
private noteref;
|
|
41
|
-
private link;
|
|
50
|
+
placeholder(el: Element, tag: string, object: ObjBuilder, candidateID?: string): void;
|
|
42
51
|
private flushText;
|
|
43
52
|
}
|
|
44
53
|
/**
|
|
45
54
|
* Converts an HTML or XHTML fragment or document into Guided Navigation
|
|
46
|
-
* objects
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
55
|
+
* objects.
|
|
56
|
+
*
|
|
57
|
+
* Given a string, `input` is parsed into a detached document that's never
|
|
58
|
+
* seen again — `options.textrefs.domRange` has nothing to resolve back
|
|
59
|
+
* against there, so it's ignored. Reflects exactly the input it's given: a
|
|
60
|
+
* real, author-written <body> becomes its own role: ["body"] node like any
|
|
61
|
+
* other element; a <body> synthesized only by text/html parsing around a
|
|
62
|
+
* bodyless fragment is not content and is skipped through; a bodyless XHTML
|
|
63
|
+
* fragment's root element is itself the content.
|
|
64
|
+
*
|
|
65
|
+
* Given a live, already-rendered element instead, it's converted in place —
|
|
66
|
+
* no parsing, no detached copy — so `domRange` can pinpoint exact text
|
|
67
|
+
* nodes a DOM-highlighting consumer can resolve straight back against that
|
|
68
|
+
* same document.
|
|
51
69
|
*/
|
|
52
|
-
export declare function parseMarkup(input: string, mediaType?: GndMediaType): GndObject[];
|
|
70
|
+
export declare function parseMarkup(input: string | Element, mediaType?: GndMediaType, options?: GndGenerationOptions): GndObject[];
|
package/build/gnd/dom.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export declare function nodeLanguage(el: Element | null): string;
|
|
2
2
|
export declare function hasElementChild(el: Element): boolean;
|
|
3
3
|
export declare function isAncestorOf(anc: Element, n: Element): boolean;
|
|
4
|
+
export declare function isInlineTag(tagName: string): boolean;
|
|
4
5
|
export type GndMediaType = "text/html" | "application/xhtml+xml";
|
|
5
6
|
export declare function sniffMediaType(input: string): GndMediaType;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DomRangeJSON } from './textrefFragment.js';
|
|
2
|
+
export interface KnownSelector {
|
|
3
|
+
el: Element;
|
|
4
|
+
selector: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function generateDomRange(range: {
|
|
7
|
+
first: [Text, number];
|
|
8
|
+
last: [Text, number];
|
|
9
|
+
}, docRoot: Document | null, known?: KnownSelector): DomRangeJSON | undefined;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { GndRole, GndText } from './types.js';
|
|
2
|
+
import { Converter } from './converter.js';
|
|
3
|
+
export declare function pagebreak(converter: Converter, el: Element, aria: GndText | null, roles: GndRole[]): boolean;
|
|
4
|
+
export declare function noteref(converter: Converter, el: Element, roles: GndRole[]): void;
|
|
5
|
+
export declare function link(converter: Converter, el: Element, roles: GndRole[], aria: GndText | null): void;
|
package/build/gnd/index.d.ts
CHANGED
|
@@ -2,3 +2,6 @@ export type { GndRole, GndText, GndObject, GndDocument } from './types.js';
|
|
|
2
2
|
export { makeGnd } from './makeGnd.js';
|
|
3
3
|
export { parseMarkup } from './converter.js';
|
|
4
4
|
export type { GndMediaType } from './dom.js';
|
|
5
|
+
export type { GndGenerationOptions, TextrefOptions } from './options.js';
|
|
6
|
+
export { encodeCssSelectorFragment, decodeCssSelectorFragment, encodeDomRangeFragment, decodeDomRangeFragment, decodeTextref, } from './textrefFragment.js';
|
|
7
|
+
export type { DomRangeJSON } from './textrefFragment.js';
|
package/build/gnd/makeGnd.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { GndDocument } from './types.js';
|
|
2
2
|
import { GndMediaType } from './dom.js';
|
|
3
|
+
import { GndGenerationOptions } from './options.js';
|
|
3
4
|
export type { GndMediaType };
|
|
4
5
|
/**
|
|
5
6
|
* Builds a Guided Navigation document from an HTML or XHTML fragment or
|
|
6
7
|
* document, following https://github.com/readium/guided-navigation.
|
|
7
8
|
*/
|
|
8
|
-
export declare function makeGnd(input: string, mediaType?: GndMediaType): GndDocument;
|
|
9
|
+
export declare function makeGnd(input: string | Element, mediaType?: GndMediaType, options?: GndGenerationOptions): GndDocument;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { GndRole } from './types.js';
|
|
2
|
+
export interface TextrefOptions {
|
|
3
|
+
roles?: boolean | GndRole[];
|
|
4
|
+
domRange?: boolean;
|
|
5
|
+
textFragment?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface GndGenerationOptions {
|
|
8
|
+
textrefs?: boolean | GndRole[] | TextrefOptions;
|
|
9
|
+
}
|
|
10
|
+
export interface NormalizedTextrefOptions {
|
|
11
|
+
predicate: ((roles: GndRole[]) => boolean) | null;
|
|
12
|
+
domRange: boolean;
|
|
13
|
+
textFragment: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function normalizeTextrefOptions(opt: GndGenerationOptions["textrefs"]): NormalizedTextrefOptions;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function prescan(root: Element, ids: Map<string, Element>, suppressed: Set<Element>): void;
|
package/build/gnd/roles.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
1
|
import { GndRole } from './types.js';
|
|
2
|
-
|
|
3
|
-
* Determines the Guided Navigation roles of an element, combining the roles
|
|
4
|
-
* derived from the element type itself with the ones from its ARIA `role` and
|
|
5
|
-
* `epub:type` attributes, e.g. `<section epub:type="chapter">` -> `[section, chapter]`.
|
|
6
|
-
* An ARIA role of "presentation"/"none" strips the element of its native semantics.
|
|
7
|
-
*/
|
|
2
|
+
export declare function hasExplicitRole(el: Element): boolean;
|
|
8
3
|
export declare function extractNodeRoles(el: Element): GndRole[];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export declare function encodeCssSelectorFragment(selector: string): string;
|
|
2
|
+
export declare function decodeCssSelectorFragment(textref: string | undefined): string | undefined;
|
|
3
|
+
export interface DomRangeJSON {
|
|
4
|
+
start: {
|
|
5
|
+
cssSelector: string;
|
|
6
|
+
textNodeIndex: number;
|
|
7
|
+
charOffset?: number;
|
|
8
|
+
};
|
|
9
|
+
end?: {
|
|
10
|
+
cssSelector: string;
|
|
11
|
+
textNodeIndex: number;
|
|
12
|
+
charOffset?: number;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export declare function encodeDomRangeFragment(domRange: DomRangeJSON): string;
|
|
16
|
+
export declare function decodeDomRangeFragment(textref: string | undefined): DomRangeJSON | undefined;
|
|
17
|
+
export interface TextFragmentDirective {
|
|
18
|
+
textStart: string;
|
|
19
|
+
textEnd?: string;
|
|
20
|
+
prefix?: string;
|
|
21
|
+
suffix?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function encodeTextFragmentDirective(fragment: TextFragmentDirective): string;
|
|
24
|
+
export declare function decodeTextFragmentDirective(textref: string | undefined): TextFragmentDirective | undefined;
|
|
25
|
+
export interface DecodedTextref {
|
|
26
|
+
cssSelector?: string;
|
|
27
|
+
domRange?: DomRangeJSON;
|
|
28
|
+
text?: {
|
|
29
|
+
highlight?: string;
|
|
30
|
+
before?: string;
|
|
31
|
+
after?: string;
|
|
32
|
+
};
|
|
33
|
+
fragment?: string;
|
|
34
|
+
}
|
|
35
|
+
export declare function decodeTextref(node: {
|
|
36
|
+
id?: string;
|
|
37
|
+
textref?: string;
|
|
38
|
+
} | undefined): DecodedTextref | undefined;
|