@vkontakte/videoplayer-core 2.0.171-dev.ed76c949d.0 → 2.0.172-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 (30) hide show
  1. package/es2015.cjs +17 -127
  2. package/es2015.esm.js +17 -127
  3. package/esnext.cjs +16 -126
  4. package/esnext.esm.js +16 -126
  5. package/evergreen.esm.js +16 -126
  6. package/package.json +2 -2
  7. package/types/player/Player.d.ts +4 -1
  8. package/types/player/types.d.ts +21 -5
  9. package/types/providers/DashLiveProvider/utils/LiveDashPlayer.d.ts +9 -0
  10. package/types/providers/DashProvider/baseDashProvider.d.ts +0 -3
  11. package/types/providers/DashProvider/lib/buffer.d.ts +6 -2
  12. package/types/providers/DashProvider/lib/player.d.ts +1 -0
  13. package/types/providers/DashProviderVirtual/baseDashProvider.d.ts +1 -4
  14. package/types/providers/DashProviderVirtual/lib/buffer/nativeBufferManager.d.ts +3 -1
  15. package/types/providers/DashProviderVirtual/lib/buffer/sourceBufferTaskQueue.d.ts +3 -1
  16. package/types/providers/DashProviderVirtual/lib/buffer/virtualBuffer/baseVirtualBufferManager.versionA.d.ts +3 -1
  17. package/types/providers/DashProviderVirtual/lib/player/basePlayer.d.ts +3 -1
  18. package/types/providers/ProviderContainer/Mayday/heuristics/SegmentAppendHeuristic.d.ts +10 -0
  19. package/types/providers/ProviderContainer/Mayday/types.d.ts +1 -1
  20. package/types/providers/types.d.ts +4 -2
  21. package/types/providers/utils/Abr/abrManager.d.ts +2 -0
  22. package/types/providers/utils/Abr/selectTrackByRules.d.ts +23 -0
  23. package/types/providers/utils/Abr/utils.d.ts +4 -1
  24. package/types/providers/utils/HTMLVideoElement/observable.d.ts +1 -1
  25. package/types/providers/utils/HTMLVideoElement/pool.d.ts +1 -1
  26. package/types/utils/ThroughputEstimator.d.ts +2 -0
  27. package/types/utils/buffer/isBrokenSegmentAppend.d.ts +3 -0
  28. package/types/utils/buffer/timeRangesToIntervals.d.ts +3 -0
  29. package/types/utils/tuningConfig.d.ts +34 -4
  30. package/types/utils/autoSelectTrack.d.ts +0 -36
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vkontakte/videoplayer-core",
3
- "version": "2.0.171-dev.ed76c949d.0",
3
+ "version": "2.0.172-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.100-dev.ed76c949d.0"
45
+ "@vkontakte/videoplayer-shared": "1.0.101-beta.1"
46
46
  }
47
47
  }
@@ -1,5 +1,5 @@
1
1
  import type { IOptionalTuningConfig } from "../utils/tuningConfig";
2
- import type { ILogEntry, ITracer, QualityLimits, Seconds, VideoQuality } from "@vkontakte/videoplayer-shared";
2
+ import type { ILogEntry, ITracer, QualityLimits, Seconds, VideoQuality, DebugData } from "@vkontakte/videoplayer-shared";
3
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";
4
4
  import type { IPlayerOptions } from "../utils/playerOptions";
