@vkontakte/videoplayer-core 2.0.161-dev.eddfe39b7.0 → 2.0.161
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 +11 -9
- package/es2015.esm.js +13 -11
- package/esnext.cjs +11 -9
- package/esnext.esm.js +33 -31
- package/evergreen.esm.js +13 -11
- package/package.json +2 -2
- package/types/providers/DashProvider/lib/buffer.d.ts +1 -0
- package/types/providers/DashProvider/lib/player.d.ts +3 -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/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/HlsProvider/index.d.ts +1 -1
- package/types/providers/MpegProvider/index.d.ts +1 -1
- package/types/providers/types.d.ts +1 -0
- package/types/providers/utils/Abr/rules/video/upperLimitRule.d.ts +59 -2
- package/types/utils/ThroughputEstimator.d.ts +3 -1
- package/types/utils/tuningConfig.d.ts +31 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vkontakte/videoplayer-core",
|
|
3
|
-
"version": "2.0.161
|
|
3
|
+
"version": "2.0.161",
|
|
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.90
|
|
45
|
+
"@vkontakte/videoplayer-shared": "1.0.90"
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -72,6 +72,7 @@ export declare class Player {
|
|
|
72
72
|
videoLastDataObtainedTimestamp$: IValueSubject<Milliseconds>;
|
|
73
73
|
fetcherRecoverableError$: Subject<IError>;
|
|
74
74
|
fetcherError$: Subject<IError>;
|
|
75
|
+
updateDurationError$: Subject<IError>;
|
|
75
76
|
private liveStreamEndTimestamp;
|
|
76
77
|
private liveBuffer;
|
|
77
78
|
private isUpdatingLive;
|
|
@@ -115,4 +116,6 @@ export declare class Player {
|
|
|
115
116
|
* Возвращает duration в милисекундах.
|
|
116
117
|
*/
|
|
117
118
|
calculateDurationFromSegments(): number;
|
|
119
|
+
private isAnyBufferUpdating;
|
|
120
|
+
updateSourceDurationFromSegments(): void;
|
|
118
121
|
}
|
|
@@ -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;
|
|
@@ -70,10 +70,11 @@ export declare abstract class BasePlayer {
|
|
|
70
70
|
videoLastDataObtainedTimestamp$: IValueSubject<Milliseconds>;
|
|
71
71
|
fetcherRecoverableError$: Subject<IError>;
|
|
72
72
|
fetcherError$: Subject<IError>;
|
|
73
|
+
updateDurationError$: Subject<IError>;
|
|
73
74
|
private isOnDemand;
|
|
74
75
|
protected constructor(params: Params);
|
|
75
76
|
protected abstract prepareManifestUrlString(manifestBaseUrlString: string, offset: number): string;
|
|
76
|
-
protected abstract
|
|
77
|
+
protected abstract setSourceInitDuration(): void;
|
|
77
78
|
protected abstract restoreAfterDeepStall(stallTraceAttributes: Record<string, number>): Promise<void>;
|
|
78
79
|
initRepresentations: ReturnType<typeof abortable<[Representation["id"], Representation["id"] | undefined, IHLSSource | undefined]>>;
|
|
79
80
|
initManifest(element: HTMLVideoElement, manifestBaseUrlString: string, offset: number): Promise<void>;
|
|
@@ -82,7 +83,6 @@ export declare abstract class BasePlayer {
|
|
|
82
83
|
seek(requestedPosition: Milliseconds, forcePrecise?: boolean): Promise<void>;
|
|
83
84
|
warmUpMediaSourceIfNeeded(position?: Milliseconds | undefined): void;
|
|
84
85
|
getForwardBufferRepresentations(kind: Exclude<StreamKind, StreamKind.TEXT>): Map<Representation["id"], Segment[]> | undefined;
|
|
85
|
-
calculateDurationFromSegments(representationId: Representation["id"]): Milliseconds;
|
|
86
86
|
get isStreamEnded(): boolean;
|
|
87
87
|
getStreams(): Manifest["streams"] | undefined;
|
|
88
88
|
getCodecs(): Manifest["codecs"] | undefined;
|
|
@@ -90,6 +90,9 @@ export declare abstract class BasePlayer {
|
|
|
90
90
|
setPreloadOnly(preloadOnly: boolean): void;
|
|
91
91
|
stop(): void;
|
|
92
92
|
destroy(): void;
|
|
93
|
+
updateSourceDurationFromSegments(): void;
|
|
94
|
+
calculateDurationFromBuffersSegments(): Milliseconds;
|
|
95
|
+
private isAnyBufferUpdating;
|
|
93
96
|
protected get isStreamNotOpen(): boolean;
|
|
94
97
|
protected reinitDecoderIfNeeded(force?: boolean): Promise<void>;
|
|
95
98
|
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;
|
|
@@ -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;
|
|
@@ -108,6 +108,7 @@ export interface IProviderOutput {
|
|
|
108
108
|
error$: ISubject<IError>;
|
|
109
109
|
fetcherRecoverableError$: ISubject<IError>;
|
|
110
110
|
fetcherError$: ISubject<IError>;
|
|
111
|
+
updateDurationError$: ISubject<IError>;
|
|
111
112
|
warning$: ISubject<IWarning>;
|
|
112
113
|
endedEvent$: ISubject<void>;
|
|
113
114
|
loopedEvent$: ISubject<Seconds>;
|
|
@@ -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 {};
|
|
@@ -20,6 +20,8 @@ declare class ThroughputEstimator {
|
|
|
20
20
|
addRawThroughput(rate: Kbps): void;
|
|
21
21
|
addRawRtt(time: Milliseconds): void;
|
|
22
22
|
private sanityCheck;
|
|
23
|
-
private static
|
|
23
|
+
private static loadStored;
|
|
24
|
+
private static writeStored;
|
|
25
|
+
private static validateStored;
|
|
24
26
|
}
|
|
25
27
|
export default ThroughputEstimator;
|
|
@@ -45,6 +45,24 @@ export type ITuningConfig = {
|
|
|
45
45
|
continuesByteSequenceInterval: Milliseconds;
|
|
46
46
|
maxLastEvaluationTimeout: Milliseconds;
|
|
47
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;
|
|
48
66
|
};
|
|
49
67
|
autoTrackSelection: {
|
|
50
68
|
bitrateFactorAtEmptyBuffer: number;
|
|
@@ -130,6 +148,8 @@ export type ITuningConfig = {
|
|
|
130
148
|
useNewRepresentationSwitch: boolean;
|
|
131
149
|
useDelayedRepresentationSwitch: boolean;
|
|
132
150
|
useSmartRepresentationSwitch: boolean;
|
|
151
|
+
seekStallExitPolicy: boolean;
|
|
152
|
+
mutexStallExitPolicy: boolean;
|
|
133
153
|
useFetchPriorityHints: boolean;
|
|
134
154
|
useAbortMSEFix: boolean;
|
|
135
155
|
enableBaseUrlSupport: boolean;
|
|
@@ -160,6 +180,9 @@ export type ITuningConfig = {
|
|
|
160
180
|
useNewFailoverLogic: boolean;
|
|
161
181
|
useFailoverHostsOnAllProviderCrash: boolean;
|
|
162
182
|
videoTrackBanAfterProviderFail: Milliseconds;
|
|
183
|
+
saveData3gQualityLimit: ExactVideoQuality;
|
|
184
|
+
saveData2gQualityLimit: ExactVideoQuality;
|
|
185
|
+
useConnectionDataUpperLimit: boolean;
|
|
163
186
|
videoStreamRepresentaionsFilter: [VideoQuality, number, VideoCodec][];
|
|
164
187
|
filterOnDemandQualityList: boolean;
|
|
165
188
|
};
|
|
@@ -340,9 +363,17 @@ export type ITuningConfig = {
|
|
|
340
363
|
* Очищаем кэш урлов при падение провайдера.
|
|
341
364
|
*/
|
|
342
365
|
dropUrlCacheWhenProviderCrashed?: boolean;
|
|
366
|
+
/**
|
|
367
|
+
* При смене/реините провайдера игнорируем результат того, смогло видео заиграть или нет.
|
|
368
|
+
*/
|
|
369
|
+
ignoreForcePlayResultWhenProviderChanged?: boolean;
|
|
343
370
|
hls: {
|
|
344
371
|
filterOnDemandQualityList: boolean;
|
|
345
372
|
};
|
|
373
|
+
/**
|
|
374
|
+
* Устанавливаем длительность видео на основе последнего сегмента.
|
|
375
|
+
*/
|
|
376
|
+
useDurationFromSegments: boolean;
|
|
346
377
|
};
|
|
347
378
|
export type IOptionalTuningConfig = RecursivePartial<ITuningConfig>;
|
|
348
379
|
export declare const fillDefault: (partial: IOptionalTuningConfig) => ITuningConfig;
|