@vkontakte/videoplayer-core 2.0.180 → 2.0.181-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.
Files changed (46) hide show
  1. package/es2015.cjs +17 -17
  2. package/es2015.esm.js +17 -17
  3. package/esnext.cjs +16 -16
  4. package/esnext.esm.js +16 -16
  5. package/evergreen.esm.js +16 -16
  6. package/package.json +2 -2
  7. package/types/index.d.ts +3 -2
  8. package/types/player/Player.d.ts +3 -2
  9. package/types/player/types.d.ts +7 -11
  10. package/types/providers/DashProvider/baseDashProvider.d.ts +1 -1
  11. package/types/providers/DashProvider/lib/buffer.d.ts +28 -3
  12. package/types/providers/DashProvider/lib/fetcher.d.ts +31 -6
  13. package/types/providers/DashProvider/lib/player.d.ts +2 -0
  14. package/types/providers/DashProviderVirtual/baseDashProvider.d.ts +1 -1
  15. package/types/providers/DashProviderVirtual/lib/buffer/types.d.ts +1 -0
  16. package/types/providers/DashProviderVirtual/lib/buffer/virtualBuffer/baseVirtualBufferManager.d.ts +7 -3
  17. package/types/providers/DashProviderVirtual/lib/fetcher.d.ts +30 -6
  18. package/types/providers/DashProviderVirtual/lib/player/basePlayer.d.ts +1 -0
  19. package/types/providers/DashProviderVirtual/lib/player/types.d.ts +2 -1
  20. package/types/providers/types.d.ts +1 -3
  21. package/types/providers/utils/Abr/rules/video/stallsRule.d.ts +9 -11
  22. package/types/providers/utils/StallsManager.d.ts +1 -8
  23. package/types/providers/utils/TextTrackManager.d.ts +16 -0
  24. package/types/utils/ClientChecker/services/DeviceChecker.d.ts +4 -0
  25. package/types/utils/ClientChecker/types/userAgentData.d.ts +4 -2
  26. package/types/utils/ThroughputEstimator.d.ts +20 -4
  27. package/types/utils/UserHappinessController.d.ts +8 -0
  28. package/types/utils/UserHappinessObserver/constants.d.ts +12 -0
  29. package/types/utils/UserHappinessObserver/index.d.ts +15 -0
  30. package/types/utils/UserHappinessObserver/metrics/hasFatalError.d.ts +3 -0
  31. package/types/utils/UserHappinessObserver/metrics/highStallRatio.d.ts +3 -0
  32. package/types/utils/UserHappinessObserver/metrics/lowQuality/constants.d.ts +5 -0
  33. package/types/utils/UserHappinessObserver/metrics/lowQuality/createLowQuality.d.ts +4 -0
  34. package/types/utils/UserHappinessObserver/metrics/lowQuality/index.d.ts +1 -0
  35. package/types/utils/UserHappinessObserver/metrics/lowQuality/types.d.ts +13 -0
  36. package/types/utils/UserHappinessObserver/metrics/lowQuality/utils.d.ts +26 -0
  37. package/types/utils/UserHappinessObserver/metrics/slowFirstFrame.d.ts +3 -0
  38. package/types/utils/UserHappinessObserver/types.d.ts +8 -0
  39. package/types/utils/UserHappinessObserver/utils/qualityPlatform.d.ts +2 -0
  40. package/types/utils/UserHappinessObserver/utils/thresholds.d.ts +2 -0
  41. package/types/utils/UserHappinessObserver/utils/watchedTimeSeconds.d.ts +3 -0
  42. package/types/utils/buffer/isPositionBuffered.d.ts +1 -0
  43. package/types/utils/tuningConfig.d.ts +52 -21
  44. package/types/utils/userHappinessTriggers.d.ts +4 -0
  45. package/types/providers/utils/HTMLVideoElement/TextTrackManager.d.ts +0 -32
  46. package/types/utils/setStateWithSubscribe.d.ts +0 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vkontakte/videoplayer-core",
3
- "version": "2.0.180",
3
+ "version": "2.0.181-beta.0",
4
4
  "author": "vk.ru",
5
5
  "description": "Videoplayer core library based on the vk.ru platform",
6
6
  "homepage": "https://vk.ru",
@@ -42,6 +42,6 @@
42
42
  "**/*.d.ts"
43
43
  ],
44
44
  "dependencies": {
45
- "@vkontakte/videoplayer-shared": "1.0.109"
45
+ "@vkontakte/videoplayer-shared": "1.0.110-beta.0"
46
46
  }
47
47
  }
