@banou/media-player 0.10.20 → 0.10.22

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,4 @@
1
+ import type { PlaybackOutput } from '../../engine';
1
2
  import type { MediaPlayerLocalOptions } from '../video-player';
2
3
  /**
3
4
  * Owns the engine for the life of a source: start, teardown, and every piece of state the pipeline
@@ -5,4 +6,4 @@ import type { MediaPlayerLocalOptions } from '../video-player';
5
6
  */
6
7
  export declare const usePlayback: (video: HTMLVideoElement | null, subtitles: HTMLElement | null,
7
8
  /** null when the media is remote: there are no bytes, so there is no pipeline to run. */
8
- options: MediaPlayerLocalOptions | null) => void;
9
+ options: MediaPlayerLocalOptions | null, onOutput?: (output: PlaybackOutput) => void) => void;
@@ -1,8 +1,16 @@
1
+ import type { LoudnessSource } from '../../audio/loudness-analysis';
2
+ import type { PlaybackTap } from '../../audio/playback-tap';
1
3
  /**
2
4
  * Normalizes the element's volume while `enabled`. Nothing is built until it first is, and turning it off
3
5
  * afterwards bypasses rather than unroutes, since an element cannot be handed back. `refused` is true once the
4
6
  * engine turned the element down, which leaves it playing exactly as before.
7
+ *
8
+ * With a `source`, the file is also analysed ahead of the playhead while it is on, reading only the byte `ranges`
9
+ * given (all of them when undefined), or with a `tap`, from the audio playback remuxed.
5
10
  */
6
- export declare const useVolumeNormalizer: (video: HTMLVideoElement | null, workletUrl: string | undefined, enabled: boolean) => {
11
+ export declare const useVolumeNormalizer: (video: HTMLVideoElement | null, workletUrl: string | undefined, enabled: boolean, source?: LoudnessSource | {
12
+ tap: PlaybackTap;
13
+ audioStreamIndex: number;
14
+ }, ranges?: [number, number][]) => {
7
15
  refused: boolean;
8
16
  };
@@ -6,13 +6,19 @@ import type { ExposePlayerOptions } from '../remote';
6
6
  /**
7
7
  * The source, read a range at a time: the player never downloads the whole file. Both fields travel
8
8
  * together, so passing one without the other is a type error.
9
+ *
10
+ * `readsDownload` marks a source each read of which is a download, a file over HTTP, so the volume normalizer
11
+ * analyses the audio playback fetched instead of reading the file again. Without it, and with no
12
+ * `downloadedRanges`, every byte is taken to be readable for free, as a local file's are.
9
13
  */
10
14
  export type MediaPlayerSource = {
11
15
  read: (offset: number, size: number) => Promise<ArrayBuffer>;
12
16
  size: number;
17
+ readsDownload?: boolean;
13
18
  } | {
14
19
  read?: undefined;
15
20
  size?: undefined;
21
+ readsDownload?: undefined;
16
22
  };
17
23
  /** Shared by both arms: nothing here depends on who owns the media. */
18
24
  type CommonOptions = {
@@ -134,11 +140,13 @@ export type MediaPlayerLocalOptions = CommonOptions & MediaPlayerSource & {
134
140
  /** Byte spans available, painted on the seekbar and informing the thumbnail generator. */
135
141
  downloadedRanges?: DownloadedRange[];
136
142
  /**
137
- * Reader for the thumbnail engine, when it should differ from playback's.
143
+ * Reader for the thumbnail engine and the volume normalizer's analysis, when it should differ from playback's.
138
144
  *
139
145
  * They are the same by default so generation shares playback's fetch order. A consumer whose
140
146
  * reads are not free wants them apart: a torrent hands this a non-prioritising, fail-fast reader
141
- * so generating previews cannot steal download order from the bytes playback is blocked on.
147
+ * so generating previews cannot steal download order from the bytes playback is blocked on. The
148
+ * analysis asks it only for bytes inside `downloadedRanges`, with none given for the whole file, and for
149
+ * nothing when the source `readsDownload`.
142
150
  */
143
151
  thumbnailRead?: (offset: number, size: number) => Promise<ArrayBuffer>;
144
152
  /** Off entirely. A second wasm worker during pipeline boot is worth avoiding on a slow source. */
@@ -153,10 +161,14 @@ export type MediaPlayerLocalOptions = CommonOptions & MediaPlayerSource & {
153
161
  */
154
162
  normalizerWorkletUrl?: string;
155
163
  /**
156
- * The settings menu's "Normalize volume" switch: holds the loudness steady, so a music cue is turned down to
157
- * the dialogue around it. Off by default. The player keeps the switch's state from here and from the viewer's
158
- * clicks; nothing is saved, so an app that wants it to stick saves what `onNormalizeVolumeChange` reports and
159
- * passes it back.
164
+ * The settings menu's "Normalize volume" switch: keeps the file's normal level and turns down what goes well
165
+ * over it, a loud burst before it starts. On by default; pass false for off. The player keeps the switch's
166
+ * state from here and from the viewer's clicks; nothing is saved, so an app that wants it to stick saves what
167
+ * `onNormalizeVolumeChange` reports and passes it back.
168
+ *
169
+ * While it is on the file is read a second time, in a worker, as far as `downloadedRanges` allows, to find the
170
+ * loud parts ahead of the playhead; a source that `readsDownload` is not read again, and its loud parts are found
171
+ * in what playback fetched. The sound plays 10 ms behind its input, on or off, once routed.
160
172
  *
161
173
  * The first time it is on, the element is routed through Web Audio for the rest of its life (off then
162
174
  * bypasses). If autoplay rules hold the audio back, that waits for the page's next click, tap or key press, and
@@ -165,7 +177,7 @@ export type MediaPlayerLocalOptions = CommonOptions & MediaPlayerSource & {
165
177
  * the element is never routed.
166
178
  */
167
179
  normalizeVolume?: boolean;
168
- /** The viewer flipped the switch. */
180
+ /** The viewer flipped the switch, to `normalizeVolume`: what an app saves to pass back as `normalizeVolume`. */
169
181
  onNormalizeVolumeChange?: (normalizeVolume: boolean) => void;
170
182
  };
171
183
  /**
@@ -15,12 +15,17 @@ declare const fromUrl: ({ url, length: _length, name, credentials }: {
15
15
  length: number;
16
16
  name: string | undefined;
17
17
  read: (offset: number, size: number) => Promise<ArrayBuffer>;
18
+ readsDownload: boolean;
18
19
  }>;
19
- /** A source resolved down to what the remuxer needs: a total length and a byte-range reader. */
20
+ /**
21
+ * A source resolved down to what the remuxer needs: a total length and a byte-range reader, and whether each read
22
+ * is a download, which the player's `readsDownload` takes.
23
+ */
20
24
  export type RemuxerInput = {
21
25
  length: number;
22
26
  name?: string;
23
27
  read: (offset: number, size: number) => Promise<ArrayBuffer>;
28
+ readsDownload?: boolean;
24
29
  };
25
30
  export declare const inputToRemuxerInput: (params: Parameters<typeof fromBlob | typeof fromUrl>[0] | {
26
31
  length: number;