@vkontakte/videoplayer-core 2.0.160-dev.ff8ccb48.0 → 2.0.161-beta.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/es2015.cjs +13 -11
- package/es2015.esm.js +20 -18
- package/esnext.cjs +13 -11
- package/esnext.esm.js +14 -12
- package/evergreen.esm.js +34 -32
- package/package.json +2 -2
- package/types/providers/DashProvider/baseDashProvider.d.ts +1 -0
- package/types/providers/DashProvider/lib/buffer.d.ts +1 -0
- package/types/providers/DashProvider/lib/fetcher.d.ts +9 -1
- package/types/providers/DashProvider/lib/player.d.ts +4 -0
- package/types/providers/DashProvider/lib/processNetworkErrors.d.ts +9 -0
- package/types/providers/DashProvider/lib/urlsCache.d.ts +23 -0
- package/types/providers/DashProviderVirtual/baseDashProvider.d.ts +1 -0
- package/types/providers/DashProviderVirtual/lib/buffer/nativeBufferManager.d.ts +2 -1
- package/types/providers/DashProviderVirtual/lib/buffer/types.d.ts +2 -1
- package/types/providers/DashProviderVirtual/lib/buffer/virtualBuffer/baseVirtualBufferManager.d.ts +2 -2
- package/types/providers/DashProviderVirtual/lib/fetcher.d.ts +9 -1
- package/types/providers/DashProviderVirtual/lib/player/basePlayer.d.ts +5 -2
- package/types/providers/DashProviderVirtual/lib/player/livePlayer.d.ts +1 -1
- package/types/providers/DashProviderVirtual/lib/player/player.d.ts +1 -1
- package/types/providers/DashProviderVirtual/lib/player/types.d.ts +1 -0
- package/types/providers/DashProviderVirtual/lib/processNetworkErrors.d.ts +9 -0
- package/types/providers/DashProviderVirtual/lib/urlsCache.d.ts +22 -0
- package/types/providers/HlsProvider/index.d.ts +4 -2
- package/types/providers/MpegProvider/index.d.ts +1 -1
- package/types/providers/ProviderContainer/index.d.ts +5 -1
- package/types/providers/ProviderContainer/types.d.ts +5 -1
- package/types/providers/utils/Abr/rules/video/upperLimitRule.d.ts +59 -2
- package/types/utils/StatefulIterator/index.d.ts +3 -0
- package/types/utils/ThroughputEstimator.d.ts +4 -2
- package/types/utils/tuningConfig.d.ts +55 -1
- package/types/utils/videoFormat.d.ts +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vkontakte/videoplayer-core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.161-beta.0",
|
|
4
4
|
"author": "vk.com",
|
|
5
5
|
"description": "Videoplayer core library based on the vk.com platform",
|
|
6
6
|
"homepage": "https://vk.com",
|
|
@@ -42,6 +42,6 @@
|
|
|
42
42
|
"**/*.d.ts"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@vkontakte/videoplayer-shared": "1.0.
|
|
45
|
+
"@vkontakte/videoplayer-shared": "1.0.90-beta.0"
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -18,6 +18,7 @@ type IParams = IProviderParams<IDashURLSource> & {
|
|
|
18
18
|
sourceHls?: IHLSSource;
|
|
19
19
|
forceVideoCodec?: VideoCodec;
|
|
20
20
|
failedVideoTrack?: Nullable<IVideoTrack>;
|
|
21
|
+
isOnDemand?: boolean;
|
|
21
22
|
};
|
|
22
23
|
export default abstract class BaseDashProvider implements IProvider {
|
|
23
24
|
scene3D: Scene3D | undefined;
|
|
@@ -22,6 +22,9 @@ export interface IParams {
|
|
|
22
22
|
compatibilityMode?: boolean;
|
|
23
23
|
tracer: ITracer;
|
|
24
24
|
useEnableSubtitlesParam?: boolean;
|
|
25
|
+
handleExtendedNetworkErrorsSet?: boolean;
|
|
26
|
+
useUrlCacheMechanism?: boolean;
|
|
27
|
+
measureNonSegmentRequests?: boolean;
|
|
25
28
|
}
|
|
26
29
|
export type Priority = "high" | "low" | "auto";
|
|
27
30
|
export interface FetchParamsWithUrl extends FetchParams {
|
|
@@ -38,6 +41,7 @@ export interface FetchParams {
|
|
|
38
41
|
isLowLatency?: boolean;
|
|
39
42
|
bufferOptimisation?: boolean;
|
|
40
43
|
ignoreNetworkErrors?: boolean;
|
|
44
|
+
urlCacheMechanismEnabled?: boolean;
|
|
41
45
|
}
|
|
42
46
|
export type RepresentationFetchResult = {
|
|
43
47
|
init: CommonInit | null;
|
|
@@ -63,9 +67,13 @@ export declare class Fetcher {
|
|
|
63
67
|
private readonly subscription;
|
|
64
68
|
private compatibilityMode;
|
|
65
69
|
private useEnableSubtitlesParam;
|
|
70
|
+
private useUrlCacheMechanism;
|
|
71
|
+
private measureNonSegmentRequests;
|
|
72
|
+
private startupPhase;
|
|
66
73
|
private performanceObserver;
|
|
67
74
|
private pendingConnectionMetrics;
|
|
68
|
-
|
|
75
|
+
private handleExtendedNetworkErrorsSet;
|
|
76
|
+
constructor({ throughputEstimator, requestQuic, tracer, compatibilityMode, useEnableSubtitlesParam, handleExtendedNetworkErrorsSet, useUrlCacheMechanism, measureNonSegmentRequests }: IParams);
|
|
69
77
|
private onHeadersReceived;
|
|
70
78
|
private setupPerformanceObserver;
|
|
71
79
|
private processPerformanceResourceTiming;
|
|
@@ -19,6 +19,7 @@ export interface Params {
|
|
|
19
19
|
compatibilityMode?: boolean;
|
|
20
20
|
forceVideoCodec?: VideoCodec;
|
|
21
21
|
tracer: ITracer;
|
|
22
|
+
isOnDemand: boolean;
|
|
22
23
|
}
|
|
23
24
|
export declare class Player {
|
|
24
25
|
private element;
|
|
@@ -81,6 +82,7 @@ export declare class Player {
|
|
|
81
82
|
private stallWatchdogSubscription;
|
|
82
83
|
private livePauseWatchdogSubscription;
|
|
83
84
|
private liveWasInterrupted;
|
|
85
|
+
private isOnDemand;
|
|
84
86
|
private destroyController;
|
|
85
87
|
constructor(params: Params);
|
|
86
88
|
initManifest: ReturnType<typeof abortable<[HTMLVideoElement, string, number]>>;
|
|
@@ -113,4 +115,6 @@ export declare class Player {
|
|
|
113
115
|
* Возвращает duration в милисекундах.
|
|
114
116
|
*/
|
|
115
117
|
calculateDurationFromSegments(): number;
|
|
118
|
+
private isAnyBufferUpdating;
|
|
119
|
+
updateSourceDurationFromSegments(): void;
|
|
116
120
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IError, ISubject } from "@vkontakte/videoplayer-shared";
|
|
2
|
+
type Params = {
|
|
3
|
+
txtCode: string;
|
|
4
|
+
error$: ISubject<IError>;
|
|
5
|
+
recoverableError$: ISubject<IError>;
|
|
6
|
+
httpCode?: number | undefined;
|
|
7
|
+
};
|
|
8
|
+
export declare const processNetworkErrors: ({ txtCode, error$, recoverableError$, httpCode }: Params) => void;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type CacheManager = {
|
|
2
|
+
get: () => Promise<Response | null>;
|
|
3
|
+
set: (response: Response) => void;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Пытаемся добиться кэширования вызовов.
|
|
7
|
+
* Сейчас есть проблема, что expires и sig меняются, хотя контент не меняется, поэтому ходим мимо кэша.
|
|
8
|
+
* Из за этого обрабатываем кэш вручную.
|
|
9
|
+
*/
|
|
10
|
+
export declare const createCacheManager: (url: string) => Promise<CacheManager>;
|
|
11
|
+
export declare function canUseCacheApi(): boolean;
|
|
12
|
+
export declare function normalizeUrl(url: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Проверяет, не просрочен ли кэшированный ответ
|
|
15
|
+
*/
|
|
16
|
+
export declare function isResponseExpired(response: Response): boolean;
|
|
17
|
+
export declare function cloneResponse(response: Response, url: string): Response;
|
|
18
|
+
/**
|
|
19
|
+
* Извлекает expires из оригинального URL (параметр expires1)
|
|
20
|
+
* Предполагается, что expires1 — timestamp в секундах
|
|
21
|
+
*/
|
|
22
|
+
export declare function getExpiresFromUrl(url: string): number;
|
|
23
|
+
export declare const dropUrlsCache: () => Promise<void>;
|
|
@@ -18,6 +18,7 @@ type IParams = IProviderParams<IDashURLSource> & {
|
|
|
18
18
|
sourceHls?: IHLSSource;
|
|
19
19
|
forceVideoCodec?: VideoCodec;
|
|
20
20
|
failedVideoTrack?: Nullable<IVideoTrack>;
|
|
21
|
+
isOnDemand?: boolean;
|
|
21
22
|
};
|
|
22
23
|
export default abstract class BaseDashProvider implements IProvider {
|
|
23
24
|
scene3D: Scene3D | undefined;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { IError, IRange, ISubject, Milliseconds } from "@vkontakte/videoplayer-shared";
|
|
1
|
+
import type { IError, IRange, ISubject, IValueSubject, Milliseconds } from "@vkontakte/videoplayer-shared";
|
|
2
2
|
export declare class NativeBufferManager {
|
|
3
3
|
error$: ISubject<IError>;
|
|
4
|
+
updateEnd$: IValueSubject<void>;
|
|
4
5
|
private mediaSource;
|
|
5
6
|
private sourceBuffer;
|
|
6
7
|
private sourceBufferTaskQueue;
|
|
@@ -32,10 +32,11 @@ export interface IVirtualBufferManager<T extends Segment = Segment> {
|
|
|
32
32
|
getForwardBufferRepresentations(currentPosition?: Milliseconds): Map<Representation["id"], T[]>;
|
|
33
33
|
getForwardPlaybackBufferDuration(currentPosition?: Milliseconds): Milliseconds;
|
|
34
34
|
getPlaybackBufferState(): IRange<Milliseconds> | null;
|
|
35
|
+
getMutexInfo(): string;
|
|
35
36
|
setTarget(time: Milliseconds): void;
|
|
36
37
|
setPreloadOnly(preloadOnly: boolean): void;
|
|
37
38
|
findSegmentStartTime(position: Milliseconds): Milliseconds | undefined;
|
|
38
|
-
calculateDurationFromSegments(
|
|
39
|
+
calculateDurationFromSegments(): Milliseconds;
|
|
39
40
|
destroy(): void;
|
|
40
41
|
get lastDataObtainedTimestamp(): Milliseconds;
|
|
41
42
|
}
|
package/types/providers/DashProviderVirtual/lib/buffer/virtualBuffer/baseVirtualBufferManager.d.ts
CHANGED
|
@@ -59,7 +59,6 @@ export declare abstract class BaseVirtualBufferManager<T extends Segment> implem
|
|
|
59
59
|
startWith: ReturnType<typeof abortable<[Representation["id"]]>>;
|
|
60
60
|
switchTo(newRepresentationId: Representation["id"], mode?: SwithRepresentationMode): Promise<void>;
|
|
61
61
|
protected getSwitchWithAbort(): ReturnType<typeof abortable<[Representation["id"], SwithRepresentationMode], void>>;
|
|
62
|
-
switchToOld: ReturnType<typeof abortable<[Representation["id"], boolean | undefined], void>>;
|
|
63
62
|
prepareSeek(): Promise<void>;
|
|
64
63
|
seek(position: Milliseconds | undefined): Promise<void>;
|
|
65
64
|
maintain(currentPosition?: Milliseconds | undefined): Promise<void>;
|
|
@@ -69,7 +68,8 @@ export declare abstract class BaseVirtualBufferManager<T extends Segment> implem
|
|
|
69
68
|
abort(): Promise<void>;
|
|
70
69
|
findSegmentStartTime(position: Milliseconds): Milliseconds | undefined;
|
|
71
70
|
getRepresentationInitialTime(): Seconds;
|
|
72
|
-
|
|
71
|
+
getMutexInfo(): string;
|
|
72
|
+
calculateDurationFromSegments(): Milliseconds;
|
|
73
73
|
get lastDataObtainedTimestamp(): Milliseconds;
|
|
74
74
|
setTarget(time: Milliseconds): void;
|
|
75
75
|
setPreloadOnly(preloadOnly: boolean): void;
|
|
@@ -22,6 +22,9 @@ export interface IParams {
|
|
|
22
22
|
compatibilityMode?: boolean;
|
|
23
23
|
tracer: ITracer;
|
|
24
24
|
useEnableSubtitlesParam?: boolean;
|
|
25
|
+
handleExtendedNetworkErrorsSet?: boolean;
|
|
26
|
+
useUrlCacheMechanism?: boolean;
|
|
27
|
+
measureNonSegmentRequests?: boolean;
|
|
25
28
|
}
|
|
26
29
|
export type Priority = "high" | "low" | "auto";
|
|
27
30
|
export interface FetchParamsWithUrl extends FetchParams {
|
|
@@ -37,6 +40,7 @@ export interface FetchParams {
|
|
|
37
40
|
measureThroughput?: boolean;
|
|
38
41
|
isLowLatency?: boolean;
|
|
39
42
|
bufferOptimisation?: boolean;
|
|
43
|
+
urlCacheMechanismEnabled?: boolean;
|
|
40
44
|
}
|
|
41
45
|
export type RepresentationFetchResult<T extends Segment> = {
|
|
42
46
|
initMetadata: CommonInit | null;
|
|
@@ -62,9 +66,13 @@ export declare class Fetcher {
|
|
|
62
66
|
private subscription;
|
|
63
67
|
private compatibilityMode;
|
|
64
68
|
private useEnableSubtitlesParam;
|
|
69
|
+
private useUrlCacheMechanism;
|
|
70
|
+
private measureNonSegmentRequests;
|
|
71
|
+
private startupPhase;
|
|
65
72
|
private performanceObserver;
|
|
66
73
|
private pendingConnectionMetrics;
|
|
67
|
-
|
|
74
|
+
private handleExtendedNetworkErrorsSet;
|
|
75
|
+
constructor({ throughputEstimator, requestQuic, tracer, compatibilityMode, useEnableSubtitlesParam, handleExtendedNetworkErrorsSet, useUrlCacheMechanism, measureNonSegmentRequests }: IParams);
|
|
68
76
|
private onHeadersReceived;
|
|
69
77
|
private setupPerformanceObserver;
|
|
70
78
|
private processResourceTiming;
|
|
@@ -70,9 +70,10 @@ export declare abstract class BasePlayer {
|
|
|
70
70
|
videoLastDataObtainedTimestamp$: IValueSubject<Milliseconds>;
|
|
71
71
|
fetcherRecoverableError$: Subject<IError>;
|
|
72
72
|
fetcherError$: Subject<IError>;
|
|
73
|
+
private isOnDemand;
|
|
73
74
|
protected constructor(params: Params);
|
|
74
75
|
protected abstract prepareManifestUrlString(manifestBaseUrlString: string, offset: number): string;
|
|
75
|
-
protected abstract
|
|
76
|
+
protected abstract setSourceInitDuration(): void;
|
|
76
77
|
protected abstract restoreAfterDeepStall(stallTraceAttributes: Record<string, number>): Promise<void>;
|
|
77
78
|
initRepresentations: ReturnType<typeof abortable<[Representation["id"], Representation["id"] | undefined, IHLSSource | undefined]>>;
|
|
78
79
|
initManifest(element: HTMLVideoElement, manifestBaseUrlString: string, offset: number): Promise<void>;
|
|
@@ -81,7 +82,6 @@ export declare abstract class BasePlayer {
|
|
|
81
82
|
seek(requestedPosition: Milliseconds, forcePrecise?: boolean): Promise<void>;
|
|
82
83
|
warmUpMediaSourceIfNeeded(position?: Milliseconds | undefined): void;
|
|
83
84
|
getForwardBufferRepresentations(kind: Exclude<StreamKind, StreamKind.TEXT>): Map<Representation["id"], Segment[]> | undefined;
|
|
84
|
-
calculateDurationFromSegments(representationId: Representation["id"]): Milliseconds;
|
|
85
85
|
get isStreamEnded(): boolean;
|
|
86
86
|
getStreams(): Manifest["streams"] | undefined;
|
|
87
87
|
getCodecs(): Manifest["codecs"] | undefined;
|
|
@@ -89,6 +89,9 @@ export declare abstract class BasePlayer {
|
|
|
89
89
|
setPreloadOnly(preloadOnly: boolean): void;
|
|
90
90
|
stop(): void;
|
|
91
91
|
destroy(): void;
|
|
92
|
+
updateSourceDurationFromSegments(): void;
|
|
93
|
+
calculateDurationFromBuffersSegments(): Milliseconds;
|
|
94
|
+
private isAnyBufferUpdating;
|
|
92
95
|
protected get isStreamNotOpen(): boolean;
|
|
93
96
|
protected reinitDecoderIfNeeded(force?: boolean): Promise<void>;
|
|
94
97
|
protected stallWatchdogIntervalCallback(): Promise<void>;
|
|
@@ -18,7 +18,7 @@ export declare class LivePlayer extends BasePlayer {
|
|
|
18
18
|
initBuffer(): void;
|
|
19
19
|
protected forcePositionToRepresentationInitialTime(): Promise<void>;
|
|
20
20
|
protected tick(): Promise<void>;
|
|
21
|
-
protected
|
|
21
|
+
protected setSourceInitDuration(): void;
|
|
22
22
|
protected isStallExceeded(timeInWaiting: Milliseconds): boolean;
|
|
23
23
|
protected restoreAfterDeepStall(stallTraceAttributes: Record<string, number>): Promise<void>;
|
|
24
24
|
protected updateManifest(): Promise<Manifest | null>;
|
|
@@ -4,7 +4,7 @@ export declare class Player extends BasePlayer {
|
|
|
4
4
|
constructor(params: Params);
|
|
5
5
|
protected prepareManifestUrlString(manifestBaseUrlString: string, _offset: number): string;
|
|
6
6
|
protected initRepresentationSubscriptions(): void;
|
|
7
|
-
protected
|
|
7
|
+
protected setSourceInitDuration(): void;
|
|
8
8
|
protected restoreAfterDeepStall(stallTraceAttributes: Record<string, number>): Promise<void>;
|
|
9
9
|
protected initDisableStallWatchdogSubscription(): void;
|
|
10
10
|
protected initEndOfVideoSubscription(): void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IError, ISubject } from "@vkontakte/videoplayer-shared";
|
|
2
|
+
type Params = {
|
|
3
|
+
txtCode: string;
|
|
4
|
+
error$: ISubject<IError>;
|
|
5
|
+
recoverableError$: ISubject<IError>;
|
|
6
|
+
httpCode?: number | undefined;
|
|
7
|
+
};
|
|
8
|
+
export declare const processNetworkErrors: ({ txtCode, error$, recoverableError$, httpCode }: Params) => void;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type CacheManager = {
|
|
2
|
+
get: () => Promise<Response | null>;
|
|
3
|
+
set: (response: Response) => Promise<void>;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Пытаемся добиться кэширования вызовов.
|
|
7
|
+
* Сейчас есть проблема, что expires и sig меняются, хотя контент не меняется, поэтому ходим мимо кэша.
|
|
8
|
+
* Из за этого обрабатываем кэш вручную.
|
|
9
|
+
*/
|
|
10
|
+
export declare const createCacheManager: (url: string) => Promise<CacheManager>;
|
|
11
|
+
export declare function canUseCacheApi(): boolean;
|
|
12
|
+
export declare function normalizeUrl(url: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Проверяет, не просрочен ли кэшированный ответ
|
|
15
|
+
*/
|
|
16
|
+
export declare function isResponseExpired(response: Response): boolean;
|
|
17
|
+
export declare function cloneResponse(response: Response, url: string): Response;
|
|
18
|
+
/**
|
|
19
|
+
* Извлекает expires из оригинального URL (параметр expires1)
|
|
20
|
+
* Предполагается, что expires1 — timestamp в секундах
|
|
21
|
+
*/
|
|
22
|
+
export declare function getExpiresFromUrl(url: string): number;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { IHLSSource } from "../../player/types";
|
|
2
2
|
import type { IProvider, IProviderParams } from "../types";
|
|
3
|
-
type Params = IProviderParams<IHLSSource
|
|
3
|
+
type Params = IProviderParams<IHLSSource> & {
|
|
4
|
+
isOnDemand: boolean;
|
|
5
|
+
};
|
|
4
6
|
export default class HlsProvider implements IProvider {
|
|
5
7
|
private subscription;
|
|
6
8
|
private volumeSubscription;
|
|
@@ -16,7 +18,7 @@ export default class HlsProvider implements IProvider {
|
|
|
16
18
|
private subscribe;
|
|
17
19
|
destroy(): void;
|
|
18
20
|
private prepare;
|
|
19
|
-
|
|
21
|
+
protected playIfAllowed(): void;
|
|
20
22
|
private seek;
|
|
21
23
|
private syncPlayback;
|
|
22
24
|
}
|
|
@@ -13,7 +13,7 @@ export default class MpegProvider implements IProvider {
|
|
|
13
13
|
private subscribe;
|
|
14
14
|
destroy(): void;
|
|
15
15
|
private prepare;
|
|
16
|
-
|
|
16
|
+
protected playIfAllowed(): void;
|
|
17
17
|
private seek;
|
|
18
18
|
private syncPlayback;
|
|
19
19
|
private handleQualityLimitTransition;
|
|
@@ -19,7 +19,11 @@ interface IParams extends IProviderDependencies {
|
|
|
19
19
|
export default class ProviderContainer implements IProviderContainer {
|
|
20
20
|
current$: IValueSubject<IProviderEntry>;
|
|
21
21
|
providerError$: ISubject<IError>;
|
|
22
|
-
noAvailableProvidersError$: ISubject<
|
|
22
|
+
noAvailableProvidersError$: ISubject<{
|
|
23
|
+
forced?: VideoFormat;
|
|
24
|
+
input: VideoFormat[];
|
|
25
|
+
supported: VideoFormat[];
|
|
26
|
+
}>;
|
|
23
27
|
volumeMultiplierError$: ISubject<IError>;
|
|
24
28
|
providerOutput: IProviderOutput;
|
|
25
29
|
private subscription;
|
|
@@ -4,7 +4,11 @@ import type { IProvider, IProviderOutput } from "../types";
|
|
|
4
4
|
export interface IProviderContainer {
|
|
5
5
|
current$: IValueObservable<IProviderEntry>;
|
|
6
6
|
providerError$: ISubject<IError>;
|
|
7
|
-
noAvailableProvidersError$: ISubject<
|
|
7
|
+
noAvailableProvidersError$: ISubject<{
|
|
8
|
+
forced?: VideoFormat;
|
|
9
|
+
input: VideoFormat[];
|
|
10
|
+
supported: VideoFormat[];
|
|
11
|
+
}>;
|
|
8
12
|
volumeMultiplierError$: ISubject<IError>;
|
|
9
13
|
providerOutput: IProviderOutput;
|
|
10
14
|
init(): void;
|
|
@@ -3,10 +3,67 @@ import type { IVideoTrack } from "../../../../../player/types";
|
|
|
3
3
|
import type { Nullable, QualityLimits, VideoQuality } from "@vkontakte/videoplayer-shared";
|
|
4
4
|
import { type ExactVideoQuality } from "@vkontakte/videoplayer-shared";
|
|
5
5
|
import { LimitAboveRule } from "../limitAboveRule";
|
|
6
|
-
type UpperLimitsLogsArgs = [limitsAreInvalid: boolean, lowestAvailableQuality: Nullable<ExactVideoQuality>, highestAvailableQuality: Nullable<ExactVideoQuality>, visible: boolean, limits: QualityLimits, backgroundVideoQualityLimit: VideoQuality];
|
|
6
|
+
type UpperLimitsLogsArgs = [limitsAreInvalid: boolean, lowestAvailableQuality: Nullable<ExactVideoQuality>, highestAvailableQuality: Nullable<ExactVideoQuality>, visible: boolean, limits: QualityLimits, backgroundVideoQualityLimit: VideoQuality, effectiveType: string | undefined, connectionDataQualityLimit: ExactVideoQuality | undefined];
|
|
7
|
+
/**
|
|
8
|
+
* Правило верхнего ограничения качества в авто-ABR. Из списка `videoTracksDesc`
|
|
9
|
+
* (отсортирован от высшего к низшему) выбирает самый высокий трек, который
|
|
10
|
+
* одновременно удовлетворяет ВСЕМ активным лимитам сверху. Если подходящего
|
|
11
|
+
* нет — возвращает минимально доступный трек (graceful fallback).
|
|
12
|
+
*
|
|
13
|
+
* Источники лимитов сверху (действуют совместно, победитель — самый строгий):
|
|
14
|
+
*
|
|
15
|
+
* 1. `context.limits.max` — явный пользовательский/интеграционный лимит.
|
|
16
|
+
* Приходит из публичного API `Player.setAutoQualityLimits({ max, min })`
|
|
17
|
+
* (см. `packages/core/src/player/Player.ts`). Слой UI/интеграция пробрасывает
|
|
18
|
+
* его в `desiredState.autoVideoTrackLimits` → `AbrManager.updateContext({ limits })`
|
|
19
|
+
* → `IVideoAbrContext.limits`. `undefined` в `limits` или `limits.max` снимает
|
|
20
|
+
* лимит. Значение типа `ExactVideoQuality` (например, '720p'), трактуется
|
|
21
|
+
* включительно (`<=`). Если лимиты невалидны (min > max, либо min выше
|
|
22
|
+
* highestAvailable, либо max ниже lowestAvailable) — см. `areLimitsInvalid` —
|
|
23
|
+
* лимит игнорируется целиком, чтобы не заблокировать воспроизведение.
|
|
24
|
+
*
|
|
25
|
+
* Реальные кейсы:
|
|
26
|
+
* - Пользователь в настройках плеера выбрал пресет «Экономия трафика»
|
|
27
|
+
* (`PredefinedQualityLimits.TRAFFIC_SAVING`) — хост передаёт
|
|
28
|
+
* `{ max: tuning.autoTrackSelection.trafficSavingLimit }` (Q_480P).
|
|
29
|
+
* - Хост-приложение (мини-апп ВК, лента) ограничивает качество для
|
|
30
|
+
* превью/фонового воспроизведения.
|
|
31
|
+
* - A/B-эксперимент или бизнес-правило режет качество для конкретной
|
|
32
|
+
* категории видео / региона / тарифа.
|
|
33
|
+
*
|
|
34
|
+
* 2. `tuning.autoTrackSelection.backgroundVideoQualityLimit` — применяется
|
|
35
|
+
* только когда `context.visible === false` (плеер вне viewport, по данным
|
|
36
|
+
* `elementVisible$` из `observeElementVisibility`, порог — `activeVideoAreaThreshold`).
|
|
37
|
+
*
|
|
38
|
+
* Реальные кейсы: автовоспроизведение в ленте при прокрутке мимо плеера,
|
|
39
|
+
* PiP/мини-плеер в фоне, неактивная вкладка.
|
|
40
|
+
*
|
|
41
|
+
* 3. `effectiveType` из Network Information API (`navigator.connection`).
|
|
42
|
+
* Активируется `tuning.dash.useConnectionDataUpperLimit`.
|
|
43
|
+
* Приоритет разрешения в `connectionDataQualityLimit`:
|
|
44
|
+
* a. `effectiveType ∈ {'2g', 'slow-2g'}` → `tuning.dash.saveData2gQualityLimit`
|
|
45
|
+
* (Q_360P) — жёсткий лимит на очень слабой сети.
|
|
46
|
+
* b. `effectiveType === '3g'` → `tuning.dash.saveData3gQualityLimit` (Q_480P).
|
|
47
|
+
* c. Иначе — без ограничения.
|
|
48
|
+
*
|
|
49
|
+
* Network Information API доступен только в Chromium (Android, десктоп Chrome/Edge/
|
|
50
|
+
* Opera/Samsung Internet, Android WebView). В Firefox, Safari и Chrome iOS
|
|
51
|
+
* (WebKit) `navigator.connection === undefined` — этот источник лимита
|
|
52
|
+
* неактивен, правило работает только по п.1 и п.2.
|
|
53
|
+
*
|
|
54
|
+
* Реальные кейсы: пользователь в метро / зоне слабого сигнала, пользователь
|
|
55
|
+
* на edge/3G-тарифе.
|
|
56
|
+
*
|
|
57
|
+
* Все три источника комбинируются операцией AND: трек проходит, если
|
|
58
|
+
* `fitsLimits && fitsBackgroundVideoQualityLimit && fitsSaveDataLimit`. Поэтому
|
|
59
|
+
* итоговый потолок = минимум из активных. Нижнюю границу закрывает
|
|
60
|
+
* `LowerLimitRule` (поле `limits.min` здесь не используется).
|
|
61
|
+
*/
|
|
7
62
|
export declare class UpperLimitsRule extends LimitAboveRule<IVideoTrack, IVideoAbrContext, UpperLimitsLogsArgs> implements IAbrRule<IVideoTrack, IVideoAbrContext> {
|
|
8
63
|
constructor(confidence: RuleConfidence);
|
|
9
64
|
execute(context: IVideoAbrContext): IAbrRuleResolution<IVideoTrack>;
|
|
10
|
-
protected createLogMessage(selectedTrack: IVideoTrack, limitsAreInvalid: boolean, lowestAvailableQuality: Nullable<ExactVideoQuality>, highestAvailableQuality: Nullable<ExactVideoQuality>, visible: boolean, limits: QualityLimits, backgroundVideoQualityLimit: VideoQuality): string;
|
|
65
|
+
protected createLogMessage(selectedTrack: IVideoTrack, limitsAreInvalid: boolean, lowestAvailableQuality: Nullable<ExactVideoQuality>, highestAvailableQuality: Nullable<ExactVideoQuality>, visible: boolean, limits: QualityLimits, backgroundVideoQualityLimit: VideoQuality, effectiveType: string | undefined, connectionDataQualityLimit: ExactVideoQuality | undefined): string;
|
|
66
|
+
private getConnection;
|
|
67
|
+
private resolveConnectionDataQualityLimit;
|
|
11
68
|
}
|
|
12
69
|
export {};
|
|
@@ -3,9 +3,11 @@ export interface IStatefulIterator<T> {
|
|
|
3
3
|
getValue(): T;
|
|
4
4
|
isCompleted(): boolean;
|
|
5
5
|
isLast(): boolean;
|
|
6
|
+
all(): T[];
|
|
6
7
|
}
|
|
7
8
|
export declare class StatefulIterator<T> implements IStatefulIterator<T> {
|
|
8
9
|
private readonly length;
|
|
10
|
+
private array;
|
|
9
11
|
private index;
|
|
10
12
|
private iterator;
|
|
11
13
|
private current;
|
|
@@ -14,4 +16,5 @@ export declare class StatefulIterator<T> implements IStatefulIterator<T> {
|
|
|
14
16
|
getValue(): T;
|
|
15
17
|
isCompleted(): boolean;
|
|
16
18
|
isLast(): boolean;
|
|
19
|
+
all(): T[];
|
|
17
20
|
}
|
|
@@ -19,7 +19,9 @@ declare class ThroughputEstimator {
|
|
|
19
19
|
*/
|
|
20
20
|
addRawThroughput(rate: Kbps): void;
|
|
21
21
|
addRawRtt(time: Milliseconds): void;
|
|
22
|
-
private
|
|
23
|
-
private static
|
|
22
|
+
private sanityCheck;
|
|
23
|
+
private static loadStored;
|
|
24
|
+
private static writeStored;
|
|
25
|
+
private static validateStored;
|
|
24
26
|
}
|
|
25
27
|
export default ThroughputEstimator;
|
|
@@ -2,7 +2,7 @@ import type { VideoCodec, VideoFormat } from "../player/types";
|
|
|
2
2
|
import { WebmCodecStrategy } from "../enums/WebmCodecStrategy";
|
|
3
3
|
import { AndroidPreferredFormat } from "../enums/AndroidPreferredFormat";
|
|
4
4
|
import { IOSPreferredFormat } from "../enums/IOSPreferredFormat";
|
|
5
|
-
import type { Byte, Milliseconds, RecursivePartial, Seconds } from "@vkontakte/videoplayer-shared";
|
|
5
|
+
import type { Byte, Kbps, Milliseconds, RecursivePartial, Seconds } from "@vkontakte/videoplayer-shared";
|
|
6
6
|
import { type ExactVideoQuality, VideoQuality } from "@vkontakte/videoplayer-shared";
|
|
7
7
|
import { AudioRuleName, VideoRuleName } from "../providers/utils/Abr/types";
|
|
8
8
|
export type ITuningConfig = {
|
|
@@ -33,6 +33,9 @@ export type ITuningConfig = {
|
|
|
33
33
|
basisTrendChangeCount: number;
|
|
34
34
|
changeThreshold: number;
|
|
35
35
|
useBrowserEstimation: boolean;
|
|
36
|
+
initialThroughput: Kbps;
|
|
37
|
+
measureNonSegmentRequests: boolean;
|
|
38
|
+
smallSampleMinDuration: Milliseconds;
|
|
36
39
|
rttPenaltyRequestSize: Byte;
|
|
37
40
|
streamMinSampleSize: Byte;
|
|
38
41
|
streamMinSampleTime: Milliseconds;
|
|
@@ -42,6 +45,24 @@ export type ITuningConfig = {
|
|
|
42
45
|
continuesByteSequenceInterval: Milliseconds;
|
|
43
46
|
maxLastEvaluationTimeout: Milliseconds;
|
|
44
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* TTL + проверка типа сети для кешированного throughput из localStorage.
|
|
50
|
+
* При включении: если сохранённое значение старше storedThroughputTtlMs
|
|
51
|
+
* или тип сети изменился (Wi-Fi→3G) — значение отбрасывается.
|
|
52
|
+
* Предотвращает старт в 4K при переходе с Wi-Fi на мобильную сеть.
|
|
53
|
+
*
|
|
54
|
+
* При OFF (дефолт): читаем/пишем как до фикса — plain number в legacy-ключ
|
|
55
|
+
* one_video_*. Это даёт безопасный rollback JS-версии без потери данных.
|
|
56
|
+
* При ON: новый формат (JSON с timestamp+networkType) → новый ключ vk_uvp_*.
|
|
57
|
+
*/
|
|
58
|
+
useThroughputTtl: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Срок жизни кешированного throughput (мс). По умолчанию 4 часа.
|
|
61
|
+
* После истечения TTL значение из localStorage игнорируется —
|
|
62
|
+
* используется browser estimation или initialThroughput.
|
|
63
|
+
* Применимо только при useThroughputTtl=true.
|
|
64
|
+
*/
|
|
65
|
+
storedThroughputTtlMs: Milliseconds;
|
|
45
66
|
};
|
|
46
67
|
autoTrackSelection: {
|
|
47
68
|
bitrateFactorAtEmptyBuffer: number;
|
|
@@ -127,6 +148,8 @@ export type ITuningConfig = {
|
|
|
127
148
|
useNewRepresentationSwitch: boolean;
|
|
128
149
|
useDelayedRepresentationSwitch: boolean;
|
|
129
150
|
useSmartRepresentationSwitch: boolean;
|
|
151
|
+
seekStallExitPolicy: boolean;
|
|
152
|
+
mutexStallExitPolicy: boolean;
|
|
130
153
|
useFetchPriorityHints: boolean;
|
|
131
154
|
useAbortMSEFix: boolean;
|
|
132
155
|
enableBaseUrlSupport: boolean;
|
|
@@ -157,7 +180,11 @@ export type ITuningConfig = {
|
|
|
157
180
|
useNewFailoverLogic: boolean;
|
|
158
181
|
useFailoverHostsOnAllProviderCrash: boolean;
|
|
159
182
|
videoTrackBanAfterProviderFail: Milliseconds;
|
|
183
|
+
saveData3gQualityLimit: ExactVideoQuality;
|
|
184
|
+
saveData2gQualityLimit: ExactVideoQuality;
|
|
185
|
+
useConnectionDataUpperLimit: boolean;
|
|
160
186
|
videoStreamRepresentaionsFilter: [VideoQuality, number, VideoCodec][];
|
|
187
|
+
filterOnDemandQualityList: boolean;
|
|
161
188
|
};
|
|
162
189
|
dashCmafLive: {
|
|
163
190
|
externalStopControl: boolean;
|
|
@@ -238,8 +265,10 @@ export type ITuningConfig = {
|
|
|
238
265
|
requestQuick: boolean;
|
|
239
266
|
/** @deprecated HLS.js удалён, флаг ничего не делает */
|
|
240
267
|
useHlsJs: boolean;
|
|
268
|
+
disableHlsOnDesktop: boolean;
|
|
241
269
|
useNativeHLSTextTracks: boolean;
|
|
242
270
|
useNewSwitchTo: boolean;
|
|
271
|
+
alwaysAbortPreviousSwitch: boolean;
|
|
243
272
|
useDashProviderVirtual: boolean;
|
|
244
273
|
useDashProviderVirtualMobile: boolean;
|
|
245
274
|
useNewAutoSelectVideoTrack: boolean;
|
|
@@ -320,6 +349,31 @@ export type ITuningConfig = {
|
|
|
320
349
|
* (Скорее всего имеет смысл включить такой же флаг в настройках ui)
|
|
321
350
|
*/
|
|
322
351
|
reuseOwnVideoElement?: boolean;
|
|
352
|
+
/**
|
|
353
|
+
* Обрабатываем все сетевые ошибки, которые приходят с бэка.
|
|
354
|
+
* на http 500 не падаем в краш.
|
|
355
|
+
*/
|
|
356
|
+
handleExtendedNetworkErrorsSet?: boolean;
|
|
357
|
+
/**
|
|
358
|
+
* Кэшируем ответы от сервера руками, так как из за динамичесокй природы некоторых параметров в урле
|
|
359
|
+
* браузер это не может сделать.
|
|
360
|
+
*/
|
|
361
|
+
useUrlCacheMechanism?: boolean;
|
|
362
|
+
/**
|
|
363
|
+
* Очищаем кэш урлов при падение провайдера.
|
|
364
|
+
*/
|
|
365
|
+
dropUrlCacheWhenProviderCrashed?: boolean;
|
|
366
|
+
/**
|
|
367
|
+
* При смене/реините провайдера игнорируем результат того, смогло видео заиграть или нет.
|
|
368
|
+
*/
|
|
369
|
+
ignoreForcePlayResultWhenProviderChanged?: boolean;
|
|
370
|
+
hls: {
|
|
371
|
+
filterOnDemandQualityList: boolean;
|
|
372
|
+
};
|
|
373
|
+
/**
|
|
374
|
+
* Устанавливаем длительность видео на основе последнего сегмента.
|
|
375
|
+
*/
|
|
376
|
+
useDurationFromSegments: boolean;
|
|
323
377
|
};
|
|
324
378
|
export type IOptionalTuningConfig = RecursivePartial<ITuningConfig>;
|
|
325
379
|
export declare const fillDefault: (partial: IOptionalTuningConfig) => ITuningConfig;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type ISources, VideoFormat } from "../player/types";
|
|
2
|
-
export declare const filterAvailableFormats: (formats: VideoFormat[]) => VideoFormat[];
|
|
2
|
+
export declare const filterAvailableFormats: (formats: VideoFormat[], disableHlsOnDesktop?: boolean) => VideoFormat[];
|
|
3
3
|
export declare const isLiveFormat: (format: VideoFormat) => boolean;
|
|
4
|
-
export declare const areValidLiveRecordSources: (sources: ISources) => boolean;
|
|
4
|
+
export declare const areValidLiveRecordSources: (sources: ISources, disableHlsOnDesktop?: boolean) => boolean;
|