@vindral/web-sdk 1.2.1 → 2.0.2
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/LICENSES +66 -0
- package/README.md +35 -24
- package/index.d.ts +138 -52
- package/package.json +2 -1
- package/web-sdk.esm.js +1 -1
- package/web-sdk.umd.js +1 -1
package/LICENSES
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
libopus license
|
|
2
|
+
---------------
|
|
3
|
+
|
|
4
|
+
Copyright 2001-2011 Xiph.Org, Skype Limited, Octasic,
|
|
5
|
+
Jean-Marc Valin, Timothy B. Terriberry,
|
|
6
|
+
CSIRO, Gregory Maxwell, Mark Borgerding,
|
|
7
|
+
Erik de Castro Lopo
|
|
8
|
+
|
|
9
|
+
Redistribution and use in source and binary forms, with or without
|
|
10
|
+
modification, are permitted provided that the following conditions
|
|
11
|
+
are met:
|
|
12
|
+
|
|
13
|
+
- Redistributions of source code must retain the above copyright
|
|
14
|
+
notice, this list of conditions and the following disclaimer.
|
|
15
|
+
|
|
16
|
+
- Redistributions in binary form must reproduce the above copyright
|
|
17
|
+
notice, this list of conditions and the following disclaimer in the
|
|
18
|
+
documentation and/or other materials provided with the distribution.
|
|
19
|
+
|
|
20
|
+
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
|
21
|
+
names of specific contributors, may be used to endorse or promote
|
|
22
|
+
products derived from this software without specific prior written
|
|
23
|
+
permission.
|
|
24
|
+
|
|
25
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
26
|
+
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
27
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
28
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
|
29
|
+
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
30
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
31
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
32
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
33
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
34
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
35
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
36
|
+
|
|
37
|
+
Opus is subject to the royalty-free patent licenses which are
|
|
38
|
+
specified at:
|
|
39
|
+
|
|
40
|
+
Xiph.Org Foundation:
|
|
41
|
+
https://datatracker.ietf.org/ipr/1524/
|
|
42
|
+
|
|
43
|
+
Microsoft Corporation:
|
|
44
|
+
https://datatracker.ietf.org/ipr/1914/
|
|
45
|
+
|
|
46
|
+
Broadcom Corporation:
|
|
47
|
+
https://datatracker.ietf.org/ipr/1526/
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
h264 license
|
|
52
|
+
------------
|
|
53
|
+
|
|
54
|
+
Copyright (C) 2009 The Android Open Source Project
|
|
55
|
+
|
|
56
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
57
|
+
you may not use this file except in compliance with the License.
|
|
58
|
+
You may obtain a copy of the License at
|
|
59
|
+
|
|
60
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
61
|
+
|
|
62
|
+
Unless required by applicable law or agreed to in writing, software
|
|
63
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
64
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
65
|
+
See the License for the specific language governing permissions and
|
|
66
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -2,41 +2,55 @@
|
|
|
2
2
|
|
|
3
3
|
**Ultra low latency streaming on all modern web browsers.**
|
|
4
4
|
|
|
5
|
-
This package contains the
|
|
5
|
+
This package contains the Web SDK for Vindral - the ultra low latency streaming platform for synchronized live experiences.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
For information about the Vindral product family and how the Web SDK fits into the system, [make sure to read the System Overview](https://docs.vindral.com/docs/overview/system-overview).
|
|
8
|
+
|
|
9
|
+
Make sure to check out the full [Web SDK Documentation](https://docs.vindral.com/web-sdk/) as well.
|
|
10
|
+
|
|
11
|
+
[Check out our demo](https://demo.vindral.com/) to see some of Vindral's features.
|
|
8
12
|
|
|
9
13
|
## Getting Started
|
|
10
14
|
|
|
11
15
|
There are multiple ways to integrate the Web SDK, depending on use-case.
|
|
12
16
|
|
|
13
|
-
The
|
|
17
|
+
The most simple way to get started is to use the iframe-based [Embed Player](#embed-player). This requires the least amount of code, and will automatically be updated when new releases are available.
|
|
14
18
|
|
|
15
19
|
The two other alternatives are [Player SDK](#player-sdk) and [Core SDK](#core-sdk) - these are the recommended options if the integration requires access to the APIs, such as timed metadata or other controls. The two SDKs have very similar APIs, but the Player SDK provides controls and buffering indication built in - the Core SDK is the most strippped down implementation for use-cases where all UI components are customized.
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
If you are going for one of the SDK alternatives, follow the steps at [Installation](#installation) to get started:
|
|
22
|
+
|
|
23
|
+
## Embed Player
|
|
18
24
|
|
|
19
25
|
This is the simplest way to integrate. It allows you to add a fully functional video player to your site in no time. It will also be automatically updated when improvements are released.
|
|
20
26
|
|
|
21
|
-
Add the following html snippet,
|
|
27
|
+
Add the following html snippet, set `channelId` to channel id credential, done!
|
|
22
28
|
|
|
23
|
-
```
|
|
24
|
-
<iframe
|
|
29
|
+
```html
|
|
30
|
+
<iframe
|
|
31
|
+
src="https://embed.vindral.com/?channelId=vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f"
|
|
32
|
+
frameborder="0"
|
|
33
|
+
allowfullscreen
|
|
34
|
+
></iframe>
|
|
25
35
|
```
|
|
26
36
|
|
|
27
|
-
|
|
37
|
+
[See the player in action](https://embed.vindral.com/?channelId=vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f) or [read more about Embed Player here](https://docs.vindral.com/docs/guides/using-the-embed-player).
|
|
28
38
|
|
|
29
|
-
|
|
39
|
+
## Installation
|
|
30
40
|
|
|
31
|
-
|
|
41
|
+
Install @vindral/web-sdk using `npm`:
|
|
32
42
|
|
|
33
43
|
```
|
|
34
|
-
npm install @vindral/web-sdk
|
|
44
|
+
npm install --save @vindral/web-sdk
|
|
35
45
|
```
|
|
36
46
|
|
|
37
|
-
|
|
47
|
+
or `yarn`:
|
|
38
48
|
|
|
39
|
-
|
|
49
|
+
```
|
|
50
|
+
yarn add @vindral/web-sdk
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Player SDK
|
|
40
54
|
|
|
41
55
|
The Player SDK provides a ready-to-go player with controls - perfect for use-cases where the embed solution is not enough, such as when access to the javascript API is needed.
|
|
42
56
|
|
|
@@ -52,21 +66,18 @@ import { Player } from "@vindral/web-sdk"
|
|
|
52
66
|
const root = document.querySelector<HTMLElement>("#root")
|
|
53
67
|
|
|
54
68
|
const player = new Player({
|
|
55
|
-
url: "
|
|
56
|
-
channelId: "
|
|
69
|
+
url: "https://lb.cdn.vindral.com",
|
|
70
|
+
channelId: "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
|
|
57
71
|
})
|
|
58
72
|
|
|
59
73
|
// Starts connecting to the channel
|
|
60
74
|
player.core.connect()
|
|
61
75
|
|
|
62
|
-
// This event is emitted when timed metadata events occur
|
|
63
|
-
player.core.on("metadata", (metadata) => console.log("metadata: ", metadata.content))
|
|
64
|
-
|
|
65
76
|
// Attaches the player view to the DOM
|
|
66
77
|
player.attach(root)
|
|
67
78
|
```
|
|
68
79
|
|
|
69
|
-
|
|
80
|
+
### Core SDK
|
|
70
81
|
|
|
71
82
|
The Core SDK is the lowest level method to integrate that provides only a video view and audio playback - this allows for full customization of the look of buffering indication, controls, etc.
|
|
72
83
|
|
|
@@ -75,7 +86,7 @@ The Core SDK is the lowest level method to integrate that provides only a video
|
|
|
75
86
|
The example assumes that there is a html page that loads this script that has at least a div with `id="#root"`, `id="#playback-state"` and a button with `id="#activate-audio-button"`.
|
|
76
87
|
|
|
77
88
|
```typescript
|
|
78
|
-
import { Vindral } from "@
|
|
89
|
+
import { Vindral } from "@vindral/web-sdk"
|
|
79
90
|
|
|
80
91
|
const root = document.querySelector<HTMLElement>("#root")!
|
|
81
92
|
const button = document.querySelector<HTMLElement>("#activate-audio-button")!
|
|
@@ -84,8 +95,8 @@ const playbackState = document.querySelector<HTMLElement>("#playback-state")!
|
|
|
84
95
|
button.style.display = "none"
|
|
85
96
|
|
|
86
97
|
const instance = new Vindral({
|
|
87
|
-
url: "
|
|
88
|
-
channelId: "
|
|
98
|
+
url: "https://lb.cdn.vindral.com",
|
|
99
|
+
channelId: "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
|
|
89
100
|
})
|
|
90
101
|
|
|
91
102
|
// Errors are emitted when they can not be handled internally
|
|
@@ -122,6 +133,6 @@ button.addEventListener("click", () => {
|
|
|
122
133
|
|
|
123
134
|
#### License and support
|
|
124
135
|
|
|
125
|
-
Vindral is a commercial product and requires an active, paid license to access and use. To obtain such a license, or in case you have any questions, get in touch
|
|
136
|
+
Vindral is a commercial product and requires an active, paid license to access and use. To obtain such a license, or in case you have any questions, do not hesitate to [get in touch](https://vindral.com/inquiries)!
|
|
126
137
|
|
|
127
|
-
Copyright
|
|
138
|
+
Copyright RealSprint AB
|
package/index.d.ts
CHANGED
|
@@ -317,8 +317,12 @@ interface VindralErrorProps {
|
|
|
317
317
|
source?: Error;
|
|
318
318
|
}
|
|
319
319
|
export declare const CONNECTION_FAILED_CODE = "connection_failed";
|
|
320
|
+
export declare const CONNECTION_FAILED_AFTER_RETRIES_CODE = "connection_failed_will_not_attempt_again";
|
|
320
321
|
export declare const AUTHENTICATION_FAILED_CODE = "authentication_error";
|
|
322
|
+
export declare const AUTHENTICATION_EXPIRED_CODE = "authentication_expired";
|
|
323
|
+
export declare const CHANNEL_NOT_FOUND_CODE = "channel_not_found";
|
|
321
324
|
export declare const NO_INCOMING_DATA = "no_incoming_data_error";
|
|
325
|
+
export declare const INACTIVITY_CODE = "connection_inactivity";
|
|
322
326
|
export declare class VindralError extends Error {
|
|
323
327
|
private props;
|
|
324
328
|
private extra;
|
|
@@ -331,7 +335,12 @@ export declare class VindralError extends Error {
|
|
|
331
335
|
export declare const mediaElementError: (isFatal: boolean, mediaError: MediaError) => VindralError;
|
|
332
336
|
export declare const audioContextTimeoutError: () => VindralError;
|
|
333
337
|
export declare const authenticationError: () => VindralError;
|
|
338
|
+
export declare const authenticationExpiredError: () => VindralError;
|
|
339
|
+
export declare const inactivityError: () => VindralError;
|
|
340
|
+
export declare const channelNotFoundError: () => VindralError;
|
|
334
341
|
export declare const noIncomingDataError: () => VindralError;
|
|
342
|
+
export declare const unableToConnectError: () => VindralError;
|
|
343
|
+
export declare const unableToConnectAfterRetriesError: () => VindralError;
|
|
335
344
|
export declare const isValidOptions: (options: unknown) => options is Options;
|
|
336
345
|
export declare const validateOptions: (options: Options) => Options;
|
|
337
346
|
declare type State = "connected" | "disconnected" | "connecting";
|
|
@@ -369,7 +378,9 @@ declare class ConnectionModule {
|
|
|
369
378
|
private lastPingSentTime?;
|
|
370
379
|
private connectCount;
|
|
371
380
|
private _firstConnectionTime?;
|
|
381
|
+
private _lastConnectionTime?;
|
|
372
382
|
private contextSwitchesInProgress;
|
|
383
|
+
private contextSwitchesCompleted;
|
|
373
384
|
private buffer;
|
|
374
385
|
private constructor();
|
|
375
386
|
static create: (emitter: Emitter<ConnectionModuleListeners, ConnectionModuleEvents>, logger: Logger, options: ConnectOptions) => ConnectionModule;
|
|
@@ -380,12 +391,13 @@ declare class ConnectionModule {
|
|
|
380
391
|
get estimatedBandwidth(): number | undefined;
|
|
381
392
|
get connectTime(): number | undefined;
|
|
382
393
|
get firstConnectionTime(): number | undefined;
|
|
394
|
+
get lastConnectionTime(): number | undefined;
|
|
383
395
|
getState: () => State;
|
|
384
396
|
sendSignal: (signal: Readonly<string>) => void;
|
|
385
397
|
getStatistics: () => ConnectionStatistics;
|
|
386
398
|
private onMessage;
|
|
387
399
|
private handleMessage;
|
|
388
|
-
connect: () => void;
|
|
400
|
+
connect: (connectionsCount: 1 | 2) => void;
|
|
389
401
|
private onTransportChange;
|
|
390
402
|
disconnect: (reason?: string) => void;
|
|
391
403
|
reconnect: (reason: string) => void;
|
|
@@ -451,8 +463,8 @@ declare class RenditionsModule {
|
|
|
451
463
|
constructor(emitter: Emitter<RenditionsModuleListeners, RenditionsModuleEvents>, subscriptionSource: SubscriptionSource);
|
|
452
464
|
unload: () => void;
|
|
453
465
|
static create: (emitter: Emitter<RenditionsModuleListeners, RenditionsModuleEvents>, subscriptionSource: SubscriptionSource) => RenditionsModule;
|
|
454
|
-
getRenditionLevels: () => ReadonlyArray<RenditionLevel>;
|
|
455
|
-
getRenditionLevel: (
|
|
466
|
+
getRenditionLevels: (subscription?: Readonly<Subscription> | undefined) => ReadonlyArray<RenditionLevel>;
|
|
467
|
+
getRenditionLevel: (subscription?: Readonly<Subscription> | undefined) => RenditionLevel | undefined;
|
|
456
468
|
setRenditions: (channelId: ChannelId, renditions: Rendition[]) => void;
|
|
457
469
|
getLanguages: () => ReadonlyArray<string>;
|
|
458
470
|
getVideoRendition: (renditionId: number, channelId?: string) => Readonly<VideoRendition> | undefined;
|
|
@@ -462,6 +474,7 @@ declare class RenditionsModule {
|
|
|
462
474
|
private onRenditions;
|
|
463
475
|
private onSubscriptionChanged;
|
|
464
476
|
private updateRenditionLevels;
|
|
477
|
+
private createRenditionLevels;
|
|
465
478
|
private getCurrentSubscription;
|
|
466
479
|
}
|
|
467
480
|
interface Size {
|
|
@@ -485,8 +498,11 @@ declare class SubscriptionModule {
|
|
|
485
498
|
isSwitchingSubscription: () => boolean;
|
|
486
499
|
getTargetSubscription: () => Subscription;
|
|
487
500
|
getCurrentSubscription: () => Subscription;
|
|
488
|
-
|
|
489
|
-
|
|
501
|
+
setSize: (size: Readonly<Size>) => void;
|
|
502
|
+
setVideoConstraint: (constraint: VideoConstraint) => void;
|
|
503
|
+
setAudioConstraint: (constraint: AudioConstraint) => void;
|
|
504
|
+
setVideoBitRate: (bitRate: number) => void;
|
|
505
|
+
setAudioBitRate: (bitRate: number) => void;
|
|
490
506
|
setChannelId: (channelId: string) => void;
|
|
491
507
|
setLanguage: (language: string | undefined) => void;
|
|
492
508
|
setVideoCodec: (videoCodec: VideoCodec | undefined) => void;
|
|
@@ -545,6 +561,7 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
545
561
|
private _channels;
|
|
546
562
|
private createdAt;
|
|
547
563
|
private hasCalledConnect;
|
|
564
|
+
private apiClient;
|
|
548
565
|
private durationSessions;
|
|
549
566
|
constructor(options: Options);
|
|
550
567
|
attach: (container: HTMLElement) => void;
|
|
@@ -573,6 +590,10 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
573
590
|
set maxSize(size: Size);
|
|
574
591
|
get maxBitRate(): number;
|
|
575
592
|
set maxBitRate(bitRate: number);
|
|
593
|
+
get maxVideoBitrate(): number;
|
|
594
|
+
set maxVideoBitrate(bitRate: number);
|
|
595
|
+
get maxAudioBitrate(): number;
|
|
596
|
+
set maxAudioBitrate(bitRate: number);
|
|
576
597
|
get renditionLevels(): ReadonlyArray<RenditionLevel>;
|
|
577
598
|
get currentRenditionLevel(): Readonly<RenditionLevel> | undefined;
|
|
578
599
|
get targetRenditionLevel(): Readonly<RenditionLevel> | undefined;
|
|
@@ -584,10 +605,13 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
584
605
|
get bufferingRatios(): Map<string, number>;
|
|
585
606
|
get timeSpentBuffering(): number;
|
|
586
607
|
get timeActive(): number;
|
|
608
|
+
updateAuthenticationToken: (token: string) => void;
|
|
587
609
|
connect: () => void;
|
|
610
|
+
private connectionInfo;
|
|
588
611
|
private connectHandler;
|
|
589
612
|
private filterRenditions;
|
|
590
613
|
private patchSubscription;
|
|
614
|
+
private isSupportedVideoCodecProfile;
|
|
591
615
|
private supportedAudioCodecs;
|
|
592
616
|
private initializeDecodingModule;
|
|
593
617
|
unload: () => Promise<void>;
|
|
@@ -596,6 +620,7 @@ export declare class Vindral extends Emitter<PublicVindralEvents> {
|
|
|
596
620
|
get uptime(): number;
|
|
597
621
|
getStatistics: () => Statistics;
|
|
598
622
|
private onBufferEvent;
|
|
623
|
+
private alignSizeAndBitRate;
|
|
599
624
|
private get currentSubscription();
|
|
600
625
|
private get targetSubscription();
|
|
601
626
|
private timeToFirstFrame;
|
|
@@ -637,15 +662,30 @@ interface Size {
|
|
|
637
662
|
interface PictureInPictureSizeSource {
|
|
638
663
|
getPictureInPictureSize(): Size | undefined;
|
|
639
664
|
}
|
|
665
|
+
declare type DeepPartial<T> = {
|
|
666
|
+
[P in keyof T]?: DeepPartial<T[P]>;
|
|
667
|
+
};
|
|
640
668
|
interface ConstraintCapModuleEvents {
|
|
641
|
-
["constraint cap changed"]: Readonly<
|
|
669
|
+
["constraint cap changed"]: Readonly<ConstraintCap>;
|
|
642
670
|
}
|
|
643
671
|
interface ConstraintCapModuleListeners {
|
|
644
672
|
["enter picture in picture"]: Readonly<PictureInPictureSizeSource>;
|
|
645
673
|
["exit picture in picture"]: void;
|
|
646
674
|
}
|
|
675
|
+
interface VideoConstraintCap {
|
|
676
|
+
width: number;
|
|
677
|
+
height: number;
|
|
678
|
+
bitRate: number;
|
|
679
|
+
}
|
|
680
|
+
interface AudioConstraintCap {
|
|
681
|
+
bitRate: number;
|
|
682
|
+
}
|
|
683
|
+
interface ConstraintCap {
|
|
684
|
+
video: VideoConstraintCap;
|
|
685
|
+
audio: AudioConstraintCap;
|
|
686
|
+
}
|
|
647
687
|
interface ConstraintCapStatistics {
|
|
648
|
-
constraintCap?:
|
|
688
|
+
constraintCap?: ConstraintCap;
|
|
649
689
|
windowInnerWidth: number;
|
|
650
690
|
windowInnerHeight: number;
|
|
651
691
|
elementWidth: number;
|
|
@@ -666,17 +706,20 @@ declare class ConstraintCapModule {
|
|
|
666
706
|
private renditionLevelSource;
|
|
667
707
|
private resizeObserver?;
|
|
668
708
|
private elementSize;
|
|
669
|
-
private
|
|
709
|
+
private _sizeBasedResolutionCapEnabled;
|
|
670
710
|
constructor(emitter: Emitter<ConstraintCapModuleListeners, ConstraintCapModuleEvents>, element: HTMLElement, renditionLevelSource: RenditionLevelSource, sizeBasedResolutionCapEnabled: boolean);
|
|
671
711
|
unload: () => void;
|
|
672
712
|
load: () => void;
|
|
673
713
|
static create: (emitter: Emitter<ConstraintCapModuleListeners, ConstraintCapModuleEvents>, element: HTMLElement, renditionLevelSource: RenditionLevelSource, sizeBasedResolutionCapEnabled: boolean) => ConstraintCapModule;
|
|
674
714
|
unsuspend: () => void;
|
|
675
715
|
suspend: () => void;
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
716
|
+
get sizeBasedResolutionCapEnabled(): boolean;
|
|
717
|
+
set sizeBasedResolutionCapEnabled(enabled: boolean);
|
|
718
|
+
setUserSpecifiedCap: (cap: DeepPartial<ConstraintCap>) => void;
|
|
719
|
+
getUserSpecifiedCap: () => ConstraintCap | undefined;
|
|
720
|
+
getCurrentConstraintCap: () => ConstraintCap | undefined;
|
|
679
721
|
getStatistics: () => ConstraintCapStatistics;
|
|
722
|
+
constrainSubscription: (subscription: Subscription) => Subscription;
|
|
680
723
|
private onResize;
|
|
681
724
|
private evaluateConstraintCap;
|
|
682
725
|
private enterPictureInPicture;
|
|
@@ -906,6 +949,7 @@ interface QualityOfServiceModuleEvents {
|
|
|
906
949
|
interface QualityOfServiceModuleStatistics {
|
|
907
950
|
timeSpentBuffering: number;
|
|
908
951
|
bufferingEventsCount: number;
|
|
952
|
+
fatalQosCount: number;
|
|
909
953
|
timeSpentRatio: {
|
|
910
954
|
[bitRate: string]: number;
|
|
911
955
|
};
|
|
@@ -919,6 +963,7 @@ declare class QualityOfServiceModule {
|
|
|
919
963
|
private bufferFullnessRegression?;
|
|
920
964
|
private currentLevel?;
|
|
921
965
|
private isSuspended;
|
|
966
|
+
private _fatalQosCount;
|
|
922
967
|
private hasAsserted;
|
|
923
968
|
constructor(emitter: Emitter<QualityOfServiceModuleEvents>, logger: Logger);
|
|
924
969
|
static create: (emitter: Emitter<QualityOfServiceModuleEvents>, logger: Logger) => QualityOfServiceModule;
|
|
@@ -926,6 +971,9 @@ declare class QualityOfServiceModule {
|
|
|
926
971
|
unload: () => void;
|
|
927
972
|
suspend: () => void;
|
|
928
973
|
unsuspend: () => void;
|
|
974
|
+
fatalQosGraceTime: () => number;
|
|
975
|
+
get fatalQosCount(): number;
|
|
976
|
+
incrementFatalQosCount: () => void;
|
|
929
977
|
getMetrics: () => Metrics;
|
|
930
978
|
getLevelStats: (renditionLevel: RenditionLevel) => PerLevelStats | undefined;
|
|
931
979
|
getBufferFullnessRegression: () => Regression | undefined;
|
|
@@ -974,20 +1022,25 @@ interface SyncModuleStatistics {
|
|
|
974
1022
|
discardedTimeInfoCount: number;
|
|
975
1023
|
}
|
|
976
1024
|
declare class SyncModule {
|
|
977
|
-
private static INCREASE_MAX_BEHIND_EVERY;
|
|
978
1025
|
private emitter;
|
|
979
1026
|
private logger;
|
|
980
1027
|
private playbackSource;
|
|
981
1028
|
private bufferSource;
|
|
982
1029
|
private lastSeekTime;
|
|
983
1030
|
readonly seekCooldownTime = 5000;
|
|
984
|
-
readonly
|
|
985
|
-
readonly
|
|
986
|
-
|
|
1031
|
+
readonly syncMaxBehind: number;
|
|
1032
|
+
readonly syncMaxBehindMultiplierStep = 1;
|
|
1033
|
+
readonly syncMaxBehindIncreaseEvery = 5;
|
|
1034
|
+
readonly syncMaxBehindMaximumAllowed = 1000;
|
|
987
1035
|
syncMaxBehindMultiplier: number;
|
|
988
|
-
readonly playbackRateMaxBehind = 1000;
|
|
989
1036
|
readonly syncMaxAhead = 150;
|
|
990
|
-
readonly
|
|
1037
|
+
readonly playbackRateSyncConstants: {
|
|
1038
|
+
readonly enabled: true;
|
|
1039
|
+
readonly maxBehind: 1000;
|
|
1040
|
+
readonly catchupRate: 1.05;
|
|
1041
|
+
readonly slowdownRate: 0.95;
|
|
1042
|
+
};
|
|
1043
|
+
readonly maxTimeSyncDifferenceTolerance = 150;
|
|
991
1044
|
private timers;
|
|
992
1045
|
private rtt;
|
|
993
1046
|
private channelSyncInfo;
|
|
@@ -1029,12 +1082,12 @@ declare class SyncModule {
|
|
|
1029
1082
|
}
|
|
1030
1083
|
interface TelemetryModuleOptions {
|
|
1031
1084
|
url: string;
|
|
1032
|
-
interval
|
|
1033
|
-
includeErrors
|
|
1034
|
-
includeEvents
|
|
1035
|
-
includeStats
|
|
1036
|
-
maxRetries
|
|
1037
|
-
maxErrorReports
|
|
1085
|
+
interval?: number;
|
|
1086
|
+
includeErrors?: boolean;
|
|
1087
|
+
includeEvents?: boolean;
|
|
1088
|
+
includeStats?: boolean;
|
|
1089
|
+
maxRetries?: number;
|
|
1090
|
+
maxErrorReports?: number;
|
|
1038
1091
|
}
|
|
1039
1092
|
interface FlushOptions {
|
|
1040
1093
|
isFinal?: boolean;
|
|
@@ -1139,8 +1192,9 @@ export interface ReconnectState {
|
|
|
1139
1192
|
reconnectRetries: number;
|
|
1140
1193
|
}
|
|
1141
1194
|
export interface AdvancedOptions {
|
|
1142
|
-
wasmDecodingConstraint: Partial<
|
|
1195
|
+
wasmDecodingConstraint: Partial<VideoConstraint>;
|
|
1143
1196
|
}
|
|
1197
|
+
export declare type Media = "audio" | "video" | "audio+video";
|
|
1144
1198
|
export interface Options {
|
|
1145
1199
|
url: string;
|
|
1146
1200
|
channelId: string;
|
|
@@ -1157,7 +1211,8 @@ export interface Options {
|
|
|
1157
1211
|
mseOpusEnabled?: boolean;
|
|
1158
1212
|
abrEnabled?: boolean;
|
|
1159
1213
|
maxSize?: Size;
|
|
1160
|
-
|
|
1214
|
+
maxAudioBitRate?: number;
|
|
1215
|
+
maxVideoBitRate?: number;
|
|
1161
1216
|
muted?: boolean;
|
|
1162
1217
|
reconnectHandler?: (state: ReconnectState) => Promise<boolean> | boolean;
|
|
1163
1218
|
tags?: string[];
|
|
@@ -1166,6 +1221,7 @@ export interface Options {
|
|
|
1166
1221
|
logShippingEnabled?: boolean;
|
|
1167
1222
|
statsShippingEnabled?: boolean;
|
|
1168
1223
|
advanced?: AdvancedOptions;
|
|
1224
|
+
media?: Media;
|
|
1169
1225
|
}
|
|
1170
1226
|
export interface PlaybackSource {
|
|
1171
1227
|
volume: number;
|
|
@@ -1185,6 +1241,7 @@ export interface PublicVindralEvents {
|
|
|
1185
1241
|
["rendition levels"]: ReadonlyArray<RenditionLevel>;
|
|
1186
1242
|
["rendition level"]: Readonly<RenditionLevel>;
|
|
1187
1243
|
["languages"]: ReadonlyArray<string>;
|
|
1244
|
+
["channels"]: ReadonlyArray<Channel>;
|
|
1188
1245
|
["server wallclock time"]: Readonly<number>;
|
|
1189
1246
|
["buffer state event"]: Readonly<BufferStateEvent>;
|
|
1190
1247
|
["initialized media"]: void;
|
|
@@ -1230,24 +1287,33 @@ export declare type Rendition = VideoRendition | AudioRendition;
|
|
|
1230
1287
|
export declare const isVideoRendition: (rendition: Readonly<Rendition>) => rendition is VideoRendition;
|
|
1231
1288
|
export declare const isAudioRendition: (rendition: Readonly<Rendition>) => rendition is AudioRendition;
|
|
1232
1289
|
export declare const getMimeType: (rendition: Readonly<Rendition>) => string;
|
|
1233
|
-
interface
|
|
1290
|
+
interface AudioConstraint {
|
|
1291
|
+
bitRate: number;
|
|
1292
|
+
codec?: AudioCodec;
|
|
1293
|
+
codecString?: string;
|
|
1294
|
+
language?: string;
|
|
1295
|
+
}
|
|
1296
|
+
interface VideoConstraint {
|
|
1234
1297
|
width: number;
|
|
1235
1298
|
height: number;
|
|
1236
1299
|
bitRate: number;
|
|
1300
|
+
codec?: VideoCodec;
|
|
1301
|
+
codecString?: string;
|
|
1237
1302
|
}
|
|
1238
1303
|
declare type SubscriptionInitiator = "manual" | "edge";
|
|
1239
1304
|
interface Subscription {
|
|
1240
1305
|
channelId: string;
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
language?: string;
|
|
1306
|
+
video: VideoConstraint;
|
|
1307
|
+
audio: AudioConstraint;
|
|
1244
1308
|
meta?: Record<string, string>;
|
|
1245
|
-
constraint: Constraint;
|
|
1246
1309
|
initiator?: SubscriptionInitiator;
|
|
1247
1310
|
}
|
|
1248
1311
|
interface ContextSwitch {
|
|
1249
1312
|
type: "context switch";
|
|
1250
1313
|
}
|
|
1314
|
+
interface ContextSwitchComplete {
|
|
1315
|
+
type: "context switch complete";
|
|
1316
|
+
}
|
|
1251
1317
|
interface RenditionsSignal {
|
|
1252
1318
|
type: "renditions";
|
|
1253
1319
|
renditions: Rendition[];
|
|
@@ -1278,35 +1344,33 @@ interface PingSignal {
|
|
|
1278
1344
|
interface PongSignal {
|
|
1279
1345
|
type: "pong";
|
|
1280
1346
|
}
|
|
1281
|
-
|
|
1347
|
+
interface RefreshAuthSignal {
|
|
1348
|
+
type: "refresh auth";
|
|
1349
|
+
token: string;
|
|
1350
|
+
}
|
|
1351
|
+
declare type Signal = RenditionsSignal | SubscribeSignal | SubscriptionChangedSignal | TimingInfoSignal | PingSignal | PongSignal | ClientIpSignal | ContextSwitch | ContextSwitchComplete | RefreshAuthSignal;
|
|
1282
1352
|
export interface Channel {
|
|
1283
|
-
|
|
1353
|
+
channelId: string;
|
|
1284
1354
|
name: string;
|
|
1285
1355
|
isLive: boolean;
|
|
1286
|
-
|
|
1356
|
+
thumbnailUrls: string[];
|
|
1287
1357
|
}
|
|
1288
|
-
|
|
1358
|
+
interface ChannelWithRenditions extends Channel {
|
|
1289
1359
|
renditions: Rendition[];
|
|
1290
|
-
} & Channel;
|
|
1291
|
-
export interface ChannelsApi {
|
|
1292
|
-
getChannelGroup: (channelGroupId: string) => Promise<Channel[]>;
|
|
1293
1360
|
}
|
|
1294
|
-
interface
|
|
1361
|
+
interface ConnectOptions {
|
|
1295
1362
|
channelGroupId?: string;
|
|
1296
1363
|
channelId: string;
|
|
1297
1364
|
}
|
|
1298
|
-
interface ConnectApi {
|
|
1299
|
-
get: (connectInfo: ConnectInfo) => Promise<ConnectResponse>;
|
|
1300
|
-
}
|
|
1301
1365
|
interface Telemetry {
|
|
1302
|
-
probability: number;
|
|
1303
1366
|
url: string;
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1367
|
+
probability?: number;
|
|
1368
|
+
includeErrors?: boolean;
|
|
1369
|
+
includeEvents?: boolean;
|
|
1370
|
+
includeStats?: boolean;
|
|
1371
|
+
maxRetries?: number;
|
|
1372
|
+
maxErrorReports?: number;
|
|
1373
|
+
interval?: number;
|
|
1310
1374
|
}
|
|
1311
1375
|
export interface ConnectResponse {
|
|
1312
1376
|
logsUrl?: string;
|
|
@@ -1315,10 +1379,26 @@ export interface ConnectResponse {
|
|
|
1315
1379
|
channels: ChannelWithRenditions[];
|
|
1316
1380
|
edges: string[];
|
|
1317
1381
|
}
|
|
1318
|
-
export
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
}
|
|
1382
|
+
export interface ApiClientOptions {
|
|
1383
|
+
publicEndpoint: string;
|
|
1384
|
+
tokenFactory?: AuthorizationTokenFactory;
|
|
1385
|
+
}
|
|
1386
|
+
export interface AuthorizationContext {
|
|
1387
|
+
channelGroupId?: string;
|
|
1388
|
+
channelId?: string;
|
|
1389
|
+
}
|
|
1390
|
+
export declare type AuthorizationTokenFactory = (context: AuthorizationContext) => string | undefined;
|
|
1391
|
+
export declare class ApiClient {
|
|
1392
|
+
private baseUrl;
|
|
1393
|
+
private tokenFactory?;
|
|
1394
|
+
constructor(options: ApiClientOptions);
|
|
1395
|
+
connect(options: ConnectOptions): Promise<ConnectResponse>;
|
|
1396
|
+
getChannel(channelId: string): Promise<Channel>;
|
|
1397
|
+
getChannels(channelGroupId: string): Promise<Channel[]>;
|
|
1398
|
+
private getAuthToken;
|
|
1399
|
+
private toChannels;
|
|
1400
|
+
private toChannel;
|
|
1401
|
+
}
|
|
1322
1402
|
interface FullscreenEvents {
|
|
1323
1403
|
["on fullscreen change"]: boolean;
|
|
1324
1404
|
}
|
|
@@ -1336,6 +1416,12 @@ declare class Fullscreen extends Emitter<FullscreenEvents> {
|
|
|
1336
1416
|
}
|
|
1337
1417
|
export interface PlayerOptions {
|
|
1338
1418
|
controlsEnabled?: boolean;
|
|
1419
|
+
fullscreenButtonEnabled?: boolean;
|
|
1420
|
+
pipButtonEnabled?: boolean;
|
|
1421
|
+
channelSelectionEnabled?: boolean;
|
|
1422
|
+
renditionLevelsEnabled?: boolean;
|
|
1423
|
+
languagesButtonEnabled?: boolean;
|
|
1424
|
+
oneToOneButtonEnabled?: boolean;
|
|
1339
1425
|
hideTimeout?: number;
|
|
1340
1426
|
}
|
|
1341
1427
|
export interface PlayerState {
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vindral/web-sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"homepage": "https://vindral.com",
|
|
5
5
|
"description": "Web SDK for viewing Vindral streams",
|
|
6
6
|
"license": "SEE LICENSE IN https://www.vindral.com/terms-conditions",
|
|
7
7
|
"author": "RealSprint",
|
|
8
8
|
"files": [
|
|
9
9
|
"README.md",
|
|
10
|
+
"LICENSES",
|
|
10
11
|
"web-sdk.esm.js",
|
|
11
12
|
"web-sdk.umd.js",
|
|
12
13
|
"index.d.ts"
|