5
5
  export default class Player implements IPlayer {
@@ -78,7 +78,10 @@ export default class Player implements IPlayer {
78
78
  getExactTime(): Seconds;
79
79
  getExactLiveTime(): Seconds;
80
80
  getAllLogs(): ILogEntry[];
81
+ getDebugData(): DebugData;
82
+ private buildDebugData;
81
83
  private setIntrinsicVideoSize;
84
+ private initDebugDataSubscriptions;
82
85
  private initDesiredStateSubscriptions;
83
86
  private initProviderContainerSubscription;
84
87
  private initChromecastSubscription;
@@ -1,4 +1,4 @@
1
- import type { IError, ILogEntry, IObservable, IRectangle, IValueObservable, IValueSubject, Kbps, Milliseconds, QualityLimits, Seconds, Subject, ValueSubject, VideoQuality } from "@vkontakte/videoplayer-shared";
1
+ import type { DebugData, IError, ILogEntry, IObservable, IRectangle, IValueObservable, IValueSubject, Kbps, Milliseconds, QualityLimits, Seconds, Subject, ValueSubject, VideoQuality } from "@vkontakte/videoplayer-shared";
2
2
  import type { dump } from "../utils/playbackTelemetry";
3
3
  export interface StartEnd<Unit extends number> {
4
4
  start: Unit;
@@ -311,17 +311,29 @@ export interface PlayerInfoValues {
311
311
  */
312
312
  currentPlaybackRate$: PlaybackRate;
313
313
  /**
314
- * Текущий буффер плеера (тот; который содержит текущую позицию воспроизведения)
314
+ * Текущий видео буффер-плеера (тот; который содержит текущую позицию воспроизведения)
315
315
  *
316
316
  * default value: `undefined`
317
317
  */
318
- currentBuffer$: StartEnd<Seconds> | undefined;
318
+ currentVideoBuffer$: StartEnd<Seconds> | undefined;
319
319
  /**
320
- * Текущий браузерный буффер (тот; который содержит текущую позицию воспроизведения)
320
+ * Текущий аудио-буффер плеера (тот; который содержит текущую позицию воспроизведения)
321
321
  *
322
322
  * default value: `undefined`
323
323
  */
324
- currentNativeBuffer$: StartEnd<Seconds> | undefined;
324
+ currentAudioBuffer$: StartEnd<Seconds> | undefined;
325
+ /**
326
+ * Текущий браузерный видео-буффер (тот; который содержит текущую позицию воспроизведения)
327
+ *
328
+ * default value: `undefined`
329
+ */
330
+ currentNativeVideoBuffer$: StartEnd<Seconds> | undefined;
331
+ /**
332
+ * Текущий браузерный аудио-буффер (тот; который содержит текущую позицию воспроизведения)
333
+ *
334
+ * default value: `undefined`
335
+ */
336
+ currentNativeAudioBuffer$: StartEnd<Seconds> | undefined;
325
337
  /** Суммарная длительность всех буферизованных диапазонов в миллисекундах */
326
338
  totalBufferDuration$: Milliseconds | undefined;
327
339
  /**
@@ -456,6 +468,10 @@ export interface PlayerInfoValues {
456
468
  * Длина аудио сегмента
457
469
  */
458
470
  currentAudioSegmentLength$: number;
471
+ /**
472
+ * Отладочная информация
473
+ */
474
+ debugData$: DebugData;
459
475
  }
460
476
  export type IPlayerInfo = { [K in keyof PlayerInfoValues]: IValueObservable<PlayerInfoValues[K]> };
461
477
  export type PlayerInfoImpl = { [K in keyof PlayerInfoValues]: ValueSubject<PlayerInfoValues[K]> };
@@ -60,6 +60,7 @@ export default class LiveDashPlayer {
60
60
  */
61
61
  private waitingForFirstBufferAfterSrcChange;
62
62
  private params;
63
+ private playbackStateSubscription;
63
64
  soundProhibitedEvent$: Subject<void>;
64
65
  constructor(params: IParams);
65
66
  attachSource(manifestUrl: string): void;
@@ -101,6 +102,14 @@ export default class LiveDashPlayer {
101
102
  * send buffering notification to player
102
103
  */
103
104
  private _notifyBuffering;
105
+ private _notifyLoadStart;
106
+ /**
107
+ * Лоадер для случая, когда play запрошен до завершения подготовки видео:
108
+ * syncPlayback при этом умирает на раннем выходе по активному videoState-переходу и не вызывает play().
109
+ * Смотрим только переходы подготовки (MANIFEST_READY/READY): переход PAUSED→PLAYING создаётся
110
+ * syncPlayback позже (debounce(0)), поэтому обычный resume сюда не попадает.
111
+ */
112
+ private _syncBufferingWithDesiredPlayback;
104
113
  /**
105
114
  * initialize video tag, add necessary event listeners
106
115
  * @private
@@ -4,7 +4,6 @@ import { ProviderState } from "./lib/types";
4
4
  import type { Representation, Stream } from "../utils/parsers/types";
5
5
  import type { IProvider, IProviderAllocationResolution, IProviderParams } from "../types";
6
6
  import type { IObservableVideo } from "../utils/HTMLVideoElement/observable";
7
- import { TrackHistory } from "../../utils/autoSelectTrack";
8
7
  import type { IStateMachine } from "../../utils/StateMachine/types";
9
8
  import type { ExactVideoQuality, ISubscription, ITracer, Milliseconds, Nullable } from "@vkontakte/videoplayer-shared";
10
9
  import { Player } from "./lib/player";
@@ -47,8 +46,6 @@ export default abstract class BaseDashProvider implements IProvider {
47
46
  }>;
48
47
  protected videoStreamsMap: Map<Stream, IVideoTrack[]>;
49
48
  protected audioStreamsMap: Map<Stream, IAudioTrack[]>;
50
- protected videoTrackSwitchHistory: TrackHistory<IVideoTrack>;
51
- protected audioTrackSwitchHistory: TrackHistory<IAudioTrack>;
52
49
  constructor(params: IParams);
53
50
  protected abstract seek(position: Milliseconds, forcePrecise: boolean): void;
54
51
  protected getProviderSubscriptionInfo(): IProviderSubscriptionInfo;
@@ -1,5 +1,5 @@
1
1
  import type { ITuningConfig } from "../../../utils/tuningConfig";
2
- import type { IError, IRange, ISubject, IValueSubject, Milliseconds } from "@vkontakte/videoplayer-shared";
2
+ import type { IError, IRange, ISubject, ITracer, IValueSubject, Milliseconds } from "@vkontakte/videoplayer-shared";
3
3
  import { abortable } from "@vkontakte/videoplayer-shared";
4
4
  import type { Fetcher } from "./fetcher";
5
5
  import type { CommonInit, Manifest, Representation, Segment, Stream, StreamKind } from "../../utils/parsers/types";
@@ -11,6 +11,7 @@ export interface Dependencies {
11
11
  isActiveLowLatency: () => boolean;
12
12
  compatibilityMode?: boolean;
13
13
  manifest: Manifest | null;
14
+ tracer: ITracer;
14
15
  }
15
16
  export interface Gap extends IRange<Milliseconds> {
16
17
  representation: Representation["id"];
@@ -67,6 +68,7 @@ export declare class BufferManager {
67
68
  private baseUrlsIndex;
68
69
  private compatibilityMode;
69
70
  private preloadOnly;
71
+ private tracer;
70
72
  private isLive;
71
73
  private liveUpdateSegmentIndex;
72
74
  private liveInitialAdditionalOffset;
@@ -75,7 +77,8 @@ export declare class BufferManager {
75
77
  private lastDataObtainedTimestampMs;
76
78
  private loadByteRangeSegmentsTimeoutId;
77
79
  private preDownloadedFirstSegment;
78
- constructor(kind: StreamKind, mediaSource: MediaSource, representations: Representation[], { fetcher, tuning, getCurrentPosition, isActiveLowLatency, compatibilityMode, manifest }: Dependencies);
80
+ private brokenSegmentAppendDetected;
81
+ constructor(kind: StreamKind, mediaSource: MediaSource, representations: Representation[], { fetcher, tuning, getCurrentPosition, isActiveLowLatency, compatibilityMode, manifest, tracer }: Dependencies);
79
82
  startWith: ReturnType<typeof abortable<[Representation["id"]]>>;
80
83
  switchToWithPreviousAbort(newRepresentationId: Representation["id"], dropBuffer?: boolean): Promise<void | undefined>;
81
84
  switchTo: ReturnType<typeof abortable<[Representation["id"], boolean | undefined], void>>;
@@ -119,6 +122,7 @@ export declare class BufferManager {
119
122
  */
120
123
  private onSomeByteRangesDataLoaded;
121
124
  private onSegmentFullyAppended;
125
+ private detectBrokenSegmentAppend;
122
126
  private abortSegment;
123
127
  private loadNextInit;
124
128
  private loadInit;
@@ -83,6 +83,7 @@ export declare class Player {
83
83
  private gapWatchdogActive;
84
84
  private gapWatchdogSubscription;
85
85
  private stallWatchdogSubscription;
86
+ private stallTracer;
86
87
  private livePauseWatchdogSubscription;
87
88
  private liveWasInterrupted;
88
89
  private isOnDemand;
@@ -1,10 +1,9 @@
1
- import type { IAudioTrack, IBaseTrack, IDashURLSource, IHLSSource, IInternalTextTrack, IVideoTrack, VideoCodec } from "../../player/types";
1
+ import type { IAudioTrack, IDashURLSource, IHLSSource, IInternalTextTrack, IVideoTrack, VideoCodec } from "../../player/types";
2
2
  import type { IProviderSubscriptionInfo } from "./lib/types";
3
3
  import { ProviderState } from "./lib/types";
4
4
  import type { Representation, Stream } from "../utils/parsers/types";
5
5
  import type { IProvider, IProviderAllocationResolution, IProviderParams } from "../types";
6
6
  import type { IObservableVideo } from "../utils/HTMLVideoElement/observable";
7
- import { TrackHistory } from "../../utils/autoSelectTrack";
8
7
  import type { IStateMachine } from "../../utils/StateMachine/types";
9
8
  import type { ExactVideoQuality, ISubscription, ITracer, Milliseconds, Nullable } from "@vkontakte/videoplayer-shared";
10
9
  import DroppedFramesManager from "../utils/HTMLVideoElement/DroppedFramesManager";
@@ -47,8 +46,6 @@ export default abstract class BaseDashProvider implements IProvider {
47
46
  }>;
48
47
  protected videoStreamsMap: Map<Stream, IVideoTrack[]>;
49
48
  protected audioStreamsMap: Map<Stream, IAudioTrack[]>;
50
- protected videoTrackSwitchHistory: TrackHistory<IVideoTrack>;
51
- protected audioTrackSwitchHistory: TrackHistory<IBaseTrack>;
52
49
  constructor(params: IParams);
53
50
  protected abstract seek(position: Milliseconds, forcePrecise: boolean): void;
54
51
  protected abstract getPlayer(): BasePlayer;
@@ -1,12 +1,14 @@
1
1
  import type { IError, IRange, ISubject, IValueSubject, Milliseconds } from "@vkontakte/videoplayer-shared";
2
+ import type { ITuningConfig } from "../../../../utils/tuningConfig";
2
3
  export declare class NativeBufferManager {
3
4
  error$: ISubject<IError>;
4
5
  updateEnd$: IValueSubject<void>;
5
6
  private mediaSource;
6
7
  private sourceBuffer;
7
8
  private sourceBufferTaskQueue;
9
+ private readonly tuning;
8
10
  private subscription;
9
- constructor(mediaSource: MediaSource);
11
+ constructor(mediaSource: MediaSource, tuning: ITuningConfig);
10
12
  init(mime: string, codecs: string): void;
11
13
  addInitSegment(initView: BufferSource, signal?: AbortSignal): Promise<boolean>;
12
14
  append(segmentView: BufferSource, signal?: AbortSignal): Promise<boolean>;
@@ -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>;
@@ -52,6 +52,7 @@ export declare abstract class BaseVirtualBufferManager<T extends Segment> implem
52
52
  protected subscription: Subscription;
53
53
  protected readonly getCurrentPosition: () => Milliseconds | undefined;
54
54
  protected readonly getCurrentStallDuration: () => Milliseconds | undefined;
55
+ protected brokenSegmentAppendDetected: boolean;
55
56
  protected constructor(kind: StreamKind, nativeBufferManager: NativeBufferManager, representations: Representation[], { fetcher, tracer, tuning, getCurrentPosition, getCurrentStallDuration, manifest }: Dependencies);
56
57
  protected abstract loadItems(itemsToLoad: IBufferPlaybackQueueItem<T>[], representation: Representation, priority?: Priority): Promise<void>;
57
58
  protected abstract selectItemsToLoad(): IBufferPlaybackQueueItem<T>[];
@@ -96,7 +97,7 @@ export declare abstract class BaseVirtualBufferManager<T extends Segment> implem
96
97
  */
97
98
  protected sanitizeBufferPlaybackQueue(): boolean;
98
99
  protected forceSwitchCondition(oldRepresentation: Representation, newRepresentation: Representation): boolean;
99
- protected clearBuffer(): Promise<void>;
100
+ protected clearBuffer(signal?: AbortSignal): Promise<void>;
100
101
  private resetBuffer;
101
102
  protected abortDownload(): void;
102
103
  protected abortDownloadingItems(): void;
@@ -120,6 +121,7 @@ export declare abstract class BaseVirtualBufferManager<T extends Segment> implem
120
121
  protected parseFeedableSegmentChunk(chunk: DataView): DataView | null;
121
122
  protected onItemFullyDownloaded(downloadedItem: IBufferPlaybackQueueItem<T>): void;
122
123
  protected onItemFullyAppended(appendedItem: IBufferPlaybackQueueItem<T>): void;
124
+ private detectBrokenSegmentAppend;
123
125
  protected removeSegment(nextRemoveItem: IBufferPlaybackQueueItem<T>, signal: AbortSignal): Promise<void>;
124
126
  protected onDownloadItem(downloadedItem: IBufferPlaybackQueueItem<T>): void;
125
127
  protected pruneVirtualBuffer(currentPosition: Milliseconds): void;
@@ -63,9 +63,11 @@ export declare abstract class BasePlayer {
63
63
  liveSeekableDuration$: IValueSubject<Milliseconds>;
64
64
  liveAvailabilityStartTime$: IValueSubject<Milliseconds>;
65
65
  liveStreamStatus$: IValueSubject<LiveStreamStatus | undefined>;
66
- currentBuffer$: IValueSubject<IRange<Seconds>>;
66
+ currentVideoBuffer$: IValueSubject<IRange<Seconds>>;
67
+ currentAudioBuffer$: IValueSubject<IRange<Seconds>>;
67
68
  bufferLength$: IValueSubject<Milliseconds>;
68
69
  nativeBufferLength$: IValueSubject<Milliseconds>;
70
+ nativeAudioBufferLength$: IValueSubject<IRange<Seconds>>;
69
71
  liveLatency$: IValueSubject<Milliseconds | undefined>;
70
72
  liveLoadBufferLength$: IValueSubject<Milliseconds>;
71
73
  livePositionFromPlayer$: IValueSubject<number>;
@@ -0,0 +1,10 @@
1
+ import type { IError } from "@vkontakte/videoplayer-shared";
2
+ import type { IHeuristicDeps } from "../types";
3
+ import type { ISyncHeuristic, HeuristicResult } from "./IHeuristic";
4
+ export declare class SegmentAppendHeuristic implements ISyncHeuristic {
5
+ private deps;
6
+ static readonly heuristicName = "SegmentAppendHeuristic";
7
+ readonly type = "sync";
8
+ constructor(deps: IHeuristicDeps);
9
+ analyze(error: IError): HeuristicResult;
10
+ }
@@ -14,7 +14,7 @@ export interface IMaydayProviderOutput {
14
14
  position$: IValueSubject<number>;
15
15
  currentVideoTrack$: IValueSubject<IVideoTrack | undefined>;
16
16
  totalBufferDuration$: IValueSubject<Milliseconds | undefined>;
17
- currentNativeBuffer$: IValueSubject<IRange<Seconds> | undefined>;
17
+ currentNativeVideoBuffer$: IValueSubject<IRange<Seconds> | undefined>;
18
18
  bufferRangeCount$: IValueSubject<number | undefined>;
19
19
  availableVideoStreams$: IValueSubject<IVideoStream[]>;
20
20
  currentAudioStream$: IValueSubject<IAudioStream | undefined>;
@@ -81,8 +81,10 @@ export interface IProviderOutput {
81
81
  autoVideoTrackLimits$: IValueSubject<QualityLimits | undefined>;
82
82
  autoVideoTrackLimitingAvailable$: IValueSubject<boolean>;
83
83
  canChangePlaybackSpeed$: IValueSubject<boolean | undefined>;
84
- currentBuffer$: IValueSubject<IRange<Seconds> | undefined>;
85
- currentNativeBuffer$: IValueSubject<IRange<Seconds> | undefined>;
84
+ currentVideoBuffer$: IValueSubject<IRange<Seconds> | undefined>;
85
+ currentAudioBuffer$: IValueSubject<IRange<Seconds> | undefined>;
86
+ currentNativeVideoBuffer$: IValueSubject<IRange<Seconds> | undefined>;
87
+ currentNativeAudioBuffer$: IValueSubject<IRange<Seconds> | undefined>;
86
88
  totalBufferDuration$: IValueSubject<Milliseconds | undefined>;
87
89
  bufferRangeCount$: IValueSubject<number | undefined>;
88
90
  videoLastDataObtainedTimestamp$: IValueSubject<Milliseconds | undefined>;
@@ -7,12 +7,14 @@ export declare class AbrManager {
7
7
  private audioAbrController;
8
8
  private subscription;
9
9
  private lastVideoTrackSelected$;
10
+ private lastAudioTrackSelected$;
10
11
  private context;
11
12
  private phaseController;
12
13
  private allVideoRules;
13
14
  private tracer;
14
15
  init(context: IInitAbrManagerContext): void;
15
16
  updateContext(updateContext: IUpdatableAbrManagerContext): void;
17
+ private getAudioReserve;
16
18
  autoSelectTrack<T extends IVideoTrack | IAudioTrack>(kind: Exclude<StreamKind, StreamKind.TEXT>): T;
17
19
  destroy(): void;
18
20
  private initVideoElementAbrContext;
@@ -0,0 +1,23 @@
1
+ import type { IComponentLogger, IRectangle, ITracer, Kbps, Milliseconds, Nullable, QualityLimits } from "@vkontakte/videoplayer-shared";
2
+ import type { IVideoTrack } from "../../../player/types";
3
+ import type { ITuningConfig } from "../../../utils/tuningConfig";
4
+ export interface ISelectTrackByRulesContext {
5
+ videoTracks: IVideoTrack[];
6
+ tuning: ITuningConfig;
7
+ abrLogger: IComponentLogger;
8
+ tracer: ITracer;
9
+ estimatedThroughput: Kbps;
10
+ container?: Nullable<IRectangle>;
11
+ panelSize?: Nullable<IRectangle>;
12
+ limits?: QualityLimits;
13
+ playbackRate?: number;
14
+ forwardBufferHealth?: number;
15
+ forwardBufferDuration?: Milliseconds;
16
+ visible?: boolean;
17
+ currentVideoTrack?: Nullable<IVideoTrack>;
18
+ reserve?: Kbps;
19
+ isLive?: boolean;
20
+ element?: HTMLMediaElement;
21
+ }
22
+ export declare const defaultEmptyArrayErrorMessage = "Assertion \"ABR Tracks is empty array\" failed";
23
+ export declare function selectTrackByRules(context: ISelectTrackByRulesContext): IVideoTrack;
@@ -1,5 +1,6 @@
1
- import type { Milliseconds, Nullable } from "@vkontakte/videoplayer-shared";
1
+ import type { Kbps, Milliseconds, Nullable } from "@vkontakte/videoplayer-shared";
2
2
  import type { IAudioTrack, IBaseTrack, IVideoTrack } from "../../../player/types";
3
+ import type { Representation, Segment } from "../parsers/types";
3
4
  export declare const bufferToPlaybackMs: (contentMs: Milliseconds | undefined, playbackRate: number) => Milliseconds;
4
5
  export declare enum CompareTrack {
5
6
  Descending = -1,
@@ -13,3 +14,5 @@ export declare const isLowerTrack: <T extends IBaseTrack>(track1: T, track2: T)
13
14
  export declare const logBase: (base: number, x: number) => number;
14
15
  export declare const bitrateFactorFromBufferLevel: (forwardBufferHealth: number, emptyFactor: number, fullFactor: number) => number;
15
16
  export declare const getMinPossibleAudioForVideo: (videoTrack: Nullable<IVideoTrack>, sortedVideoTracksAsc: IVideoTrack[], sortedAudioTracksAsc: IAudioTrack[], minVideoAudioRatio: number) => IAudioTrack | undefined;
17
+ export declare const getForwardBitrateKbps: (forwardBufferRepresentations: Nullable<Map<Representation["id"], Segment[]>>, videoTrack: Nullable<IVideoTrack>) => Kbps | undefined;
18
+ export declare const isVideoTail: (remainingDurationMs: Nullable<Milliseconds>, mpdSegmentDurationMs: Nullable<Milliseconds>) => boolean;
@@ -17,7 +17,7 @@ export interface IObservableVideo {
17
17
  loadedMetadata$: IObservable<undefined>;
18
18
  loadedData$: IObservable<undefined>;
19
19
  isBuffering$: IObservable<boolean>;
20
- currentBuffer$: IObservable<IRange<Seconds>>;
20
+ currentVideoBuffer$: IObservable<IRange<Seconds>>;
21
21
  totalBufferDuration$: IObservable<Milliseconds>;
22
22
  bufferRangeCount$: IObservable<number>;
23
23
  volumeState$: IObservable<IVolumeState>;
@@ -1,5 +1,5 @@
1
1
  import type { ITuningConfig } from "../../../utils/tuningConfig";
2
- type DisposeConstraints = Pick<ITuningConfig, "reuseOwnVideoElement">;
2
+ type DisposeConstraints = Pick<ITuningConfig, "reuseOwnVideoElement" | "clearAudioElementOnDispose">;
3
3
  export declare const allocate: (container: HTMLElement, { audioVideoSyncRate, disableYandexPiP, reuseOwnVideoElement }: ITuningConfig) => HTMLVideoElement;
4
4
  export declare const initializeAudio: (element: HTMLAudioElement) => HTMLAudioElement;
5
5
  export declare const dispose: (element: HTMLMediaElement, constraints: DisposeConstraints) => void;
@@ -14,6 +14,8 @@ declare class ThroughputEstimator {
14
14
  trackXHR(xhr: XMLHttpRequest): void;
15
15
  trackStream(stream: ReadableStream, isLowLatency?: boolean): void;
16
16
  addRawSpeed(size: Byte, time: Milliseconds, concurrency?: number, isLowLatency?: boolean): void;
17
+ private countActiveDownloads;
18
+ private isFastSample;
17
19
  /**
18
20
  * Стоит использовать только когда другие методы совсем не получается
19
21
  */
@@ -0,0 +1,3 @@
1
+ import type { IRange, Milliseconds } from "@vkontakte/videoplayer-shared";
2
+ declare const _default: (buffered: IRange<Milliseconds>[], segment: IRange<Milliseconds>, tolerance: Milliseconds) => boolean;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { IRange, Milliseconds } from "@vkontakte/videoplayer-shared";
2
+ declare const _default: (timeRanges: TimeRanges) => IRange<Milliseconds>[];
3
+ export default _default;
@@ -56,8 +56,19 @@ export type ITuningConfig = {
56
56
  * - fromCache — попадание в Cache API (doFetch дёргает onCacheHit);
57
57
  * - TTFB — headersReceivedAt - requestStartedAt < max(rtt*0.5, 2мс) (кэш ~0, реал ≥ RTT).
58
58
  * 2. sanityCheck отключает порог time ≤ cacheThresholdSize → реальные быстрые сэмплы проходят.
59
+ * 3. Прошедший быстрый сэмпл применяется только если поднимает оценку: по объекту, который
60
+ * укладывается в одно окно, наблюдаемое время — латентность, а не size/полоса, поэтому
61
+ * он задаёт нижнюю границу и не может доказать, что сеть стала медленнее.
62
+ * 4. Финальный замер стрима делит полосу на параллельные загрузки, как промежуточные:
63
+ * мелкий сегмент качается параллельно с аудио и другого замера не получает.
64
+ * Параллельной считается загрузка, отдававшая байты внутри окна замера: открытая,
65
+ * но молчащая (подвисла либо уже выкачала своё и ждёт done) полосу не занимает.
59
66
  * Честный кэш (мгновенная отдача → rate > 1 Гбит/с) по-прежнему режется проверкой rate выше.
60
67
  *
68
+ * Пункты 3 и 4 добавлены после эксперимента 37621: без них включённые быстрые сэмплы
69
+ * систематически занижали оценку, ABR держал низкое качество и сегменты оставались
70
+ * мелкими — петля с положительной обратной связью, вердикт NO-GO.
71
+ *
61
72
  * По умолчанию false — поведение не меняется.
62
73
  */
63
74
  measureFastSamples: boolean;
@@ -179,7 +190,8 @@ export type ITuningConfig = {
179
190
  useNewRepresentationSwitch: boolean;
180
191
  useDelayedRepresentationSwitch: boolean;
181
192
  useSmartRepresentationSwitch: boolean;
182
- stallForceSeekOncePerStall: boolean;
193
+ brokenSegmentAppendDetection: boolean;
194
+ brokenSegmentAppendTolerance: Milliseconds;
183
195
  useFetchPriorityHints: boolean;
184
196
  enableBaseUrlSupport: boolean;
185
197
  maxSegmentRetryCount: number;
@@ -200,11 +212,9 @@ export type ITuningConfig = {
200
212
  tickMaintainInterval: Milliseconds;
201
213
  minSafeBufferToPlay: Milliseconds;
202
214
  useBufferHoldingOnlyOnStall: boolean;
203
- useNewAbr: boolean;
204
215
  useAbrPhases: boolean;
205
216
  abrVideoRules: VideoRuleName[];
206
217
  abrAudioRules: AudioRuleName[];
207
- useDynamicBirtateRule: boolean;
208
218
  useFailoverHostsOnAllProviderCrash: boolean;
209
219
  saveData3gQualityLimit: ExactVideoQuality;
210
220
  saveData2gQualityLimit: ExactVideoQuality;
@@ -241,6 +251,20 @@ export type ITuningConfig = {
241
251
  maxQualityForFirstSegmentPreload: ExactVideoQuality;
242
252
  /** Включает отправку телеметрии трейсера (resume) при превышении stall watchdog */
243
253
  tracerResumeOnUnexpectedStall: boolean;
254
+ /**
255
+ * При отмене signal текущей задачи sourceBufferTaskQueue (например, через
256
+ * `maintainAbortController.abort()` в `prepareSeek`) прерывать зависшую MSE-операцию
257
+ * через `buffer.abort()`. Без этого `completeTask` не вызовется при залипшем
258
+ * SourceBuffer и промис `append`/`remove` зависнет навечно — `prepareSeek`
259
+ * застрянет на `await maintainMutexPromise` (V3 deadlock), stall растёт до
260
+ * `crashOnStallTimeout=25с`.
261
+ *
262
+ * По умолчанию false (opt-in). Дешёвый фикс, но поведенческое изменение:
263
+ * единственный побочный эффект — лишний `buffer.abort()` при штатной отмене
264
+ * maintain (например, при обычном seek), но MSE `abort()` без активной операции
265
+ * — no-op по спеке. Включать поэтапно, начиная с процента.
266
+ */
267
+ abortSourceBufferOnSignal: boolean;
244
268
  };
245
269
  dashCmafLive: {
246
270
  externalStopControl: boolean;
@@ -338,7 +362,8 @@ export type ITuningConfig = {
338
362
  alwaysAbortPreviousSwitch: boolean;
339
363
  useDashProviderVirtual: boolean;
340
364
  useDashProviderVirtualMobile: boolean;
341
- useNewAutoSelectVideoTrack: boolean;
365
+ useDashLiveProviderVirtual: boolean;
366
+ useDashLiveProviderVirtualMobile: boolean;
342
367
  useSafariEndlessRequestBugfix: boolean;
343
368
  /**
344
369
  * Ручка для фикса сброса playbackRate при перемотке live-трансляции на Safari.
@@ -438,6 +463,11 @@ export type ITuningConfig = {
438
463
  /** включен режим проигрывания только аудио (без видео) */
439
464
  audioOnly: boolean;
440
465
  /**
466
+ * В audio-режиме при dispose провайдера очищает внешний <audio> (снятие src + load())
467
+ * вместо destroy(), который удаляет элемент из DOM.
468
+ */
469
+ clearAudioElementOnDispose: boolean;
470
+ /**
441
471
  * Переводить провайдер в READY по loadedmetadata вместо canplay.
442
472
  * canplay означает, что видео уже может играться, что избыточно для READY —
443
473
  * достаточно получить манифест (loadedmetadata).
@@ -1,36 +0,0 @@
1
- import type { ITuningConfig } from "./tuningConfig";
2
- import type { Kbps, Milliseconds, IRectangle, QualityLimits, IComponentLogger } from "@vkontakte/videoplayer-shared";
3
- import { type ExactVideoQuality } from "@vkontakte/videoplayer-shared";
4
- import type { IAudioTrack, IBaseTrack, IVideoTrack } from "../player/types";
5
- interface IConstraints<T extends IBaseTrack> {
6
- container?: IRectangle;
7
- estimatedThroughput?: Kbps;
8
- tuning: ITuningConfig["autoTrackSelection"];
9
- limits?: QualityLimits;
10
- reserve?: Kbps;
11
- playbackRate?: number;
12
- forwardBufferHealth?: number;
13
- current?: T;
14
- visible?: boolean;
15
- history?: TrackHistory<T>;
16
- droppedVideoMaxQualityLimit?: ExactVideoQuality;
17
- stallsVideoMaxQualityLimit?: ExactVideoQuality;
18
- stallsPredictedThroughput?: Kbps;
19
- abrLogger: IComponentLogger;
20
- panelSize?: IRectangle;
21
- }
22
- export declare class TrackHistory<T extends IBaseTrack> {
23
- last: T | undefined;
24
- history: Record<IBaseTrack["id"], Milliseconds>;
25
- recordSelection(track: T): void;
26
- recordSwitch(track: T | undefined): void;
27
- clear(): void;
28
- }
29
- export declare const defaultEmptyArrayErrorMessage = "Assertion \"ABR Tracks is empty array\" failed";
30
- export declare const getMinPossibleAudioForVideoOld: (videoTrack: IVideoTrack, videoTracks: IVideoTrack[], audioTracks: IAudioTrack[], minVideoAudioRatio: number) => IAudioTrack | undefined;
31
- export declare const getMinPossibleAudioForVideoNew: (videoTrack: IVideoTrack, videoTracks: IVideoTrack[], audioTracks: IAudioTrack[], minVideoAudioRatio: number) => IAudioTrack | undefined;
32
- export declare const autoSelectVideoTrackNew: (videoTracks: IVideoTrack[], { container, estimatedThroughput, tuning, limits, reserve, forwardBufferHealth, playbackRate, current, history, visible, droppedVideoMaxQualityLimit, stallsVideoMaxQualityLimit, stallsPredictedThroughput, abrLogger, panelSize }: IConstraints<IVideoTrack>) => IVideoTrack;
33
- export declare const autoSelectVideoTrackOld: (videoTracks: IVideoTrack[], { container, estimatedThroughput, tuning, limits, reserve, forwardBufferHealth, playbackRate, current, history, visible, droppedVideoMaxQualityLimit, stallsVideoMaxQualityLimit, stallsPredictedThroughput, abrLogger, panelSize }: IConstraints<IVideoTrack>) => IVideoTrack;
34
- export declare const autoSelectAudioTrackForVideoOld: (selectedVideoTrack: IVideoTrack, videoTracks: IVideoTrack[], audioTracks: IAudioTrack[], { estimatedThroughput, tuning, playbackRate, forwardBufferHealth, history, abrLogger, stallsPredictedThroughput }: IConstraints<IAudioTrack>) => IAudioTrack | undefined;
35
- export declare const autoSelectAudioTrackForVideoNew: (selectedVideoTrack: IVideoTrack, videoTracks: IVideoTrack[], audioTracks: IAudioTrack[], { estimatedThroughput, tuning, playbackRate, forwardBufferHealth, history, abrLogger, stallsPredictedThroughput }: IConstraints<IAudioTrack>) => IAudioTrack | undefined;
36
- export {};