@readium/speech 0.5.0 → 0.6.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.
@@ -1,3 +1,7 @@
1
+ import { GndObject } from './gnd/types';
2
+ import { Configurable } from './preferences/Configurable';
3
+ import { SpeechPreferences } from './preferences/SpeechPreferences';
4
+ import { SpeechSettings } from './preferences/SpeechSettings';
1
5
  import { ReadiumSpeechVoice } from './voices/types';
2
6
  import { ReadiumSpeechUtterance } from './utterance';
3
7
  export type ReadiumSpeechPlaybackState = "playing" | "paused" | "idle" | "loading" | "ready";
@@ -5,13 +9,14 @@ export interface ReadiumSpeechPlaybackEvent {
5
9
  type: "start" | "pause" | "resume" | "end" | "stop" | "skip" | "error" | "boundary" | "mark" | "idle" | "loading" | "ready" | "voiceschanged" | "languagefallback";
6
10
  detail?: any;
7
11
  }
8
- export interface ReadiumSpeechNavigatorContract {
12
+ export interface ReadiumSpeechNavigatorContract extends Configurable<SpeechSettings, SpeechPreferences> {
9
13
  getVoices(): Promise<ReadiumSpeechVoice[]>;
10
14
  setVoice(voice: ReadiumSpeechVoice | string): void;
11
15
  getCurrentVoice(): ReadiumSpeechVoice | null;
12
16
  setSpeakInContentLanguage(enabled: boolean): void;
13
17
  getSpeakInContentLanguage(): boolean;
14
18
  loadContent(content: ReadiumSpeechUtterance | ReadiumSpeechUtterance[]): void;
19
+ loadGndContent(nodes: GndObject[]): void;
15
20
  getCurrentContent(): ReadiumSpeechUtterance | null;
16
21
  getContentQueue(): ReadiumSpeechUtterance[];
17
22
  play(): void;
@@ -20,12 +25,6 @@ export interface ReadiumSpeechNavigatorContract {
20
25
  next(): boolean;
21
26
  previous(): boolean;
22
27
  jumpTo(utteranceIndex: number): void;
23
- setRate(rate: number): void;
24
- getRate(): number;
25
- setPitch(pitch: number): void;
26
- getPitch(): number;
27
- setVolume(volume: number): void;
28
- getVolume(): number;
29
28
  getState(): ReadiumSpeechPlaybackState;
30
29
  on(event: ReadiumSpeechPlaybackEvent["type"] | "contentchange", listener: (event: ReadiumSpeechPlaybackEvent) => void): () => void;
31
30
  destroy(): Promise<void>;
@@ -0,0 +1,12 @@
1
+ import { IPreferencesEditor } from './PreferencesEditor.js';
2
+ export interface ConfigurableSettings {
3
+ [key: string]: unknown;
4
+ }
5
+ export interface ConfigurablePreferences<T> {
6
+ merging(other: T): T;
7
+ }
8
+ export interface Configurable<S extends ConfigurableSettings, P extends ConfigurablePreferences<P>> {
9
+ settings: S;
10
+ submitPreferences(preferences: P): void;
11
+ preferencesEditor: IPreferencesEditor;
12
+ }
@@ -0,0 +1,74 @@
1
+ export interface IPreference<T> {
2
+ value: T | null | undefined;
3
+ effectiveValue: T | null | undefined;
4
+ isEffective: boolean;
5
+ clear(): void;
6
+ }
7
+ export interface IEnumPreference<T> extends IPreference<T> {
8
+ supportedValues: T[];
9
+ }
10
+ export interface IRangePreference<T> extends IPreference<T> {
11
+ supportedRange: [T, T];
12
+ step: number;
13
+ increment(): void;
14
+ decrement(): void;
15
+ format(value: T): string;
16
+ }
17
+ export declare class Preference<T> implements IPreference<T> {
18
+ protected _value?: T | null;
19
+ protected readonly _effectiveValue?: T | null;
20
+ protected readonly _isEffective: boolean;
21
+ protected _onChange: (newValue: T | null | undefined) => void;
22
+ constructor({ initialValue, effectiveValue, isEffective, onChange, }: {
23
+ initialValue?: T | null;
24
+ effectiveValue?: T | null;
25
+ isEffective: boolean;
26
+ onChange: (newValue: T | null | undefined) => void;
27
+ });
28
+ set value(value: T | null | undefined);
29
+ get value(): T | null | undefined;
30
+ get effectiveValue(): T | null | undefined;
31
+ get isEffective(): boolean;
32
+ clear(): void;
33
+ }
34
+ export declare class EnumPreference<T extends string | number | symbol> extends Preference<T> implements IEnumPreference<T> {
35
+ private readonly _supportedValues;
36
+ constructor({ initialValue, effectiveValue, isEffective, onChange, supportedValues, }: {
37
+ initialValue?: T | null;
38
+ effectiveValue?: T | null;
39
+ isEffective: boolean;
40
+ onChange: (newValue: T | null | undefined) => void;
41
+ supportedValues: T[];
42
+ });
43
+ set value(value: T | null | undefined);
44
+ get value(): T | null | undefined;
45
+ get supportedValues(): T[];
46
+ }
47
+ export declare class BooleanPreference extends Preference<boolean> {
48
+ set value(value: boolean | null | undefined);
49
+ get value(): boolean | null | undefined;
50
+ }
51
+ export declare class StringArrayPreference extends Preference<string[]> {
52
+ set value(value: string[] | null | undefined);
53
+ get value(): string[] | null | undefined;
54
+ }
55
+ export declare class RangePreference<T extends number> extends Preference<T> implements IRangePreference<T> {
56
+ private readonly _supportedRange;
57
+ private readonly _step;
58
+ private readonly _decimals;
59
+ constructor({ initialValue, effectiveValue, isEffective, onChange, supportedRange, step, }: {
60
+ initialValue?: T | null;
61
+ effectiveValue?: T | null;
62
+ isEffective: boolean;
63
+ onChange: (newValue: T | null | undefined) => void;
64
+ supportedRange: [T, T];
65
+ step: number;
66
+ });
67
+ set value(value: T | null | undefined);
68
+ get value(): T | null | undefined;
69
+ get supportedRange(): [T, T];
70
+ get step(): number;
71
+ increment(): void;
72
+ decrement(): void;
73
+ format(value: T): string;
74
+ }
@@ -0,0 +1,5 @@
1
+ import { ConfigurablePreferences } from './Configurable.js';
2
+ export interface IPreferencesEditor {
3
+ preferences: ConfigurablePreferences<unknown>;
4
+ clear(): void;
5
+ }
@@ -0,0 +1,31 @@
1
+ import { GndRole } from '../gnd/types.js';
2
+ import { ExtractionFormat, LanguageMode, PauseScope, VerbosityPreset } from './SpeechPreferences.js';
3
+ export interface ISpeechDefaults {
4
+ format?: ExtractionFormat | null;
5
+ inlineContextualization?: boolean | null;
6
+ verbosity?: VerbosityPreset | null;
7
+ skip?: GndRole[] | null;
8
+ contextualize?: GndRole[] | null;
9
+ language?: LanguageMode | null;
10
+ pauseDuration?: number | null;
11
+ pauseScope?: PauseScope | null;
12
+ automaticPausesAtPageOrSpreadEnd?: boolean | null;
13
+ rate?: number | null;
14
+ pitch?: number | null;
15
+ volume?: number | null;
16
+ }
17
+ export declare class SpeechDefaults {
18
+ readonly format: ExtractionFormat;
19
+ readonly inlineContextualization: boolean;
20
+ readonly verbosity: VerbosityPreset;
21
+ readonly skip: GndRole[];
22
+ readonly contextualize: GndRole[];
23
+ readonly language: LanguageMode;
24
+ readonly pauseDuration: number;
25
+ readonly pauseScope: PauseScope;
26
+ readonly automaticPausesAtPageOrSpreadEnd: boolean;
27
+ readonly rate: number;
28
+ readonly pitch: number;
29
+ readonly volume: number;
30
+ constructor(defaults?: ISpeechDefaults);
31
+ }
@@ -0,0 +1,36 @@
1
+ import { GndRole } from '../gnd/types.js';
2
+ import { ConfigurablePreferences } from './Configurable.js';
3
+ export type VerbosityPreset = "none" | "few" | "some" | "most" | "custom";
4
+ export type LanguageMode = "none" | "block-level" | "always";
5
+ export type ExtractionFormat = "plain" | "ssml";
6
+ export type PauseScope = "utterance" | "block";
7
+ export interface ISpeechPreferences {
8
+ format?: ExtractionFormat | null;
9
+ inlineContextualization?: boolean | null;
10
+ verbosity?: VerbosityPreset | null;
11
+ skip?: GndRole[] | null;
12
+ contextualize?: GndRole[] | null;
13
+ language?: LanguageMode | null;
14
+ pauseDuration?: number | null;
15
+ pauseScope?: PauseScope | null;
16
+ automaticPausesAtPageOrSpreadEnd?: boolean | null;
17
+ rate?: number | null;
18
+ pitch?: number | null;
19
+ volume?: number | null;
20
+ }
21
+ export declare class SpeechPreferences implements ISpeechPreferences, ConfigurablePreferences<SpeechPreferences> {
22
+ format: ExtractionFormat | null | undefined;
23
+ inlineContextualization: boolean | null | undefined;
24
+ verbosity: VerbosityPreset | null | undefined;
25
+ skip: GndRole[] | null | undefined;
26
+ contextualize: GndRole[] | null | undefined;
27
+ language: LanguageMode | null | undefined;
28
+ pauseDuration: number | null | undefined;
29
+ pauseScope: PauseScope | null | undefined;
30
+ automaticPausesAtPageOrSpreadEnd: boolean | null | undefined;
31
+ rate: number | null | undefined;
32
+ pitch: number | null | undefined;
33
+ volume: number | null | undefined;
34
+ constructor(preferences?: ISpeechPreferences);
35
+ merging(other: SpeechPreferences): SpeechPreferences;
36
+ }
@@ -0,0 +1,23 @@
1
+ import { IPreferencesEditor } from './PreferencesEditor.js';
2
+ import { BooleanPreference, EnumPreference, RangePreference, StringArrayPreference } from './Preference.js';
3
+ import { SpeechPreferences, VerbosityPreset, LanguageMode, ExtractionFormat, PauseScope } from './SpeechPreferences.js';
4
+ import { SpeechSettings } from './SpeechSettings.js';
5
+ export declare class SpeechPreferencesEditor implements IPreferencesEditor {
6
+ preferences: SpeechPreferences;
7
+ private settings;
8
+ constructor(initialPreferences: SpeechPreferences, settings: SpeechSettings);
9
+ clear(): void;
10
+ private updatePreference;
11
+ get format(): EnumPreference<ExtractionFormat>;
12
+ get inlineContextualization(): BooleanPreference;
13
+ get verbosity(): EnumPreference<VerbosityPreset>;
14
+ get skip(): StringArrayPreference;
15
+ get contextualize(): StringArrayPreference;
16
+ get language(): EnumPreference<LanguageMode>;
17
+ get pauseDuration(): RangePreference<number>;
18
+ get pauseScope(): EnumPreference<PauseScope>;
19
+ get automaticPausesAtPageOrSpreadEnd(): BooleanPreference;
20
+ get rate(): RangePreference<number>;
21
+ get pitch(): RangePreference<number>;
22
+ get volume(): RangePreference<number>;
23
+ }
@@ -0,0 +1,20 @@
1
+ import { GndRole } from '../gnd/types.js';
2
+ import { ConfigurableSettings } from './Configurable.js';
3
+ import { SpeechDefaults } from './SpeechDefaults.js';
4
+ import { ExtractionFormat, LanguageMode, PauseScope, SpeechPreferences, VerbosityPreset } from './SpeechPreferences.js';
5
+ export declare class SpeechSettings implements ConfigurableSettings {
6
+ [key: string]: unknown;
7
+ readonly format: ExtractionFormat;
8
+ readonly inlineContextualization: boolean;
9
+ readonly verbosity: VerbosityPreset;
10
+ readonly skip: GndRole[];
11
+ readonly contextualize: GndRole[];
12
+ readonly language: LanguageMode;
13
+ readonly pauseDuration: number;
14
+ readonly pauseScope: PauseScope;
15
+ readonly automaticPausesAtPageOrSpreadEnd: boolean;
16
+ readonly rate: number;
17
+ readonly pitch: number;
18
+ readonly volume: number;
19
+ constructor(preferences: SpeechPreferences, defaults: SpeechDefaults);
20
+ }
@@ -0,0 +1,14 @@
1
+ import { ExtractionFormat, ISpeechPreferences, LanguageMode, PauseScope, VerbosityPreset } from './SpeechPreferences.js';
2
+ export interface RangeConfig {
3
+ range: [number, number];
4
+ step: number;
5
+ }
6
+ export declare const pauseDurationRangeConfig: RangeConfig;
7
+ export declare const rateRangeConfig: RangeConfig;
8
+ export declare const pitchRangeConfig: RangeConfig;
9
+ export declare const volumeRangeConfig: RangeConfig;
10
+ export declare const verbosityPresets: VerbosityPreset[];
11
+ export declare const languageModes: LanguageMode[];
12
+ export declare const extractionFormats: ExtractionFormat[];
13
+ export declare const pauseScopes: PauseScope[];
14
+ export declare const extractionPreferenceKeys: (keyof ISpeechPreferences)[];
@@ -0,0 +1,4 @@
1
+ export declare function ensureBoolean(value: boolean | null | undefined): boolean | null | undefined;
2
+ export declare function ensureEnumValue<T extends string | number | symbol>(value: T | null | undefined, supportedValues: readonly T[]): T | null | undefined;
3
+ export declare function ensureValueInRange(value: number | null | undefined, range: [number, number]): number | null | undefined;
4
+ export declare function ensureStringArray(value: string[] | null | undefined): string[] | null | undefined;
@@ -0,0 +1,11 @@
1
+ export type { Configurable, ConfigurablePreferences, ConfigurableSettings } from './Configurable.js';
2
+ export type { IPreferencesEditor } from './PreferencesEditor.js';
3
+ export { BooleanPreference, EnumPreference, Preference, RangePreference, StringArrayPreference } from './Preference.js';
4
+ export type { IEnumPreference, IPreference, IRangePreference } from './Preference.js';
5
+ export { SpeechPreferences } from './SpeechPreferences.js';
6
+ export type { ISpeechPreferences, LanguageMode, VerbosityPreset } from './SpeechPreferences.js';
7
+ export { SpeechDefaults } from './SpeechDefaults.js';
8
+ export type { ISpeechDefaults } from './SpeechDefaults.js';
9
+ export { SpeechSettings } from './SpeechSettings.js';
10
+ export { SpeechPreferencesEditor } from './SpeechPreferencesEditor.js';
11
+ export { contextualizedAtVerbosity, skippableAtVerbosity } from './verbosityTables.js';
@@ -0,0 +1,4 @@
1
+ import { GndRole } from '../gnd/types.js';
2
+ import { VerbosityPreset } from './SpeechPreferences.js';
3
+ export declare const skippableAtVerbosity: Readonly<Record<Exclude<VerbosityPreset, "custom">, ReadonlySet<GndRole>>>;
4
+ export declare const contextualizedAtVerbosity: Readonly<Record<Exclude<VerbosityPreset, "custom">, ReadonlySet<GndRole>>>;
@@ -1,13 +1,32 @@
1
1
  import { ReadiumSpeechPlaybackEngine } from './engine';
2
+ import { GndObject } from './gnd/types';
2
3
  import { ReadiumSpeechNavigatorContract, ReadiumSpeechPlaybackEvent, ReadiumSpeechPlaybackState } from './navigator';
4
+ import { ISpeechDefaults } from './preferences/SpeechDefaults';
5
+ import { ISpeechPreferences, SpeechPreferences } from './preferences/SpeechPreferences';
6
+ import { SpeechPreferencesEditor } from './preferences/SpeechPreferencesEditor';
7
+ import { SpeechSettings } from './preferences/SpeechSettings';
3
8
  import { ReadiumSpeechUtterance } from './utterance';
4
9
  import { ReadiumSpeechVoice } from './voices/types';
10
+ export interface ReadiumSpeechNavigatorConfiguration {
11
+ preferences?: ISpeechPreferences;
12
+ defaults?: ISpeechDefaults;
13
+ }
5
14
  export declare class ReadiumSpeechNavigator implements ReadiumSpeechNavigatorContract {
6
15
  private engine;
7
16
  private contentQueue;
8
17
  private eventListeners;
9
18
  private navigatorState;
10
- constructor(engine: ReadiumSpeechPlaybackEngine);
19
+ private pendingAdvanceTimeout;
20
+ private _defaults;
21
+ private _preferences;
22
+ private _settings;
23
+ private _preferencesEditor;
24
+ private source;
25
+ private contentSources;
26
+ private pendingResumeIndex;
27
+ private pendingResumeState;
28
+ constructor(engine: ReadiumSpeechPlaybackEngine, configuration?: ReadiumSpeechNavigatorConfiguration);
29
+ private applyEngineParameters;
11
30
  private initializeEngine;
12
31
  private setupEngineListeners;
13
32
  private setNavigatorState;
@@ -17,25 +36,29 @@ export declare class ReadiumSpeechNavigator implements ReadiumSpeechNavigatorCon
17
36
  setSpeakInContentLanguage(enabled: boolean): void;
18
37
  getSpeakInContentLanguage(): boolean;
19
38
  loadContent(content: ReadiumSpeechUtterance | ReadiumSpeechUtterance[]): void;
39
+ loadGndContent(nodes: GndObject[]): void;
40
+ private setContentQueue;
41
+ private reextract;
42
+ private resolveResumeIndex;
20
43
  getCurrentContent(): ReadiumSpeechUtterance | null;
21
44
  getContentQueue(): ReadiumSpeechUtterance[];
22
45
  private getCurrentUtteranceIndex;
23
46
  play(): void;
24
47
  pause(): void;
25
48
  stop(): void;
49
+ private clearPendingAdvance;
26
50
  private skipToPosition;
27
51
  next(forcePlay?: boolean): boolean;
28
52
  previous(forcePlay?: boolean): boolean;
29
53
  jumpTo(utteranceIndex: number, forcePlay?: boolean): boolean;
30
- setRate(rate: number): void;
31
- getRate(): number;
32
- setPitch(pitch: number): void;
33
- getPitch(): number;
34
- setVolume(volume: number): void;
35
- getVolume(): number;
36
54
  getState(): ReadiumSpeechPlaybackState;
37
55
  on(event: ReadiumSpeechPlaybackEvent["type"] | "contentchange", listener: (event: ReadiumSpeechPlaybackEvent) => void): () => void;
38
56
  private emitEvent;
39
57
  private emitContentChangeEvent;
58
+ get settings(): SpeechSettings;
59
+ get preferencesEditor(): SpeechPreferencesEditor;
60
+ submitPreferences(preferences: SpeechPreferences): void;
61
+ private applyPreferences;
62
+ private sameSettingValue;
40
63
  destroy(): Promise<void>;
41
64
  }
@@ -3,4 +3,5 @@ export interface ReadiumSpeechUtterance {
3
3
  plain?: string;
4
4
  ssml?: string;
5
5
  language?: string;
6
+ startsNewBlock?: true;
6
7
  }
@@ -10,3 +10,10 @@ import { ExtractUtterancesOptions } from './types.js';
10
10
  * rather than a wrapped document.
11
11
  */
12
12
  export declare function extractUtterances(nodes: GndObject[], options: ExtractUtterancesOptions): ReadiumSpeechUtterance[];
13
+ /**
14
+ * Same as `extractUtterances()`, plus `sources[i]`: the node that produced `utterances[i]`.
15
+ */
16
+ export declare function extractUtterancesWithSources(nodes: GndObject[], options: ExtractUtterancesOptions): {
17
+ utterances: ReadiumSpeechUtterance[];
18
+ sources: (GndObject | undefined)[];
19
+ };
@@ -1,4 +1,4 @@
1
1
  export { extractUtterances } from './extractUtterances.js';
2
- export { skippableRoles } from './roles.js';
2
+ export { blockLevelRoles, skippableRoles } from './roles.js';
3
3
  export { defaultAnnouncements } from './announcements.js';
4
4
  export type { Announcement, AnnouncementKey, AnnouncementPair, Announcements, RoleAnnouncement, ExtractUtterancesOptions, } from './types.js';
@@ -1,2 +1,3 @@
1
1
  import { GndRole } from '../gnd/types.js';
2
2
  export declare const skippableRoles: GndRole[];
3
+ export declare const blockLevelRoles: GndRole[];
@@ -47,7 +47,7 @@ export interface SsmlSegment {
47
47
  export declare function hasPlaceholder(ssml: string): boolean;
48
48
  /**
49
49
  * Splits a raw (pre-`stripPlaceholders`) SSML string on its embedded
50
- * `<readium:TAG id="...">` placeholders, for `interruptSentence`: each
50
+ * `<readium:TAG id="...">` placeholders, for `inlineContextualization`: each
51
51
  * placeholder becomes its own segment (resolved via the `GndObject` sharing
52
52
  * its `id`) instead of being spoken after the whole enclosing text.
53
53
  */
@@ -12,7 +12,7 @@ export interface ExtractUtterancesOptions {
12
12
  format?: "plain" | "ssml";
13
13
  announcements?: Announcements;
14
14
  skip?: GndRole[];
15
+ contextualize?: GndRole[];
15
16
  language?: "none" | "block-level" | "always";
16
- interruptSentence?: boolean;
17
- contextualize?: boolean;
17
+ inlineContextualization?: boolean;
18
18
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@readium/speech",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "A TypeScript library for implementing read aloud features with Web technologies, following best practices for digital publishing.",
5
5
  "author": "Readium Foundation",
6
6
  "keywords": [