@vkontakte/videoplayer-core 2.0.173-dev.ebda080eb.0 → 2.0.174-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 (36) 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/providers/DashLiveProvider/DashLiveProvider.d.ts +1 -0
  8. package/types/providers/DashProvider/dashCmafLiveProvider.d.ts +1 -0
  9. package/types/providers/DashProvider/lib/buffer.d.ts +1 -2
  10. package/types/providers/DashProvider/lib/fetcher.d.ts +6 -8
  11. package/types/providers/DashProvider/lib/player.d.ts +0 -1
  12. package/types/providers/DashProvider/lib/sourceBufferTaskQueue.d.ts +3 -1
  13. package/types/providers/DashProvider/lib/urlsCache.d.ts +23 -0
  14. package/types/providers/DashProviderVirtual/lib/buffer/types.d.ts +0 -2
  15. package/types/providers/DashProviderVirtual/lib/buffer/virtualBuffer/{baseVirtualBufferManager.versionA.d.ts → baseVirtualBufferManager.d.ts} +1 -3
  16. package/types/providers/DashProviderVirtual/lib/buffer/virtualBuffer/{byteRangeVirtualBufferManager.versionA.d.ts → byteRangeVirtualBufferManager.d.ts} +1 -2
  17. package/types/providers/DashProviderVirtual/lib/buffer/virtualBuffer/liveVirtualBuffer.d.ts +1 -1
  18. package/types/providers/DashProviderVirtual/lib/buffer/virtualBuffer/{templateVirtualBufferManager.versionA.d.ts → templateVirtualBufferManager.d.ts} +1 -1
  19. package/types/providers/DashProviderVirtual/lib/fetcher.d.ts +6 -8
  20. package/types/providers/DashProviderVirtual/lib/player/basePlayer.d.ts +0 -2
  21. package/types/providers/DashProviderVirtual/lib/urlsCache.d.ts +22 -0
  22. package/types/providers/HlsLiveProvider/index.d.ts +1 -0
  23. package/types/providers/HlsProvider/manifestDataExtractor.d.ts +2 -0
  24. package/types/providers/ProviderContainer/index.d.ts +0 -3
  25. package/types/providers/utils/buildFmp4MasterUrl.d.ts +12 -0
  26. package/types/providers/utils/generateLiveUrl.d.ts +1 -0
  27. package/types/utils/ClientChecker/services/DeviceChecker.d.ts +14 -0
  28. package/types/utils/ClientChecker/services/DisplayChecker.d.ts +3 -0
  29. package/types/utils/tuningConfig.d.ts +59 -13
  30. package/types/providers/utils/segmentCache/IndexedDbSegmentCacheStorage.d.ts +0 -54
  31. package/types/providers/utils/segmentCache/SegmentCache.d.ts +0 -59
  32. package/types/providers/utils/segmentCache/constants.d.ts +0 -20
  33. package/types/providers/utils/segmentCache/index.d.ts +0 -8
  34. package/types/providers/utils/segmentCache/segmentCacheDb.d.ts +0 -25
  35. package/types/providers/utils/segmentCache/segmentCacheUtils.d.ts +0 -25
  36. package/types/providers/utils/segmentCache/types.d.ts +0 -76
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vkontakte/videoplayer-core",
3
- "version": "2.0.173-dev.ebda080eb.0",
3
+ "version": "2.0.174-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.102-dev.ebda080eb.0"
45
+ "@vkontakte/videoplayer-shared": "1.0.103-beta.0"
46
46
  }
47
47
  }
@@ -34,4 +34,5 @@ export default class DashLiveProvider implements IProvider {
34
34
  private seek;
35
35
  private _dashCb;
36
36
  private syncPlayback;
37
+ private isSeekOffsetSupported;
37
38
  }
@@ -5,4 +5,5 @@ export default class DashCmafLiveProvider extends BaseDashProvider {
5
5
  constructor(params: IParams);
6
6
  protected override subscribe(): void;
7
7
  protected override seek(position: Milliseconds): void;
8
+ private isSeekOffsetSupported;
8
9
  }