package/types/index.d.ts CHANGED
@@ -3,9 +3,10 @@ import type { IMpegSource, IDashSource, IHLSSource, IDashURLSource, IHLSLiveSour
3
3
  import type { VideoCodec } from "./player/types";
4
4
  import { VideoFormat, Surface, PredefinedQualityLimits, VideoCodecName } from "./player/types";
5
5
  import Player from "./player/Player";
6
- import type { IPlayer, IPlayerInfo, IPlayerEvents, IConfig, ISources, ICueSettings, IExternalTextTrack, ITextTrack, PlaybackRate, IVideoStream, IAudioStream, StartEnd, HttpConnectionMetrics, HttpDownloadMetrics } from "./player/types";
6
+ import type { IPlayer, IPlayerInfo, IPlayerEvents, IConfig, ISources, IExternalTextTrack, ITextTrack, PlaybackRate, IVideoStream, IAudioStream, StartEnd, HttpConnectionMetrics, HttpDownloadMetrics } from "./player/types";
7
7
  import { PlaybackState, ChromecastState, HttpConnectionType } from "./player/types";
8
8
  import type { IOptionalTuningConfig } from "./utils/tuningConfig";
9
+ import type { UserHappinessTrigger } from "./utils/userHappinessTriggers";
9
10
  export { clientChecker, isMobile } from "./utils/ClientChecker";
10
11
  export { areValidLiveRecordSources } from "./utils/videoFormat";
11
12
  export { WebmCodecStrategy } from "./enums/WebmCodecStrategy";
@@ -15,5 +16,5 @@ import { Subscription, Observable, Subject, ValueSubject, VideoQuality } from "@
15
16
  * @deprecated
16
17
  */
17
18
  declare const SDK_VERSION: string;
18
- export type { IPlayer, IPlayerInfo, IPlayerEvents, IConfig, IOptionalTuningConfig, ILogEntry, ISources, IExternalTextTrack, ITextTrack, ISubscription, IUnsubscriber, IObservable, IEmitter, IValueObservable, IValue, IOperator, IListener, IMpegSource, IDashSource, IDashURLSource, IHLSSource, IHLSLiveSource, URLSource, RawSource, URLSourceWithSeek, ExactVideoQuality, IRange, ISeekRequest, ICueSettings, PlaybackRate, IVideoStream, IAudioStream, StartEnd, HttpConnectionMetrics, HttpDownloadMetrics };
19
+ export type { IPlayer, IPlayerInfo, IPlayerEvents, IConfig, IOptionalTuningConfig, UserHappinessTrigger, ILogEntry, ISources, IExternalTextTrack, ITextTrack, ISubscription, IUnsubscriber, IObservable, IEmitter, IValueObservable, IValue, IOperator, IListener, IMpegSource, IDashSource, IDashURLSource, IHLSSource, IHLSLiveSource, URLSource, RawSource, URLSourceWithSeek, ExactVideoQuality, IRange, ISeekRequest, PlaybackRate, IVideoStream, IAudioStream, StartEnd, HttpConnectionMetrics, HttpDownloadMetrics };
19
20
  export { Player, PlaybackState, ChromecastState, HttpConnectionType, Surface, Subscription, VideoFormat, VideoQuality, Observable, Subject, ValueSubject, VERSION, SDK_VERSION, PredefinedQualityLimits, VideoCodec, VideoCodecName };
@@ -1,6 +1,6 @@
1
1
  import type { IOptionalTuningConfig } from "../utils/tuningConfig";
2
2
  import type { ILogEntry, ITracer, QualityLimits, Seconds, VideoQuality, DebugData } from "@vkontakte/videoplayer-shared";
3
- import { type IAudioStream, type IConfig, type ICueSettings, type IExternalTextTrack, type IPlayer, type ITextTrack, type IVideoStream, type PlaybackRate, type PlayerEventsImpl, type PlayerExperimentalImpl, type PlayerInfoImpl, PredefinedQualityLimits } from "./types";
3
+ import { type IAudioStream, type IConfig, type IExternalTextTrack, type IPlayer, type ITextTrack, type IVideoStream, type PlaybackRate, type PlayerEventsImpl, type PlayerExperimentalImpl, type PlayerInfoImpl, PredefinedQualityLimits } from "./types";
4
4
  import type { IPlayerOptions } from "../utils/playerOptions";
5
5
  export default class Player implements IPlayer {
6
6
  private readonly subscription;
@@ -26,6 +26,7 @@ export default class Player implements IPlayer {
26
26
  private wasSetStartedQuality;
27
27
  private desiredState;
28
28
  info: PlayerInfoImpl;
29
+ private userHappinessController;
29
30
  events: PlayerEventsImpl;
30
31
  experimental: PlayerExperimentalImpl;
31
32
  private devNullLog;
@@ -37,6 +38,7 @@ export default class Player implements IPlayer {
37
38
  * Очищает необходимые поля при переключении на другое видео
38
39
  */
39
40
  private resetDesiredState;
41
+ private createUserHappinessController;
40
42
  /**
41
43
  * Возвращает плеер в начальное состояние
42
44
  * Позвонялет переиспользовать для другого видео
@@ -71,7 +73,6 @@ export default class Player implements IPlayer {
71
73
  setPlaybackRate(playbackRate: PlaybackRate): IPlayer;
72
74
  setExternalTextTracks(tracks: Omit<IExternalTextTrack, "type">[]): IPlayer;
73
75
  selectTextTrack(id: ITextTrack["id"] | undefined): IPlayer;
74
- setTextTrackCueSettings(settings: ICueSettings): IPlayer;
75
76
  setLiveLowLatency(isLowLatency: boolean): IPlayer;
76
77
  setLooped(isLooped: boolean): IPlayer;
77
78
  toggleChromecast(): void;
@@ -56,8 +56,10 @@ export interface IPlayer {
56
56
  setPlaybackRate(playbackRate: PlaybackRate): IPlayer;
57
57
  setLooped(isLooped: boolean): IPlayer;
58
58
  setExternalTextTracks(tracks: Omit<IExternalTextTrack, "type">[]): IPlayer;
59
+ /**
60
+ * Запоминает выбранную дорожку субтитров. Отрисовка субтитров на стороне UI
61
+ */
59
62
  selectTextTrack(id: ITextTrack["id"] | undefined): IPlayer;
60
- setTextTrackCueSettings(settings: ICueSettings): IPlayer;
61
63
  setLiveLowLatency(isLowLatency: boolean): IPlayer;
62
64
  /**
63
65
  * Включает или отключает Chromecast
@@ -225,7 +227,7 @@ export interface IPlayerEvents {
225
227
  */
226
228
  fetcherRecoverableError$: IObservable<IError>;
227
229
  /**
228
- * Произошел серьезный/долгий стол.
230
+ * Произошел серьёзный/долгий stall.
229
231
  */
230
232
  severeStallOccured$: IObservable<boolean>;
231
233
  }
@@ -348,7 +350,7 @@ export interface PlayerInfoValues {
348
350
  */
349
351
  isBuffering$: boolean;
350
352
  /**
351
- * Состояние столла. Возникает по истечении stallIgnoreThreshold после старта нежелательной буферизации
353
+ * Состояние stall. Возникает по истечении stallIgnoreThreshold после старта нежелательной буферизации
352
354
  * Статус только нежелательной буферизации возникает при опустошении буфера в процессе воспроизведения
353
355
  * и не возникает при начальном наполнении буфера или после перемотки
354
356
  */
@@ -407,7 +409,7 @@ export interface PlayerInfoValues {
407
409
  */
408
410
  availableTextTracks$: ITextTrack[];
409
411
  /**
410
- * Выбранная и отображаемая дорожка субтитров
412
+ * Выбранная дорожка субтитров
411
413
  */
412
414
  currentTextTrack$: ITextTrack["id"] | undefined;
413
415
  /**
@@ -517,7 +519,7 @@ export interface PlayerEventsImpl {
517
519
  fetcherError$: Subject<IError>;
518
520
  severeStallOccured$: Subject<boolean>;
519
521
  }
520
- interface IPlayerExperimental {
522
+ export interface IPlayerExperimental {
521
523
  /**
522
524
  * Элемент, который сейчас вставлен в container.
523
525
  * Может быть видеоэлементом, iframe и вообще чем угодно в общем случае.
@@ -685,12 +687,6 @@ export interface IInternalTextTrack extends ITextTrackBase {
685
687
  url: string;
686
688
  }
687
689
  export type ITextTrack = IExternalTextTrack | IInternalTextTrack;
688
- export interface ICueSettings {
689
- align?: "left" | "center" | "right";
690
- position?: number | "auto";
691
- size?: number;
692
- line?: number | "auto";
693
- }
694
690
  export declare enum VideoDestination {
695
691
  SCREEN = "SCREEN",
696
692
  CHROMECAST = "CHROMECAST"
@@ -8,7 +8,7 @@ import type { IStateMachine } from "../../utils/StateMachine/types";
8
8
  import type { ExactVideoQuality, ISubscription, ITracer, Milliseconds, Nullable } from "@vkontakte/videoplayer-shared";
9
9
  import { Player } from "./lib/player";
10
10
  import DroppedFramesManager from "../utils/HTMLVideoElement/DroppedFramesManager";
11
- import TextTrackManager from "../utils/HTMLVideoElement/TextTrackManager";
11
+ import TextTrackManager from "../utils/TextTrackManager";
12
12
  import StallsManager from "../utils/StallsManager";
13
13
  import { AbrManager } from "../utils/Abr/abrManager";
14
14
  import { ElementSizeManager } from "../utils/HTMLVideoElement/ElementSizeManager";
@@ -12,6 +12,7 @@ export interface Dependencies {
12
12
  compatibilityMode?: boolean;
13
13
  manifest: Manifest | null;
14
14
  tracer: ITracer;
15
+ getSeekTargetPosition?: () => Milliseconds | undefined;
15
16
  }
16
17
  export interface Gap extends IRange<Milliseconds> {
17
18
  representation: Representation["id"];
@@ -56,6 +57,7 @@ export declare class BufferManager {
56
57
  private destroyAbortController;
57
58
  private useSmartRepresentationSwitch;
58
59
  private readonly getCurrentPosition;
60
+ private readonly getSeekTargetPosition;
59
61
  private readonly isActiveLowLatency;
60
62
  private tuning;
61
63
  private forwardBufferTarget;
@@ -77,9 +79,8 @@ export declare class BufferManager {
77
79
  private index;
78
80
  private lastDataObtainedTimestampMs;
79
81
  private loadByteRangeSegmentsTimeoutId;
80
- private preDownloadedFirstSegment;
81
82
  private brokenSegmentAppendDetected;
82
- constructor(kind: StreamKind, mediaSource: MediaSource, representations: Representation[], { fetcher, tuning, getCurrentPosition, isActiveLowLatency, compatibilityMode, manifest, tracer }: Dependencies);
83
+ constructor(kind: StreamKind, mediaSource: MediaSource, representations: Representation[], { fetcher, tuning, getCurrentPosition, getSeekTargetPosition, isActiveLowLatency, compatibilityMode, manifest, tracer }: Dependencies);
83
84
  startWith: ReturnType<typeof abortable<[Representation["id"]]>>;
84
85
  switchToWithPreviousAbort(newRepresentationId: Representation["id"], dropBuffer?: boolean): Promise<void | undefined>;
85
86
  switchTo: ReturnType<typeof abortable<[Representation["id"], boolean | undefined], void>>;
@@ -108,7 +109,6 @@ export declare class BufferManager {
108
109
  private loadSegments;
109
110
  private loadTemplateSegment;
110
111
  private updateRepresentationsBaseUrlIfNeeded;
111
- private feedPreDownloadedFirstSegment;
112
112
  private loadByteRangeSegments;
113
113
  private prepareByteRangeFetchSegmentParams;
114
114
  private buildCacheMetadata;
@@ -128,7 +128,32 @@ export declare class BufferManager {
128
128
  private detectBrokenSegmentAppend;
129
129
  private abortSegment;
130
130
  private loadNextInit;
131
+ private isFirstSegmentPreloadEnabled;
132
+ private isStartPositionWithinFirstSegment;
133
+ /**
134
+ * Работа с прелоадом первого сегмента.
135
+ *
136
+ * Загружает init+index репрезентации и применяет их через onInitFetched (результаты сетятся в initData /
137
+ * parsedInitData / segments). Резолвится после применения инита.
138
+ *
139
+ * Режимы вызова:
140
+ * - critical=true — только startWith (стартовая загрузка);
141
+ * - critical=false — switchTo и ленивые idle-догрузки остальных репрезентаций.
142
+ *
143
+ * С прелоадом первого сегмента (critical && isFirstSegmentPreloadEnabled):
144
+ * - фетчер делает один combined-запрос init+index+первый сегмент;
145
+ * - инит применяется досрочно из onInitFetched, до скачанных байтов сегмента, и сразу ставится
146
+ * init-аппенд в SourceBufferTaskQueue — раньше кормления чанков сегмента (кормление синхронно
147
+ * внутри onProgress, поэтому без этого сегмент аппендился бы раньше инита);
148
+ * - резолв loadInit ждёт завершения init-аппенда;
149
+ * - чанки сегмента кормятся через handleFirstSegmentChunk, хвост добивается в finalizeCombinedStreaming
150
+ */
131
151
  private loadInit;
152
+ /**
153
+ * Здесь мы только финалим хвостовую часть — сегментную — комбинированного запроса.
154
+ * Если сегмент не докачался не беда, loadSegments подхватит.
155
+ */
156
+ private finalizeCombinedStreaming;
132
157
  private dropBuffer;
133
158
  private pruneBuffer;
134
159
  private abortBuffer;
@@ -1,8 +1,7 @@
1
1
  import type { HttpConnectionType, HttpConnectionMetrics, HttpDownloadMetrics } from "../../../player/types";
2
2
  import type ThroughputEstimator from "../../../utils/ThroughputEstimator";
3
- import type { Byte, IValueSubject, ISubject, Milliseconds, IRange, ITracer, IError } from "@vkontakte/videoplayer-shared";
3
+ import type { Byte, ExactVideoQuality, IValueSubject, ISubject, Milliseconds, IRange, ITracer, IError } from "@vkontakte/videoplayer-shared";
4
4
  import { abortable } from "@vkontakte/videoplayer-shared";
5
- import type { ExactVideoQuality } from "@vkontakte/videoplayer-shared";
6
5
  import type { CommonInit, GenericContainerParser, Segment, SegmentReference } from "../../utils/parsers/types";
7
6
  import type { ISegmentCacheStorage, CacheMetadata, SegmentCacheMode } from "../../utils/segmentCache";
8
7
  declare global {
@@ -50,13 +49,19 @@ export interface FetchParams {
50
49
  ignoreNetworkErrors?: boolean;
51
50
  representationHeight?: number;
52
51
  cacheMetadata?: CacheMetadata;
52
+ firstSegmentPreload?: boolean;
53
+ onInitFetched?: (data: IRepresentationInitReady) => void;
54
+ onSegmentsDone?: (result: ICombinedBodyResult | null) => void;
53
55
  }
54
- export type RepresentationFetchResult = {
56
+ export interface IRepresentationInitReady {
55
57
  init: CommonInit | null;
56
58
  segments: Segment[];
59
+ initData: ArrayBuffer;
60
+ globalFrom: Byte;
61
+ }
62
+ export interface ICombinedBodyResult {
57
63
  dataView: DataView;
58
- firstSegmentData?: ArrayBuffer;
59
- };
64
+ }
60
65
  export declare class Fetcher {
61
66
  private throughputEstimator;
62
67
  private requestQuic;
@@ -97,11 +102,31 @@ export declare class Fetcher {
97
102
  private trackRequestStart;
98
103
  fetchManifest: ReturnType<typeof abortable<[string], string | null>>;
99
104
  fetch: ReturnType<typeof abortable<[string, FetchParams], ArrayBuffer | null>>;
100
- fetchRepresentation(segmentReference: SegmentReference, parser: GenericContainerParser<unknown>, fetchParams: FetchParams): Promise<RepresentationFetchResult | null>;
105
+ /**
106
+ * Резолвится, когда получили init данные.
107
+ */
108
+ fetchRepresentation(segmentReference: SegmentReference, parser: GenericContainerParser<unknown>, fetchParams: FetchParams): Promise<IRepresentationInitReady | null>;
101
109
  /** Скипнутые сегменты не записаны в кэш — при следующем запросе региона докачаются как miss. */
102
110
  private traceSkippedCacheSegments;
103
111
  destroy(): void;
112
+ /**
113
+ * Тут проверяем расположение данных, нам из манифеста приходит только длина сегмента, ничто не известно про оффсет от начала,
114
+ * заявлено, что первый сегмент идет сразу после индекса. Проверяем контракт: true — нарушен, первый сегмент лежит не сразу за индексом.
115
+ */
116
+ private isFirstSegmentLayoutViolated;
117
+ private logFirstSegmentLayoutViolation;
118
+ /**
119
+ * Адаптируем onProgress комбинированного запроса: отдельно информируем о данных инита
120
+ * и о данных сегмента на основании одного combined-стрима.
121
+ */
122
+ private createInitAndFirstSegmentStreamingOnProgress;
104
123
  private fetchByteRangeRepresentation;
124
+ private fetchByteRangeRepresentationWithFirstSegment;
125
+ /**
126
+ * Если происходит downloadSignal то мы не хотим абортить загрузку инит части запроса,
127
+ * скачиваем нужную часть запроса, как только инит+индекс готов, сегмент хвост можно абортить.
128
+ */
129
+ private createSegmentTailAbort;
105
130
  private fetchTemplateRepresentation;
106
131
  private isLikelyCacheHitByTtfb;
107
132
  private doFetch;
@@ -22,6 +22,7 @@ export interface Params {
22
22
  tracer: ITracer;
23
23
  isOnDemand: boolean;
24
24
  dashMaxTvVideoQuality: Nullable<ExactVideoQuality>;
25
+ getSeekTargetPosition?: () => Milliseconds | undefined;
25
26
  }
26
27
  export declare class Player {
27
28
  private element;
@@ -89,6 +90,7 @@ export declare class Player {
89
90
  private liveWasInterrupted;
90
91
  private isOnDemand;
91
92
  private dashMaxTvVideoQuality;
93
+ private getSeekTargetPosition;
92
94
  private destroyController;
93
95
  constructor(params: Params);
94
96
  initManifest: ReturnType<typeof abortable<[HTMLMediaElement, string, number]>>;
@@ -7,7 +7,7 @@ import type { IObservableMediaElement } from "../utils/HTMLVideoElement/observab
7
7
  import type { IStateMachine } from "../../utils/StateMachine/types";
8
8
  import type { ExactVideoQuality, ISubscription, ITracer, Milliseconds, Nullable } from "@vkontakte/videoplayer-shared";
9
9
  import DroppedFramesManager from "../utils/HTMLVideoElement/DroppedFramesManager";
10
- import TextTrackManager from "../utils/HTMLVideoElement/TextTrackManager";
10
+ import TextTrackManager from "../utils/TextTrackManager";
11
11
  import StallsManager from "../utils/StallsManager";
12
12
  import { ElementSizeManager } from "../utils/HTMLVideoElement/ElementSizeManager";
13
13
  import type { BasePlayer } from "./lib/player/basePlayer";
@@ -20,6 +20,7 @@ export interface Dependencies {
20
20
  getCurrentPosition(): Milliseconds | undefined;
21
21
  getCurrentStallDuration(): Milliseconds;
22
22
  isActiveLowLatency(): boolean;
23
+ getSeekTargetPosition?(): Milliseconds | undefined;
23
24
  }
24
25
  export interface IVirtualBufferManager<T extends Segment = Segment> {
25
26
  error$: ISubject<IError>;
@@ -1,4 +1,4 @@
1
- import type { Fetcher, FetchParamsWithUrl, Priority, RepresentationFetchResult } from "../../fetcher";
1
+ import type { Fetcher, FetchParamsWithUrl, Priority } from "../../fetcher";
2
2
  import type { CommonInit, ContainerParser, Representation, Segment } from "../../../../utils/parsers/types";
3
3
  import { StreamKind } from "../../../../utils/parsers/types";
4
4
  import type { ITuningConfig } from "../../../../../utils/tuningConfig";
@@ -26,7 +26,7 @@ export declare abstract class BaseVirtualBufferManager<T extends Segment> implem
26
26
  protected downloadingRepresentationId: Representation["id"] | undefined;
27
27
  protected switchingRepresentationId: Representation["id"] | null;
28
28
  protected initData: Map<Representation["id"], ArrayBuffer>;
29
- protected initDataPromises: Map<Representation["id"], Promise<RepresentationFetchResult<T> | null | undefined>>;
29
+ protected initDataPromises: Map<Representation["id"], Promise<unknown>>;
30
30
  protected idleCallbacks: Map<Representation["id"], number>;
31
31
  protected parsedInitData: Map<Representation["id"], CommonInit>;
32
32
  protected forwardBufferRepresentations: Map<Representation["id"], T[]>;
@@ -55,8 +55,9 @@ export declare abstract class BaseVirtualBufferManager<T extends Segment> implem
55
55
  protected subscription: Subscription;
56
56
  protected readonly getCurrentPosition: () => Milliseconds | undefined;
57
57
  protected readonly getCurrentStallDuration: () => Milliseconds | undefined;
58
+ protected readonly getSeekTargetPosition: (() => Milliseconds | undefined) | undefined;
58
59
  protected brokenSegmentAppendDetected: boolean;
59
- protected constructor(kind: StreamKind, nativeBufferManager: NativeBufferManager, representations: Representation[], { fetcher, tracer, tuning, getCurrentPosition, getCurrentStallDuration, manifest, segmentCacheService }: Dependencies);
60
+ protected constructor(kind: StreamKind, nativeBufferManager: NativeBufferManager, representations: Representation[], { fetcher, tracer, tuning, getCurrentPosition, getCurrentStallDuration, getSeekTargetPosition, manifest, segmentCacheService }: Dependencies);
60
61
  protected abstract loadItems(itemsToLoad: IBufferPlaybackQueueItem<T>[], representation: Representation, priority?: Priority): Promise<void>;
61
62
  protected abstract selectItemsToLoad(): IBufferPlaybackQueueItem<T>[];
62
63
  protected abstract prepareFetchParams(items: IBufferPlaybackQueueItem<T>[], representation: Representation): FetchParamsWithUrl;
@@ -110,6 +111,9 @@ export declare abstract class BaseVirtualBufferManager<T extends Segment> implem
110
111
  protected loadInits(): Promise<void>;
111
112
  protected loadInitIfNeeded(representation: Representation, requestedPriority?: Priority, critical?: boolean): Promise<void>;
112
113
  protected loadInit(representation: Representation, requestedPriority?: Priority, critical?: boolean): Promise<void>;
114
+ private isStartPositionWithinFirstSegment;
115
+ private finalizeCombinedStreaming;
116
+ private resetStreamingItem;
113
117
  protected maintainNativeBuffer(signal: AbortSignal): Promise<void>;
114
118
  protected maintainPlaybackBuffer(position: Milliseconds): Promise<void>;
115
119
  protected actualizeLastSegmentInfo(currentPosition: Milliseconds): void;
@@ -1,8 +1,7 @@
1
1
  import type { HttpConnectionType, HttpConnectionMetrics, HttpDownloadMetrics } from "../../../player/types";
2
2
  import type ThroughputEstimator from "../../../utils/ThroughputEstimator";
3
- import type { Byte, IError, IRange, ISubject, ITracer, IValueSubject, Milliseconds } from "@vkontakte/videoplayer-shared";
3
+ import type { Byte, ExactVideoQuality, IError, IRange, ISubject, ITracer, IValueSubject, Milliseconds } from "@vkontakte/videoplayer-shared";
4
4
  import { abortable } from "@vkontakte/videoplayer-shared";
5
- import type { ExactVideoQuality } from "@vkontakte/videoplayer-shared";
6
5
  import type { CommonInit, GenericContainerParser, Segment, SegmentReference, StreamKind } from "../../utils/parsers/types";
7
6
  import type { ISegmentCacheStorage, CacheMetadata, SegmentCacheMode } from "../../utils/segmentCache";
8
7
  declare global {
@@ -44,17 +43,30 @@ export interface FetchParams {
44
43
  onProgressTasks?: Promise<void>[];
45
44
  signal?: AbortSignal;
46
45
  priority?: Priority;
46
+ representationHeight?: number;
47
47
  measureThroughput?: boolean;
48
48
  isLowLatency?: boolean;
49
49
  bufferOptimisation?: boolean;
50
50
  kind: StreamKind;
51
51
  cacheMetadata?: CacheMetadata;
52
+ firstSegmentPreload?: boolean;
53
+ onInitFetched?: (data: IRepresentationInitReady) => void;
54
+ onSegmentsDone?: (result: ICombinedBodyResult | null) => void;
55
+ }
56
+ export interface IRepresentationInitReady {
57
+ init: CommonInit | null;
58
+ segments: Segment[];
59
+ initData: ArrayBuffer;
60
+ globalFrom: Byte;
61
+ }
62
+ export interface ICombinedBodyResult {
63
+ dataView: DataView;
52
64
  }
53
65
  export type RepresentationFetchResult<T extends Segment> = {
54
- initMetadata: CommonInit | null;
55
- initDataView: DataView;
66
+ init: CommonInit | null;
56
67
  segments: T[];
57
- firstSegmentData?: ArrayBuffer;
68
+ initData: ArrayBuffer;
69
+ globalFrom: Byte;
58
70
  };
59
71
  export declare class Fetcher {
60
72
  private throughputEstimator;
@@ -96,11 +108,23 @@ export declare class Fetcher {
96
108
  private trackRequestStart;
97
109
  fetchManifest: ReturnType<typeof abortable<[string], string | null>>;
98
110
  fetch: ReturnType<typeof abortable<[string, FetchParams], ArrayBuffer | null>>;
99
- fetchRepresentation<T extends Segment>(segmentReference: SegmentReference, parser: GenericContainerParser<unknown>, dowbloadAbortSignal: AbortSignal, priority?: Priority, representationHeight?: number, kind?: StreamKind): Promise<RepresentationFetchResult<T> | null | undefined>;
111
+ fetchRepresentation<T extends Segment>(segmentReference: SegmentReference, parser: GenericContainerParser<unknown>, fetchParams?: FetchParams): Promise<RepresentationFetchResult<T> | null | undefined>;
100
112
  /** Скипнутые сегменты не записаны в кэш — при следующем запросе региона докачаются как miss. */
101
113
  private traceSkippedCacheSegments;
102
114
  destroy(): void;
115
+ /**
116
+ * Так как качем инит+сегмент, то нам нужно раньше сообщить, что мы получили инит+индекс часть,
117
+ * а сегментная пусть качается дальше.
118
+ */
119
+ private createInitAndFirstSegmentStreamingOnProgress;
120
+ /**
121
+ * Проверяем, что данные сегмента идут сразу после индекса.
122
+ */
123
+ private isFirstSegmentLayoutViolated;
124
+ private logFirstSegmentLayoutViolation;
103
125
  private fetchByteRangeRepresentation;
126
+ private fetchByteRangeRepresentationWithFirstSegment;
127
+ private createSegmentTailAbort;
104
128
  private fetchTemplateRepresentation;
105
129
  private isLikelyCacheHitByTtfb;
106
130
  private doFetch;
@@ -80,6 +80,7 @@ export declare abstract class BasePlayer {
80
80
  updateDurationError$: Subject<IError>;
81
81
  private isOnDemand;
82
82
  private dashMaxTvVideoQuality;
83
+ private getSeekTargetPosition;
83
84
  protected constructor(params: Params);
84
85
  protected abstract prepareManifestUrlString(manifestBaseUrlString: string, offset: number): string;
85
86
  protected abstract setSourceInitDuration(): void;
@@ -1,7 +1,7 @@
1
1
  import type ThroughputEstimator from "../../../../utils/ThroughputEstimator";
2
2
  import type { ITuningConfig } from "../../../../utils/tuningConfig";
3
3
  import type { VideoCodec } from "../../../../player/types";
4
- import type { ExactVideoQuality, ITracer, Nullable } from "@vkontakte/videoplayer-shared";
4
+ import type { ExactVideoQuality, ITracer, Milliseconds, Nullable } from "@vkontakte/videoplayer-shared";
5
5
  export declare enum State {
6
6
  NONE = "none",
7
7
  MANIFEST_READY = "manifest_ready",
@@ -16,4 +16,5 @@ export interface Params {
16
16
  tracer: ITracer;
17
17
  isOnDemand?: boolean;
18
18
  dashMaxTvVideoQuality?: Nullable<ExactVideoQuality>;
19
+ getSeekTargetPosition?: () => Milliseconds | undefined;
19
20
  }
@@ -2,7 +2,7 @@ import type { ITuningConfig } from "../utils/tuningConfig";
2
2
  import type { IComponentLogger, IError, ILogger, IRange, IRectangle, ISubject, ITracer, IValueSubject, IWarning, Milliseconds, QualityLimits, Seconds } from "@vkontakte/videoplayer-shared";
3
3
  import type { IChromecastInitializer } from "./ChromecastProvider/ChromecastInitializer/types";
4
4
  import type { IExternalTextTrack, IInternalTextTrack, ITextTrack, IVideoTrack, IVolumeState, PlaybackRate, PlaybackState } from "../player/types";
5
- import type { AudioCodec, HttpConnectionMetrics, HttpConnectionType, HttpDownloadMetrics, IAudioStream, IAudioTrack, ICueSettings, ISources, IVideoStream, SeekState, VideoCodec } from "../player/types";
5
+ import type { AudioCodec, HttpConnectionMetrics, HttpConnectionType, HttpDownloadMetrics, IAudioStream, IAudioTrack, ISources, IVideoStream, SeekState, VideoCodec } from "../player/types";
6
6
  import type { IStateMachine } from "../utils/StateMachine/types";
7
7
  import type ThroughputEstimator from "../utils/ThroughputEstimator";
8
8
  export interface IProvider {
@@ -44,7 +44,6 @@ export interface DesiredStateValues {
44
44
  playbackRate: PlaybackRate;
45
45
  playbackState: PlaybackState;
46
46
  seekState: SeekState;
47
- textTrackCuesSettings: ICueSettings;
48
47
  videoStream: IVideoStream | undefined;
49
48
  /**
50
49
  * Порядок смены видео дорожек:
@@ -76,7 +75,6 @@ export interface IProviderOutput {
76
75
  availableAudioTracks$: IValueSubject<IAudioTrack[]>;
77
76
  availableAudioCodecs$: IValueSubject<AudioCodec[]>;
78
77
  availableTextTracks$: IValueSubject<ITextTrack[]>;
79
- currentTextTrack$: IValueSubject<ITextTrack["id"] | undefined>;
80
78
  isAudioAvailable$: IValueSubject<boolean>;
81
79
  autoVideoTrackLimits$: IValueSubject<QualityLimits | undefined>;
82
80
  autoVideoTrackLimitingAvailable$: IValueSubject<boolean>;
@@ -1,23 +1,21 @@
1
1
  import type { IAbrRule, IAbrRuleResolution, IVideoAbrContext, RuleLogData } from "../../types";
2
2
  import type { IVideoTrack } from "../../../../../player/types";
3
- import type { Kbps, Nullable } from "@vkontakte/videoplayer-shared";
4
3
  import { LimitAboveRule } from "../limitAboveRule";
5
- import type { ITuningConfig } from "../../../../../utils/tuningConfig";
6
4
  import type { RulePhaseConfig } from "../../controllers/abrPhaseController";
7
- type StallLogsArgs = [forwardBufferHealth: Nullable<number>, playbackRate: number, reserve: Kbps, playbackRateFactor: number, bitrateFactor: number, tuning: ITuningConfig];
8
- export declare class StallsRule extends LimitAboveRule<IVideoTrack, IVideoAbrContext, StallLogsArgs> implements IAbrRule<IVideoTrack, IVideoAbrContext> {
9
- private severeStallOccurred;
10
- private qualityRestrictionTimer;
11
- private lastStallDurationRestriction;
5
+ export declare class StallsRule extends LimitAboveRule<IVideoTrack, IVideoAbrContext, []> implements IAbrRule<IVideoTrack, IVideoAbrContext> {
6
+ private wasSevereStall;
7
+ private restrictedInCurrentStall;
8
+ private stalledQuality;
9
+ private stallsByQuality;
10
+ private recoveryStartedAt;
12
11
  private maxQualityLimitOnStall;
13
- private predictedThroughputWithoutData;
14
12
  private restrictionTracer;
15
13
  private restrictionStartedAt;
16
14
  constructor(phaseConfig: RulePhaseConfig);
17
15
  execute(context: IVideoAbrContext): IAbrRuleResolution<IVideoTrack>;
18
- protected createLogData(selectedTrack: IVideoTrack, forwardBufferHealth: Nullable<number>, playbackRate: number, reserve: Kbps, playbackRateFactor: number, bitrateFactor: number, tuning: ITuningConfig): RuleLogData;
16
+ protected createLogData(selectedTrack: IVideoTrack): RuleLogData;
17
+ private trackStallEpisode;
18
+ private resolveQualityLimit;
19
19
  private traceRestrictionSet;
20
20
  private traceRestrictionReset;
21
- private updateStallQualityLimits;
22
21
  }
23
- export {};
@@ -1,9 +1,8 @@
1
- import type { ExactVideoQuality, IObservable, IValueSubject, Milliseconds, Kbps, Seconds } from "@vkontakte/videoplayer-shared";
1
+ import type { IObservable, IValueSubject, Milliseconds, Seconds } from "@vkontakte/videoplayer-shared";
2
2
  import type { IVideoTrack } from "../../player/types";
3
3
  import type { ITuningConfig } from "../../utils/tuningConfig";
4
4
  interface IConnectData {
5
5
  videoLastDataObtainedTimestamp$: IValueSubject<Milliseconds>;
6
- throughput$: IValueSubject<number>;
7
6
  rtt$: IValueSubject<Milliseconds>;
8
7
  isBuffering$: IObservable<boolean>;
9
8
  isSeeked$: IObservable<boolean>;
@@ -18,7 +17,6 @@ interface IConnectData {
18
17
  declare class StallsManager {
19
18
  private currentStallDuration$;
20
19
  private videoLastDataObtainedTimestamp$;
21
- private throughput$;
22
20
  private rtt$;
23
21
  private tuning;
24
22
  private abrParams;
@@ -26,20 +24,15 @@ declare class StallsManager {
26
24
  private isSeeked$;
27
25
  private isBuffering$;
28
26
  private isPaused;
29
- private maxQualityLimit;
30
27
  private lastUniqueVideoTrackSelected;
31
28
  private currentStallsCount;
32
29
  private sumStallsDuration;
33
30
  private lastStallDuration;
34
31
  private providerStartWatchingTimestamp;
35
32
  private lastUniqueVideoTrackSelectedTimestamp;
36
- private predictedThroughputWithoutData;
37
- private qualityRestrictionTimer;
38
33
  private subscription;
39
34
  severeStallOccurred$: IValueSubject<boolean>;
40
35
  init(data: IConnectData): void;
41
- get videoMaxQualityLimit(): ExactVideoQuality | undefined;
42
- get predictedThroughput(): Kbps;
43
36
  get abrTuningParams(): ITuningConfig["autoTrackSelection"];
44
37
  set lastVideoTrackSelected(lastUniqueVideoTrackSelected: IVideoTrack);
45
38
  destroy(): void;
@@ -0,0 +1,16 @@
1
+ import type { IExternalTextTrack, IInternalTextTrack } from "../../player/types";
2
+ import type { IDesiredState, IProviderOutput } from "../types";
3
+ declare class TextTrackManager {
4
+ private available$;
5
+ private error$;
6
+ private subscription;
7
+ private externalTracks;
8
+ private internalTracks;
9
+ private emittedIds;
10
+ connect(desiredState: Pick<IDesiredState, "externalTextTracks" | "internalTextTracks">, providerOutput: Pick<IProviderOutput, "availableTextTracks$" | "error$">): void;
11
+ setExternal(tracks: IExternalTextTrack[]): void;
12
+ setInternal(tracks: IInternalTextTrack[]): void;
13
+ destroy(): void;
14
+ private emitAvailable;
15
+ }
16
+ export default TextTrackManager;
@@ -20,6 +20,7 @@ export interface DeviceHardware {
20
20
  export declare class DeviceChecker implements Checker {
21
21
  private _displayChecker;
22
22
  private _isMobile;
23
+ private _isSmartTV;
23
24
  private _current;
24
25
  private _iosVersion;
25
26
  private _highEntropyValues;
@@ -31,6 +32,7 @@ export declare class DeviceChecker implements Checker {
31
32
  get current(): CurrentClientDevice;
32
33
  get os(): OS;
33
34
  get details(): DeviceDetails;
35
+ get isSmartTV(): boolean;
34
36
  get hardware(): DeviceHardware;
35
37
  get highEntropyValues(): HighEntropyValues;
36
38
  get isIOS(): boolean;
@@ -42,12 +44,14 @@ export declare class DeviceChecker implements Checker {
42
44
  get isWindows(): boolean;
43
45
  get isLinux(): boolean;
44
46
  get isMobile(): boolean;
47
+ get isTablet(): boolean;
45
48
  get iOSVersion(): number | undefined;
46
49
  detect(): void;
47
50
  private detectHardware;
48
51
  detectGpu(): Promise<void>;
49
52
  private requestGpuInfo;
50
53
  private detectHighEntropyValues;
54
+ private detectSmartTv;
51
55
  private detectDevice;
52
56
  private detectOS;
53
57
  private normalizeOSName;
@@ -19,6 +19,7 @@ export declare enum UADataPlatform {
19
19
  }
20
20
  export interface HighEntropyValues {
21
21
  mobile?: boolean;
22
+ formFactors?: string[];
22
23
  model?: string;
23
24
  platform?: UADataPlatform;
24
25
  platformVersion?: string;
@@ -27,7 +28,8 @@ export interface HighEntropyValues {
27
28
  brands?: UADataBrandItem[];
28
29
  }
29
30
  export type NavigatorWithUserAgentData = Navigator & {
30
- userAgentData: {
31
- getHighEntropyValues: (values: Array<string>) => HighEntropyValues;
31
+ userAgentData?: {
32
+ mobile?: boolean;
33
+ getHighEntropyValues?: (values: Array<string>) => Promise<HighEntropyValues>;
32
34
  };
33
35
  };