@@ -42,7 +42,6 @@ export declare class BufferManager {
42
42
  private parsedInitData;
43
43
  private representations;
44
44
  private segments;
45
- private segmentIndexMap;
46
45
  private allInitsLoaded;
47
46
  private activeSegments;
48
47
  private forwardBufferRepresentations;
@@ -85,6 +84,7 @@ export declare class BufferManager {
85
84
  switchTo: ReturnType<typeof abortable<[Representation["id"], boolean | undefined], void>>;
86
85
  switchToOld: ReturnType<typeof abortable<[Representation["id"], boolean | undefined], void>>;
87
86
  warmUpMediaSource(): void;
87
+ private releaseStrandedSegment;
88
88
  abort(): Promise<boolean>;
89
89
  maintain(currentPosition?: Milliseconds | undefined): void;
90
90
  get lastDataObtainedTimestamp(): number;
@@ -110,7 +110,6 @@ export declare class BufferManager {
110
110
  private feedPreDownloadedFirstSegment;
111
111
  private loadByteRangeSegments;
112
112
  private prepareByteRangeFetchSegmentParams;
113
- private buildCacheMetadata;
114
113
  private prepareTemplateFetchSegmentParams;
115
114
  private abortActiveSegments;
116
115
  private onSomeTemplateDataLoaded;
@@ -4,7 +4,6 @@ import type { Byte, IValueSubject, ISubject, Milliseconds, IRange, ITracer, IErr
4
4
  import { abortable } from "@vkontakte/videoplayer-shared";
5
5
  import type { ExactVideoQuality } from "@vkontakte/videoplayer-shared";
6
6
  import type { CommonInit, GenericContainerParser, Segment, SegmentReference } from "../../utils/parsers/types";
7
- import type { ISegmentCacheStorage, CacheMetadata } from "../../utils/segmentCache";
8
7
  declare global {
9
8
  interface Navigator {
10
9
  connection: {
@@ -25,11 +24,12 @@ export interface IParams {
25
24
  tracer: ITracer;
26
25
  useEnableSubtitlesParam?: boolean;
27
26
  handleExtendedNetworkErrorsSet?: boolean;
27
+ useUrlCacheMechanism?: boolean;
28
28
  measureNonSegmentRequests?: boolean;
29
29
  measureFastSamples?: boolean;
30
+ cacheHitTtfbMaxMs?: Milliseconds;
30
31
  preloadFirstSegment?: boolean;
31
32
  maxQualityForFirstSegmentPreload?: ExactVideoQuality;
32
- segmentCacheService?: ISegmentCacheStorage;
33
33
  }
34
34
  export type Priority = "high" | "low" | "auto";
35
35
  export interface FetchParamsWithUrl extends FetchParams {
@@ -46,8 +46,8 @@ export interface FetchParams {
46
46
  isLowLatency?: boolean;
47
47
  bufferOptimisation?: boolean;
48
48
  ignoreNetworkErrors?: boolean;
49
+ urlCacheMechanismEnabled?: boolean;
49
50
  representationHeight?: number;
50
- cacheMetadata?: CacheMetadata;
51
51
  }
52
52
  export type RepresentationFetchResult = {
53
53
  init: CommonInit | null;
@@ -74,17 +74,17 @@ export declare class Fetcher {
74
74
  private readonly subscription;
75
75
  private compatibilityMode;
76
76
  private useEnableSubtitlesParam;
77
+ private useUrlCacheMechanism;
77
78
  private measureNonSegmentRequests;
78
79
  private measureFastSamples;
80
+ private cacheHitTtfbMaxMs;
79
81
  private preloadFirstSegment;
80
82
  private maxQualityForFirstSegmentPreload;
81
- private segmentCacheService;
82
- private segmentCache;
83
83
  private startupPhase;
84
84
  private performanceObserver;
85
85
  private pendingConnectionMetrics;
86
86
  private handleExtendedNetworkErrorsSet;
87
- constructor({ throughputEstimator, requestQuic, tracer, compatibilityMode, useEnableSubtitlesParam, handleExtendedNetworkErrorsSet, measureNonSegmentRequests, measureFastSamples, preloadFirstSegment, maxQualityForFirstSegmentPreload, segmentCacheService }: IParams);
87
+ constructor({ throughputEstimator, requestQuic, tracer, compatibilityMode, useEnableSubtitlesParam, handleExtendedNetworkErrorsSet, useUrlCacheMechanism, measureNonSegmentRequests, measureFastSamples, cacheHitTtfbMaxMs, preloadFirstSegment, maxQualityForFirstSegmentPreload }: IParams);
88
88
  private onHeadersReceived;
89
89
  private setupPerformanceObserver;
90
90
  private processPerformanceResourceTiming;
@@ -95,8 +95,6 @@ export declare class Fetcher {
95
95
  fetchManifest: ReturnType<typeof abortable<[string], string | null>>;
96
96
  fetch: ReturnType<typeof abortable<[string, FetchParams], ArrayBuffer | null>>;
97
97
  fetchRepresentation(segmentReference: SegmentReference, parser: GenericContainerParser<unknown>, fetchParams: FetchParams): Promise<RepresentationFetchResult | null>;
98
- /** Скипнутые сегменты не записаны в кэш — при следующем запросе региона докачаются как miss. */
99
- private traceSkippedCacheSegments;
100
98
  destroy(): void;
101
99
  private fetchByteRangeRepresentation;
102
100
  private fetchTemplateRepresentation;
@@ -40,7 +40,6 @@ export declare class Player {
40
40
  private subscriptionRemovable;
41
41
  private representationSubscription;
42
42
  private fetcher;
43
- private segmentCacheService;
44
43
  state$: StateMachine<State>;
45
44
  currentVideoRepresentation$: IValueSubject<Representation["id"] | undefined>;
46
45
  currentVideoRepresentationInit$: IValueSubject<CommonInit | undefined>;
@@ -1,4 +1,5 @@
1
1
  import type { Byte, IError, ISubject, Milliseconds } from "@vkontakte/videoplayer-shared";
2
+ import type { ITuningConfig } from "../../../utils/tuningConfig";
2
3
  declare class SourceBufferTaskQueue {
3
4
  bufferFull$: ISubject<Byte>;
4
5
  error$: ISubject<IError>;
@@ -7,7 +8,8 @@ declare class SourceBufferTaskQueue {
7
8
  private currentTask;
8
9
  private destroyed;
9
10
  private abortRequested;
10
- constructor(buffer: SourceBuffer);
11
+ private readonly tuning;
12
+ constructor(buffer: SourceBuffer, tuning: ITuningConfig);
11
13
  append(data: BufferSource, signal?: AbortSignal): Promise<boolean>;
12
14
  remove(from: Milliseconds, to: Milliseconds, signal?: AbortSignal): Promise<boolean>;
13
15
  abort(init?: BufferSource): Promise<boolean>;
@@ -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>;
@@ -3,7 +3,6 @@ import type { CommonInit, Manifest, Representation, Segment } from "../../../uti
3
3
  import type { Fetcher } from "../fetcher";
4
4
  import type { ITuningConfig } from "../../../../utils/tuningConfig";
5
5
  import type { VideoSegmentLoadProgress } from "../../../utils/Abr/types";
6
- import type { ISegmentCacheStorage } from "../../../utils/segmentCache";
7
6
  export type TRepresentationSwitchMode = "lazy" | "force";
8
7
  export declare enum SwithRepresentationMode {
9
8
  Lazy = "lazy",
@@ -16,7 +15,6 @@ export interface Dependencies {
16
15
  tuning: ITuningConfig;
17
16
  compatibilityMode?: boolean;
18
17
  manifest: Manifest | null;
19
- segmentCacheService?: ISegmentCacheStorage;
20
18
  getCurrentPosition(): Milliseconds | undefined;
21
19
  getCurrentStallDuration(): Milliseconds;
22
20
  isActiveLowLatency(): boolean;
@@ -2,7 +2,6 @@ import type { Fetcher, FetchParamsWithUrl, Priority, RepresentationFetchResult }
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";
5
- import type { ISegmentCacheStorage } from "../../../../utils/segmentCache";
6
5
  import type { Byte, IError, IRange, ISubject, ITracer, IValueSubject, Milliseconds, Seconds } from "@vkontakte/videoplayer-shared";
7
6
  import { abortable, Subscription } from "@vkontakte/videoplayer-shared";
8
7
  import type { NativeBufferManager } from "../nativeBufferManager";
@@ -20,7 +19,6 @@ export declare abstract class BaseVirtualBufferManager<T extends Segment> implem
20
19
  protected readonly fetcher: Fetcher;
21
20
  protected readonly tracer: ITracer;
22
21
  protected readonly tuning: ITuningConfig;
23
- protected readonly segmentCacheService: ISegmentCacheStorage | undefined;
24
22
  protected representations: Map<Representation["id"], Representation>;
25
23
  protected playingRepresentationId: Representation["id"] | undefined;
26
24
  protected downloadingRepresentationId: Representation["id"] | undefined;
@@ -55,7 +53,7 @@ export declare abstract class BaseVirtualBufferManager<T extends Segment> implem
55
53
  protected readonly getCurrentPosition: () => Milliseconds | undefined;
56
54
  protected readonly getCurrentStallDuration: () => Milliseconds | undefined;
57
55
  protected brokenSegmentAppendDetected: boolean;
58
- protected constructor(kind: StreamKind, nativeBufferManager: NativeBufferManager, representations: Representation[], { fetcher, tracer, tuning, getCurrentPosition, getCurrentStallDuration, manifest, segmentCacheService }: Dependencies);
56
+ protected constructor(kind: StreamKind, nativeBufferManager: NativeBufferManager, representations: Representation[], { fetcher, tracer, tuning, getCurrentPosition, getCurrentStallDuration, manifest }: Dependencies);
59
57
  protected abstract loadItems(itemsToLoad: IBufferPlaybackQueueItem<T>[], representation: Representation, priority?: Priority): Promise<void>;
60
58
  protected abstract selectItemsToLoad(): IBufferPlaybackQueueItem<T>[];
61
59
  protected abstract prepareFetchParams(items: IBufferPlaybackQueueItem<T>[], representation: Representation): FetchParamsWithUrl;
@@ -1,4 +1,4 @@
1
- import { BaseVirtualBufferManager } from "./baseVirtualBufferManager.versionA";
1
+ import { BaseVirtualBufferManager } from "./baseVirtualBufferManager";
2
2
  import type { Dependencies, IBufferPlaybackQueueItem, ISomeDataLoadedCallbackParams, IVirtualBufferManager } from "../types";
3
3
  import type { ByteRangeSegment, Representation, StreamKind } from "../../../../utils/parsers/types";
4
4
  import type { NativeBufferManager } from "../nativeBufferManager";
@@ -8,7 +8,6 @@ export declare class ByteRangeVirtualBufferManager extends BaseVirtualBufferMana
8
8
  protected override loadItems(itemsToLoad: IBufferPlaybackQueueItem<ByteRangeSegment>[], representation: Representation, priority?: Priority): Promise<void>;
9
9
  protected override selectItemsToLoad(): IBufferPlaybackQueueItem<ByteRangeSegment>[];
10
10
  protected override prepareFetchParams(items: IBufferPlaybackQueueItem<ByteRangeSegment>[], representation: Representation): FetchParamsWithUrl;
11
- private buildCacheMetadata;
12
11
  /**
13
12
  * Закидываем в буфер сегменты атомарнее чем сегмент целиком. Например, по боксам в мпеге и по блокам в вебме.
14
13
  * Таким образом не ждём его полной загрузки и готовы играть его намного быстрее
@@ -1,4 +1,4 @@
1
- import { TemplateVirtualBufferManager } from "./templateVirtualBufferManager.versionA";
1
+ import { TemplateVirtualBufferManager } from "./templateVirtualBufferManager";
2
2
  import type { Manifest, Representation, StreamKind, TemplateSegment, TemplateSegmentReference } from "../../../../utils/parsers/types";
3
3
  import type { NativeBufferManager } from "../nativeBufferManager";
4
4
  import type { Dependencies, IBufferPlaybackQueueItem, ISomeDataLoadedCallbackParams } from "../types";
@@ -1,4 +1,4 @@
1
- import { BaseVirtualBufferManager } from "./baseVirtualBufferManager.versionA";
1
+ import { BaseVirtualBufferManager } from "./baseVirtualBufferManager";
2
2
  import type { Dependencies, IBufferPlaybackQueueItem, ISomeDataLoadedCallbackParams, IVirtualBufferManager } from "../types";
3
3
  import type { TemplateSegment, Representation, StreamKind } from "../../../../utils/parsers/types";
4
4
  import type { NativeBufferManager } from "../nativeBufferManager";
@@ -4,7 +4,6 @@ import type { Byte, IError, IRange, ISubject, ITracer, IValueSubject, Millisecon
4
4
  import { abortable } from "@vkontakte/videoplayer-shared";
5
5
  import type { ExactVideoQuality } from "@vkontakte/videoplayer-shared";
6
6
  import type { CommonInit, GenericContainerParser, Segment, SegmentReference, StreamKind } from "../../utils/parsers/types";
7
- import type { ISegmentCacheStorage, CacheMetadata } from "../../utils/segmentCache";
8
7
  declare global {
9
8
  interface Navigator {
10
9
  connection: {
@@ -25,11 +24,12 @@ export interface IParams {
25
24
  tracer: ITracer;
26
25
  useEnableSubtitlesParam?: boolean;
27
26
  handleExtendedNetworkErrorsSet?: boolean;
27
+ useUrlCacheMechanism?: boolean;
28
28
  measureNonSegmentRequests?: boolean;
29
29
  measureFastSamples?: boolean;
30
+ cacheHitTtfbMaxMs?: Milliseconds;
30
31
  preloadFirstSegment?: boolean;
31
32
  maxQualityForFirstSegmentPreload?: ExactVideoQuality;
32
- segmentCacheService?: ISegmentCacheStorage;
33
33
  }
34
34
  export type Priority = "high" | "low" | "auto";
35
35
  export interface FetchParamsWithUrl extends FetchParams {
@@ -45,8 +45,8 @@ export interface FetchParams {
45
45
  measureThroughput?: boolean;
46
46
  isLowLatency?: boolean;
47
47
  bufferOptimisation?: boolean;
48
+ urlCacheMechanismEnabled?: boolean;
48
49
  kind: StreamKind;
49
- cacheMetadata?: CacheMetadata;
50
50
  }
51
51
  export type RepresentationFetchResult<T extends Segment> = {
52
52
  initMetadata: CommonInit | null;
@@ -73,17 +73,17 @@ export declare class Fetcher {
73
73
  private subscription;
74
74
  private compatibilityMode;
75
75
  private useEnableSubtitlesParam;
76
+ private useUrlCacheMechanism;
76
77
  private measureNonSegmentRequests;
77
78
  private measureFastSamples;
79
+ private cacheHitTtfbMaxMs;
78
80
  private preloadFirstSegment;
79
81
  private maxQualityForFirstSegmentPreload;
80
- private segmentCacheService;
81
- private segmentCache;
82
82
  private startupPhase;
83
83
  private performanceObserver;
84
84
  private pendingConnectionMetrics;
85
85
  private handleExtendedNetworkErrorsSet;
86
- constructor({ throughputEstimator, requestQuic, tracer, compatibilityMode, useEnableSubtitlesParam, handleExtendedNetworkErrorsSet, measureNonSegmentRequests, measureFastSamples, preloadFirstSegment, maxQualityForFirstSegmentPreload, segmentCacheService }: IParams);
86
+ constructor({ throughputEstimator, requestQuic, tracer, compatibilityMode, useEnableSubtitlesParam, handleExtendedNetworkErrorsSet, useUrlCacheMechanism, measureNonSegmentRequests, measureFastSamples, cacheHitTtfbMaxMs, preloadFirstSegment, maxQualityForFirstSegmentPreload }: IParams);
87
87
  private onHeadersReceived;
88
88
  private setupPerformanceObserver;
89
89
  private processResourceTiming;
@@ -94,8 +94,6 @@ export declare class Fetcher {
94
94
  fetchManifest: ReturnType<typeof abortable<[string], string | null>>;
95
95
  fetch: ReturnType<typeof abortable<[string, FetchParams], ArrayBuffer | null>>;
96
96
  fetchRepresentation<T extends Segment>(segmentReference: SegmentReference, parser: GenericContainerParser<unknown>, dowbloadAbortSignal: AbortSignal, priority?: Priority, representationHeight?: number, kind?: StreamKind): Promise<RepresentationFetchResult<T> | null | undefined>;
97
- /** Скипнутые сегменты не записаны в кэш — при следующем запросе региона докачаются как miss. */
98
- private traceSkippedCacheSegments;
99
97
  destroy(): void;
100
98
  private fetchByteRangeRepresentation;
101
99
  private fetchTemplateRepresentation;
@@ -9,7 +9,6 @@ import type { IError, IRange, ISubject, ISubscription, ITracer, IValueSubject, M
9
9
  import { abortable, Subject, Subscription, SubscriptionRemovable } from "@vkontakte/videoplayer-shared";
10
10
  import type { VideoSegmentLoadProgress } from "../../../utils/Abr/types";
11
11
  import { Fetcher } from "../fetcher";
12
- import type { ISegmentCacheStorage } from "../../../utils/segmentCache";
13
12
  import type { Dependencies, IVirtualBufferManager, SwithRepresentationMode } from "../buffer/types";
14
13
  import type { Params } from "./types";
15
14
  import { State } from "./types";
@@ -36,7 +35,6 @@ export declare abstract class BasePlayer {
36
35
  protected subscriptionRemovable: SubscriptionRemovable;
37
36
  protected representationSubscription: Subscription;
38
37
  protected fetcher: Fetcher;
39
- protected segmentCacheService: ISegmentCacheStorage | undefined;
40
38
  protected forceEnded$: ISubject<void>;
41
39
  protected stallWatchdogSubscription: ISubscription | undefined;
42
40
  protected destroyController: AbortController;
@@ -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;
@@ -30,4 +30,5 @@ export default class HlsLiveProvider implements IProvider {
30
30
  private seek;
31
31
  private syncPlayback;
32
32
  private generateLiveUrl;
33
+ private isSeekOffsetSupported;
33
34
  }
@@ -12,6 +12,8 @@ export type ManifestUrl = {
12
12
  bandwidth?: Kbps;
13
13
  size?: IRectangle;
14
14
  fps?: number;
15
+ /** HLS fMP4: идентификатор аудио-группы (EXT-X-MEDIA GROUP-ID), к которой привязан вариант через STREAM-INF AUDIO= */
16
+ audioGroupId?: string;
15
17
  };
16
18
  export type HLSManifestData = {
17
19
  qualityManifests: ManifestUrl[];
@@ -37,7 +37,6 @@ export default class ProviderContainer implements IProviderContainer {
37
37
  private currentProviderStarted;
38
38
  private volumeMultiplierManager;
39
39
  private dashMaxTvVideoQuality;
40
- private segmentCacheCleared;
41
40
  private mayday;
42
41
  private maydayStatistics;
43
42
  constructor(params: IParams);
@@ -51,8 +50,6 @@ export default class ProviderContainer implements IProviderContainer {
51
50
  private destroyProvider;
52
51
  private handleMaydayRecommendation;
53
52
  private applyErrorSideEffects;
54
- /** Битые данные в кэше могут вызывать повторные ошибки после реинита — очищаем кэш целиком. */
55
- private clearSegmentCacheOnError;
56
53
  private createProvider;
57
54
  private createScreenProvider;
58
55
  private createChromecastProvider;
@@ -0,0 +1,12 @@
1
+ import type { ManifestUrl } from "../HlsProvider/manifestDataExtractor";
2
+ export declare const FMP4_QUALITY_QUERY_PARAMS: readonly ["mq", "lq"];
3
+ /**
4
+ * HLS fMP4: дочерний плейлист варианта не содержит EXT-X-MEDIA групп, поэтому нативный HLS
5
+ * не знает какую аудио-группу подцепить и продолжает держать предыдущую — звук пропадает при
6
+ * смене качества. Решение — грузить мастер-плейлист с зафиксированным качеством через
7
+ * mq=lq=<height>, тогда бэк сам отдаст нужный вариант с правильной аудио-группой.
8
+ *
9
+ * Возвращает undefined, если у варианта нельзя надёжно определить высоту — в этом случае
10
+ * лучше оставить дефолтное поведение провайдера, чем отправлять мусор в URL.
11
+ */
12
+ export declare const buildFmp4MasterUrl: (masterUrl: string, qualityManifest: ManifestUrl) => URL | undefined;
@@ -4,6 +4,7 @@ export declare enum OffsetParameterType {
4
4
  PLAYBACK_SHIFT = 1,
5
5
  DASH_CMAF_OFFSET_P = 2
6
6
  }
7
+ export declare const hasOffsetMarker: (url: string) => boolean;
7
8
  declare const _default: (url: string, offset?: Milliseconds, type?: OffsetParameterType) => string;
8
9
  export default _default;
9
10
  export declare const getLiveUrlOffset: (url: string, type: OffsetParameterType) => number;
@@ -1,6 +1,7 @@
1
1
  import { CurrentClientDevice } from "../types/currentClientDevice";
2
2
  import type { DisplayChecker } from "./DisplayChecker";
3
3
  import type { Checker } from "../types/checker";
4
+ import type { HighEntropyValues } from "../types/userAgentData";
4
5
  export interface OS {
5
6
  name: string;
6
7
  version: string;
@@ -10,6 +11,12 @@ export interface DeviceDetails {
10
11
  vendor: string;
11
12
  model: string;
12
13
  }
14
+ export interface DeviceHardware {
15
+ cpuCores?: number;
16
+ memoryGb?: number;
17
+ gpuVendor?: string;
18
+ gpuArchitecture?: string;
19
+ }
13
20
  export declare class DeviceChecker implements Checker {
14
21
  private _displayChecker;
15
22
  private _isMobile;
@@ -18,10 +25,14 @@ export declare class DeviceChecker implements Checker {
18
25
  private _highEntropyValues;
19
26
  private _os;
20
27
  private _details;
28
+ private _hardware;
29
+ private _gpuDetection;
21
30
  constructor(displayChecker: DisplayChecker);
22
31
  get current(): CurrentClientDevice;
23
32
  get os(): OS;
24
33
  get details(): DeviceDetails;
34
+ get hardware(): DeviceHardware;
35
+ get highEntropyValues(): HighEntropyValues;
25
36
  get isIOS(): boolean;
26
37
  get isIPadOS(): boolean;
27
38
  get isMac(): boolean;
@@ -33,6 +44,9 @@ export declare class DeviceChecker implements Checker {
33
44
  get isMobile(): boolean;
34
45
  get iOSVersion(): number | undefined;
35
46
  detect(): void;
47
+ private detectHardware;
48
+ detectGpu(): Promise<void>;
49
+ private requestGpuInfo;
36
50
  private detectHighEntropyValues;
37
51
  private detectDevice;
38
52
  private detectOS;
@@ -10,6 +10,7 @@ export declare class DisplayChecker implements Checker {
10
10
  private _screenHeight;
11
11
  private _screenWidth;
12
12
  private _colorDepth;
13
+ private _colorGamut;
13
14
  private _displayMode;
14
15
  private _isStandalone;
15
16
  get isTouch(): boolean;
@@ -21,8 +22,10 @@ export declare class DisplayChecker implements Checker {
21
22
  get pixelRatio(): number;
22
23
  get isHDR(): boolean;
23
24
  get colorDepth(): number;
25
+ get colorGamut(): ColorGamut | undefined;
24
26
  get displayMode(): DisplayMode;
25
27
  get isStandalone(): boolean;
26
28
  detect(): void;
29
+ private detectColorGamut;
27
30
  private detectDisplayMode;
28
31
  }
@@ -5,7 +5,6 @@ import { IOSPreferredFormat } from "../enums/IOSPreferredFormat";
5
5
  import type { Byte, Kbps, Milliseconds, RecursivePartial, Seconds, TimerModule } 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
- import type { SegmentCacheConfig } from "../providers/utils/segmentCache/types";
9
8
  export type ITuningConfig = {
10
9
  /** @deprecated */
11
10
  configName?: string[];
@@ -44,6 +43,13 @@ export type ITuningConfig = {
44
43
  smallSampleMinDuration: Milliseconds;
45
44
  cacheThresholdSize: Milliseconds;
46
45
  /**
46
+ * UVP-11541: верхняя граница порога, ниже которого ответ считается кэш-хитом по TTFB.
47
+ * Без неё порог растёт вместе с rtt и после деградации сети объявляет кэшем любой быстрый
48
+ * сетевой ответ — оценка застывает навсегда. Замер на CDN: кэш отвечает за 0.5–1.2 мс,
49
+ * сеть не быстрее 45 мс, так что коридор широкий.
50
+ */
51
+ cacheHitTtfbMaxMs: Milliseconds;
52
+ /**
47
53
  * Фичафлаг UVP-10855: лечит залипание throughput на быстрых соединениях.
48
54
  *
49
55
  * Проблема: на быстром соединении крупный сегмент реально скачивается за ≤ cacheThresholdSize
@@ -203,6 +209,7 @@ export type ITuningConfig = {
203
209
  usePersistentGaps: boolean;
204
210
  abrThrottle: number;
205
211
  useVideoElementWaitingCurrentTimeReassign: boolean;
212
+ useVideoElementProgressCurrentTimeReassign: boolean;
206
213
  stallWatchdogInterval: Milliseconds;
207
214
  liveUpdateInterval: Milliseconds;
208
215
  liveStallReinitInterval: Milliseconds;
@@ -252,20 +259,41 @@ export type ITuningConfig = {
252
259
  maxQualityForFirstSegmentPreload: ExactVideoQuality;
253
260
  /** Включает отправку телеметрии трейсера (resume) при превышении stall watchdog */
254
261
  tracerResumeOnUnexpectedStall: boolean;
262
+ /** Включает отправку телеметрии трейсера (resume) при выборе ABR качества не выше lowQualityTelemetryLimit */
263
+ tracerResumeOnLowQuality: boolean;
264
+ /**
265
+ * Эксперимент: при `true` отключает `await this.reinitDecoderIfNeeded(shouldForceSeek)`
266
+ * внутри `stallWatchdogIntervalCallback`. По умолчанию `false` — текущее поведение
267
+ * (force-seek раз в секунду при глубоком stall). Гипотеза: возможно, force-seek из
268
+ * watchdog'а сам по себе тормозит восстановление на длинных столлах (аналог B1,
269
+ * но через полное отключение reinit, а не троттлинг частоты).
270
+ */
271
+ disableStallWatchdogReinitDecoder: boolean;
255
272
  /**
256
- * При отмене signal текущей задачи sourceBufferTaskQueue (например, через
257
- * `maintainAbortController.abort()` в `prepareSeek`) прерывать зависшую MSE-операцию
258
- * через `buffer.abort()`. Без этого `completeTask` не вызовется при залипшем
259
- * SourceBuffer и промис `append`/`remove` зависнет навечно `prepareSeek`
260
- * застрянет на `await maintainMutexPromise` (V3 deadlock), stall растёт до
261
- * `crashOnStallTimeout=25с`.
273
+ * Эксперимент: при `destroy()` резолвить callback'и `currentTask` и всех задач в очереди,
274
+ * чтобы их промисы (`await this.queue.append(...)`, `await this.queue.remove(...)`) не висели
275
+ * вечно после разрушения очереди. По умолчанию `false` поведение как до эксперимента:
276
+ * `queue = []; currentTask = null` без вызова callback'ов, промисы зависают (pre-existing behaviour).
277
+ * Включать поэтапно, начиная с процента трафика, для A/B по метрикам утечек и восстановления.
278
+ */
279
+ resolveQueueOnDestroy: boolean;
280
+ /**
281
+ * Освобождает застрявшую загрузку сегментов в `DashProvider`: запись из `activeSegments`,
282
+ * когда её загрузчик закончил работу или когда `warmUpMediaSource()` переоткрыл
283
+ * `mediaSource`, и колбэки задач `sourceBufferTaskQueue`, когда очередь разрушается
284
+ * посреди `append` (UVP-11642, UVP-11519).
285
+ *
286
+ * Без первого ранний выход `onSegmentFullyAppended` по протухшему `sourceBuffer` оставляет
287
+ * запись навсегда, а `maintain()` планирует загрузки только при пустом `activeSegments` —
288
+ * видеодорожка перестаёт докачиваться до конца жизни `BufferManager`. Без второго
289
+ * `destroy()` зануляет `currentTask`, не вызвав callback, `loadTemplateSegment` навсегда
290
+ * стоит на `await`, а `initRepresentations` не доходит до `REPRESENTATIOS_READY`.
262
291
  *
263
- * По умолчанию false (opt-in). Дешёвый фикс, но поведенческое изменение:
264
- * единственный побочный эффект лишний `buffer.abort()` при штатной отмене
265
- * maintain (например, при обычном seek), но MSE `abort()` без активной операции
266
- * — no-op по спеке. Включать поэтапно, начиная с процента.
292
+ * Освобождённый сегмент возвращается в `NONE` через `abortSegment()`, то есть будет скачан
293
+ * заново: пережили ли байты переоткрытие буфера, достоверно неизвестно, и лишняя докачка
294
+ * дешевле замершего воспроизведения.
267
295
  */
268
- abortSourceBufferOnSignal: boolean;
296
+ recoverStuckSegmentLoading: boolean;
269
297
  };
270
298
  dashCmafLive: {
271
299
  externalStopControl: boolean;
@@ -313,6 +341,15 @@ export type ITuningConfig = {
313
341
  */
314
342
  maxPausedTime: number;
315
343
  catchupLiveForMutedInactiveTab: boolean;
344
+ /**
345
+ * UVP-2618. Отключать перемотку лайва, если ссылка пришла без маркера offset (`_offset_p` в пути
346
+ * или query-параметр `?offset_p=`). Применяется ко всем live-форматам: dash_live, dash_live_cmaf,
347
+ * hls_live, hls_live_cmaf. Когда манифест отдаёт DVR-окно (shiftDuration / liveSeekableDuration /
348
+ * X-Playback-Duration), но в URL нет маркера, `generateLiveUrl` не сможет подставить offset и плеер
349
+ * молча переинициализируется на live edge. Включение делает DVR-окно нулевым и скрывает таймлайн.
350
+ * По умолчанию false (прежнее поведение), включается для эксперимента.
351
+ */
352
+ disableLiveSeekWithoutOffsetMarker: boolean;
316
353
  };
317
354
  enableWakeLock: boolean;
318
355
  enableTelemetryAtStart: boolean;
@@ -353,6 +390,7 @@ export type ITuningConfig = {
353
390
  * include-threshold - записываем столлы длинее stallIgnoreThreshold
354
391
  */
355
392
  stallHandlingStrategy: "verbose" | "exclude-threshold" | "include-threshold";
393
+ stallIgnoreOnPause: boolean;
356
394
  gapWatchdogInterval: Milliseconds;
357
395
  requestQuick: boolean;
358
396
  /** @deprecated HLS.js удалён, флаг ничего не делает */
@@ -440,6 +478,15 @@ export type ITuningConfig = {
440
478
  */
441
479
  handleExtendedNetworkErrorsSet?: boolean;
442
480
  /**
481
+ * Кэшируем ответы от сервера руками, так как из за динамичесокй природы некоторых параметров в урле
482
+ * браузер это не может сделать.
483
+ */
484
+ useUrlCacheMechanism?: boolean;
485
+ /**
486
+ * Очищаем кэш урлов при падение провайдера.
487
+ */
488
+ dropUrlCacheWhenProviderCrashed?: boolean;
489
+ /**
443
490
  * При смене/реините провайдера игнорируем результат того, смогло видео заиграть или нет.
444
491
  */
445
492
  ignoreForcePlayResultWhenProviderChanged?: boolean;
@@ -467,7 +514,6 @@ export type ITuningConfig = {
467
514
  * провайдер по-прежнему ждёт canplay, чтобы play() не вызывался до появления данных.
468
515
  */
469
516
  readyOnLoadedMetadata: boolean;
470
- segmentCache: SegmentCacheConfig;
471
517
  };
472
518
  export type IOptionalTuningConfig = RecursivePartial<ITuningConfig>;
473
519
  export declare const fillDefault: (partial: IOptionalTuningConfig) => ITuningConfig;