googlevideo 2.0.0 → 4.0.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 (186) hide show
  1. package/LICENSE +9 -9
  2. package/README.md +127 -66
  3. package/dist/protos/generated/misc/common.d.ts +180 -21
  4. package/dist/protos/generated/misc/common.js +277 -147
  5. package/dist/protos/generated/misc/common.js.map +1 -0
  6. package/dist/protos/generated/video_streaming/buffered_range.d.ts +10 -25
  7. package/dist/protos/generated/video_streaming/buffered_range.js +21 -166
  8. package/dist/protos/generated/video_streaming/buffered_range.js.map +1 -0
  9. package/dist/protos/generated/video_streaming/client_abr_state.d.ts +34 -45
  10. package/dist/protos/generated/video_streaming/client_abr_state.js +209 -350
  11. package/dist/protos/generated/video_streaming/client_abr_state.js.map +1 -0
  12. package/dist/protos/generated/video_streaming/crypto_params.d.ts +2 -24
  13. package/dist/protos/generated/video_streaming/crypto_params.js +2 -86
  14. package/dist/protos/generated/video_streaming/crypto_params.js.map +1 -0
  15. package/dist/protos/generated/video_streaming/format_initialization_metadata.d.ts +6 -21
  16. package/dist/protos/generated/video_streaming/format_initialization_metadata.js +32 -95
  17. package/dist/protos/generated/video_streaming/format_initialization_metadata.js.map +1 -0
  18. package/dist/protos/generated/video_streaming/format_selection_config.d.ts +12 -0
  19. package/dist/protos/generated/video_streaming/format_selection_config.js +68 -0
  20. package/dist/protos/generated/video_streaming/format_selection_config.js.map +1 -0
  21. package/dist/protos/generated/video_streaming/innertube_request.d.ts +25 -0
  22. package/dist/protos/generated/video_streaming/innertube_request.js +186 -0
  23. package/dist/protos/generated/video_streaming/innertube_request.js.map +1 -0
  24. package/dist/protos/generated/video_streaming/live_metadata.d.ts +20 -0
  25. package/dist/protos/generated/video_streaming/live_metadata.js +153 -0
  26. package/dist/protos/generated/video_streaming/live_metadata.js.map +1 -0
  27. package/dist/protos/generated/video_streaming/media_capabilities.d.ts +0 -15
  28. package/dist/protos/generated/video_streaming/media_capabilities.js +2 -122
  29. package/dist/protos/generated/video_streaming/media_capabilities.js.map +1 -0
  30. package/dist/protos/generated/video_streaming/media_header.d.ts +5 -27
  31. package/dist/protos/generated/video_streaming/media_header.js +28 -151
  32. package/dist/protos/generated/video_streaming/media_header.js.map +1 -0
  33. package/dist/protos/generated/video_streaming/next_request_policy.d.ts +3 -15
  34. package/dist/protos/generated/video_streaming/next_request_policy.js +32 -50
  35. package/dist/protos/generated/video_streaming/next_request_policy.js.map +1 -0
  36. package/dist/protos/generated/video_streaming/onesie_header.d.ts +7 -22
  37. package/dist/protos/generated/video_streaming/onesie_header.js +16 -137
  38. package/dist/protos/generated/video_streaming/onesie_header.js.map +1 -0
  39. package/dist/protos/generated/video_streaming/onesie_header_type.d.ts +9 -25
  40. package/dist/protos/generated/video_streaming/onesie_header_type.js +17 -176
  41. package/dist/protos/generated/video_streaming/onesie_header_type.js.map +1 -0
  42. package/dist/protos/generated/video_streaming/onesie_innertube_request.d.ts +15 -0
  43. package/dist/protos/generated/video_streaming/{onesie_player_request.js → onesie_innertube_request.js} +10 -54
  44. package/dist/protos/generated/video_streaming/onesie_innertube_request.js.map +1 -0
  45. package/dist/protos/generated/video_streaming/onesie_innertube_response.d.ts +15 -0
  46. package/dist/protos/generated/video_streaming/{onesie_player_response.js → onesie_innertube_response.js} +6 -58
  47. package/dist/protos/generated/video_streaming/onesie_innertube_response.js.map +1 -0
  48. package/dist/protos/generated/video_streaming/onesie_proxy_status.d.ts +18 -0
  49. package/dist/protos/generated/video_streaming/onesie_proxy_status.js +25 -0
  50. package/dist/protos/generated/video_streaming/onesie_proxy_status.js.map +1 -0
  51. package/dist/protos/generated/video_streaming/onesie_request.d.ts +7 -17
  52. package/dist/protos/generated/video_streaming/onesie_request.js +28 -89
  53. package/dist/protos/generated/video_streaming/onesie_request.js.map +1 -0
  54. package/dist/protos/generated/video_streaming/playback_cookie.d.ts +2 -17
  55. package/dist/protos/generated/video_streaming/playback_cookie.js +6 -47
  56. package/dist/protos/generated/video_streaming/playback_cookie.js.map +1 -0
  57. package/dist/protos/generated/video_streaming/playback_start_policy.d.ts +0 -15
  58. package/dist/protos/generated/video_streaming/playback_start_policy.js +2 -66
  59. package/dist/protos/generated/video_streaming/playback_start_policy.js.map +1 -0
  60. package/dist/protos/generated/video_streaming/reload_player_response.d.ts +14 -0
  61. package/dist/protos/generated/video_streaming/reload_player_response.js +73 -0
  62. package/dist/protos/generated/video_streaming/reload_player_response.js.map +1 -0
  63. package/dist/protos/generated/video_streaming/request_cancellation_policy.d.ts +0 -15
  64. package/dist/protos/generated/video_streaming/request_cancellation_policy.js +2 -66
  65. package/dist/protos/generated/video_streaming/request_cancellation_policy.js.map +1 -0
  66. package/dist/protos/generated/video_streaming/request_identifier.d.ts +10 -0
  67. package/dist/protos/generated/video_streaming/request_identifier.js +41 -0
  68. package/dist/protos/generated/video_streaming/request_identifier.js.map +1 -0
  69. package/dist/protos/generated/video_streaming/sabr_context_sending_policy.d.ts +12 -0
  70. package/dist/protos/generated/video_streaming/sabr_context_sending_policy.js +86 -0
  71. package/dist/protos/generated/video_streaming/sabr_context_sending_policy.js.map +1 -0
  72. package/dist/protos/generated/video_streaming/sabr_context_update.d.ts +48 -0
  73. package/dist/protos/generated/video_streaming/sabr_context_update.js +242 -0
  74. package/dist/protos/generated/video_streaming/sabr_context_update.js.map +1 -0
  75. package/dist/protos/generated/video_streaming/sabr_error.d.ts +0 -15
  76. package/dist/protos/generated/video_streaming/sabr_error.js +2 -29
  77. package/dist/protos/generated/video_streaming/sabr_error.js.map +1 -0
  78. package/dist/protos/generated/video_streaming/sabr_redirect.d.ts +0 -15
  79. package/dist/protos/generated/video_streaming/sabr_redirect.js +2 -22
  80. package/dist/protos/generated/video_streaming/sabr_redirect.js.map +1 -0
  81. package/dist/protos/generated/video_streaming/snackbar_message.d.ts +10 -0
  82. package/dist/protos/generated/video_streaming/snackbar_message.js +41 -0
  83. package/dist/protos/generated/video_streaming/snackbar_message.js.map +1 -0
  84. package/dist/protos/generated/video_streaming/stream_protection_status.d.ts +1 -16
  85. package/dist/protos/generated/video_streaming/stream_protection_status.js +6 -33
  86. package/dist/protos/generated/video_streaming/stream_protection_status.js.map +1 -0
  87. package/dist/protos/generated/video_streaming/streamer_context.d.ts +11 -28
  88. package/dist/protos/generated/video_streaming/streamer_context.js +33 -383
  89. package/dist/protos/generated/video_streaming/streamer_context.js.map +1 -0
  90. package/dist/protos/generated/video_streaming/time_range.d.ts +2 -17
  91. package/dist/protos/generated/video_streaming/time_range.js +9 -41
  92. package/dist/protos/generated/video_streaming/time_range.js.map +1 -0
  93. package/dist/protos/generated/video_streaming/ump_part_id.d.ts +58 -0
  94. package/dist/protos/generated/video_streaming/ump_part_id.js +89 -0
  95. package/dist/protos/generated/video_streaming/ump_part_id.js.map +1 -0
  96. package/dist/protos/generated/video_streaming/video_playback_abr_request.d.ts +21 -36
  97. package/dist/protos/generated/video_streaming/video_playback_abr_request.js +67 -343
  98. package/dist/protos/generated/video_streaming/video_playback_abr_request.js.map +1 -0
  99. package/dist/src/core/{ChunkedDataBuffer.d.ts → CompositeBuffer.d.ts} +8 -8
  100. package/dist/src/core/{ChunkedDataBuffer.js → CompositeBuffer.js} +32 -27
  101. package/dist/src/core/CompositeBuffer.js.map +1 -0
  102. package/dist/src/core/SabrStream.d.ts +356 -0
  103. package/dist/src/core/SabrStream.js +958 -0
  104. package/dist/src/core/SabrStream.js.map +1 -0
  105. package/dist/src/core/SabrStreamingAdapter.d.ts +158 -0
  106. package/dist/src/core/SabrStreamingAdapter.js +496 -0
  107. package/dist/src/core/SabrStreamingAdapter.js.map +1 -0
  108. package/dist/src/core/SabrUmpProcessor.d.ts +53 -0
  109. package/dist/src/core/SabrUmpProcessor.js +234 -0
  110. package/dist/src/core/SabrUmpProcessor.js.map +1 -0
  111. package/dist/src/core/UmpReader.d.ts +30 -0
  112. package/dist/src/core/UmpReader.js +122 -0
  113. package/dist/src/core/UmpReader.js.map +1 -0
  114. package/dist/src/core/UmpWriter.d.ts +16 -0
  115. package/dist/src/core/UmpWriter.js +56 -0
  116. package/dist/src/core/UmpWriter.js.map +1 -0
  117. package/dist/src/exports/protos.d.ts +1 -0
  118. package/dist/src/exports/protos.js +2 -0
  119. package/dist/src/exports/protos.js.map +1 -0
  120. package/dist/src/exports/sabr-stream.d.ts +2 -0
  121. package/dist/src/exports/sabr-stream.js +2 -0
  122. package/dist/src/exports/sabr-stream.js.map +1 -0
  123. package/dist/src/exports/sabr-streaming-adapter.d.ts +3 -0
  124. package/dist/src/exports/sabr-streaming-adapter.js +3 -0
  125. package/dist/src/exports/sabr-streaming-adapter.js.map +1 -0
  126. package/dist/src/exports/ump.d.ts +3 -0
  127. package/dist/src/exports/ump.js +4 -0
  128. package/dist/src/exports/ump.js.map +1 -0
  129. package/dist/src/exports/utils.d.ts +1 -0
  130. package/dist/src/exports/utils.js +2 -0
  131. package/dist/src/exports/utils.js.map +1 -0
  132. package/dist/src/types/sabrStreamTypes.d.ts +102 -0
  133. package/dist/src/types/sabrStreamTypes.js +2 -0
  134. package/dist/src/types/sabrStreamTypes.js.map +1 -0
  135. package/dist/src/types/sabrStreamingAdapterTypes.d.ts +93 -0
  136. package/dist/src/types/sabrStreamingAdapterTypes.js +2 -0
  137. package/dist/src/types/sabrStreamingAdapterTypes.js.map +1 -0
  138. package/dist/src/types/shared.d.ts +64 -0
  139. package/dist/src/types/shared.js +2 -0
  140. package/dist/src/types/shared.js.map +1 -0
  141. package/dist/src/utils/CacheManager.d.ts +32 -0
  142. package/dist/src/utils/CacheManager.js +131 -0
  143. package/dist/src/utils/CacheManager.js.map +1 -0
  144. package/dist/src/utils/EventEmitterLike.d.ts +5 -0
  145. package/dist/src/utils/EventEmitterLike.js +51 -10
  146. package/dist/src/utils/EventEmitterLike.js.map +1 -0
  147. package/dist/src/utils/Logger.d.ts +30 -0
  148. package/dist/src/utils/Logger.js +80 -0
  149. package/dist/src/utils/Logger.js.map +1 -0
  150. package/dist/src/utils/Protos.d.ts +21 -13
  151. package/dist/src/utils/Protos.js +22 -13
  152. package/dist/src/utils/Protos.js.map +1 -0
  153. package/dist/src/utils/RequestMetadataManager.d.ts +15 -0
  154. package/dist/src/utils/RequestMetadataManager.js +48 -0
  155. package/dist/src/utils/RequestMetadataManager.js.map +1 -0
  156. package/dist/src/utils/formatKeyUtils.d.ts +45 -0
  157. package/dist/src/utils/formatKeyUtils.js +77 -0
  158. package/dist/src/utils/formatKeyUtils.js.map +1 -0
  159. package/dist/src/utils/index.d.ts +5 -3
  160. package/dist/src/utils/index.js +6 -2
  161. package/dist/src/utils/index.js.map +1 -0
  162. package/dist/src/utils/sabrStreamUtils.d.ts +28 -0
  163. package/dist/src/utils/sabrStreamUtils.js +76 -0
  164. package/dist/src/utils/sabrStreamUtils.js.map +1 -0
  165. package/dist/src/utils/shared.d.ts +43 -0
  166. package/dist/src/utils/shared.js +108 -0
  167. package/dist/src/utils/shared.js.map +1 -0
  168. package/package.json +88 -61
  169. package/dist/protos/generated/video_streaming/encrypted_player_request.d.ts +0 -37
  170. package/dist/protos/generated/video_streaming/encrypted_player_request.js +0 -239
  171. package/dist/protos/generated/video_streaming/onesie_player_request.d.ts +0 -31
  172. package/dist/protos/generated/video_streaming/onesie_player_response.d.ts +0 -29
  173. package/dist/protos/generated/video_streaming/proxy_status.d.ts +0 -16
  174. package/dist/protos/generated/video_streaming/proxy_status.js +0 -86
  175. package/dist/src/core/ServerAbrStream.d.ts +0 -38
  176. package/dist/src/core/ServerAbrStream.js +0 -272
  177. package/dist/src/core/UMP.d.ts +0 -10
  178. package/dist/src/core/UMP.js +0 -109
  179. package/dist/src/core/index.d.ts +0 -3
  180. package/dist/src/core/index.js +0 -3
  181. package/dist/src/index.d.ts +0 -4
  182. package/dist/src/index.js +0 -4
  183. package/dist/src/utils/helpers.d.ts +0 -63
  184. package/dist/src/utils/helpers.js +0 -101
  185. package/dist/src/utils/types.d.ts +0 -65
  186. package/dist/src/utils/types.js +0 -1
@@ -1,272 +0,0 @@
1
- import { UMP } from './UMP.js';
2
- import { ChunkedDataBuffer } from './ChunkedDataBuffer.js';
3
- import { EventEmitterLike, PART, QUALITY, base64ToU8, getFormatKey } from '../utils/index.js';
4
- import { ClientAbrState_MediaType } from '../../protos/generated/video_streaming/client_abr_state.js';
5
- import { VideoPlaybackAbrRequest } from '../../protos/generated/video_streaming/video_playback_abr_request.js';
6
- import { MediaHeader } from '../../protos/generated/video_streaming/media_header.js';
7
- import { NextRequestPolicy } from '../../protos/generated/video_streaming/next_request_policy.js';
8
- import { FormatInitializationMetadata } from '../../protos/generated/video_streaming/format_initialization_metadata.js';
9
- import { SabrRedirect } from '../../protos/generated/video_streaming/sabr_redirect.js';
10
- import { SabrError } from '../../protos/generated/video_streaming/sabr_error.js';
11
- import { StreamProtectionStatus } from '../../protos/generated/video_streaming/stream_protection_status.js';
12
- import { PlaybackCookie } from '../../protos/generated/video_streaming/playback_cookie.js';
13
- const DEFAULT_QUALITY = QUALITY.HD720;
14
- export class ServerAbrStream extends EventEmitterLike {
15
- constructor(args) {
16
- super();
17
- this.initializedFormats = [];
18
- this.formatsByKey = new Map();
19
- this.headerIdToFormatKeyMap = new Map();
20
- this.previousSequences = new Map();
21
- this.fetchFunction = args.fetch || fetch;
22
- this.serverAbrStreamingUrl = args.serverAbrStreamingUrl;
23
- this.videoPlaybackUstreamerConfig = args.videoPlaybackUstreamerConfig;
24
- this.poToken = args.poToken;
25
- this.totalDurationMs = args.durationMs;
26
- }
27
- on(event, listener) {
28
- super.on(event, listener);
29
- }
30
- once(event, listener) {
31
- super.once(event, listener);
32
- }
33
- /**
34
- * Initializes the server ABR stream with the provided options.
35
- * @param args - The initialization options.
36
- */
37
- async init(args) {
38
- const { audioFormats, videoFormats, clientAbrState: initialState } = args;
39
- const firstVideoFormat = videoFormats ? videoFormats[0] : undefined;
40
- const clientAbrState = {
41
- lastManualDirection: 0,
42
- timeSinceLastManualFormatSelectionMs: 0,
43
- quality: videoFormats.length === 1 ? firstVideoFormat?.width : DEFAULT_QUALITY,
44
- selectedQualityHeight: videoFormats.length === 1 ? firstVideoFormat?.width : DEFAULT_QUALITY,
45
- startTimeMs: 0,
46
- visibility: 0,
47
- mediaType: ClientAbrState_MediaType.MEDIA_TYPE_DEFAULT,
48
- ...initialState
49
- };
50
- const audioFormatIds = audioFormats.map((fmt) => ({
51
- itag: fmt.itag,
52
- lastModified: parseInt(fmt.lastModified),
53
- xtags: fmt.xtags
54
- }));
55
- const videoFormatIds = videoFormats.map((fmt) => ({
56
- itag: fmt.itag,
57
- lastModified: parseInt(fmt.lastModified),
58
- xtags: fmt.xtags
59
- }));
60
- if (typeof clientAbrState.startTimeMs !== 'number')
61
- throw new Error('Invalid media start time');
62
- try {
63
- while (clientAbrState.startTimeMs < this.totalDurationMs) {
64
- const data = await this.fetchMedia({ clientAbrState, audioFormatIds, videoFormatIds });
65
- this.emit('data', data);
66
- if (data.sabrError)
67
- break;
68
- const mainFormat = clientAbrState.mediaType === ClientAbrState_MediaType.MEDIA_TYPE_DEFAULT
69
- ? data.initializedFormats.find((fmt) => fmt.mimeType?.includes('video'))
70
- : data.initializedFormats[0];
71
- for (const fmt of data.initializedFormats) {
72
- this.previousSequences.set(fmt.formatKey, fmt.sequenceList.map((seq) => seq.sequenceNumber || 0));
73
- }
74
- if (!mainFormat ||
75
- mainFormat.sequenceCount ===
76
- mainFormat.sequenceList[mainFormat.sequenceList.length - 1]?.sequenceNumber) {
77
- this.emit('end', data);
78
- break;
79
- }
80
- clientAbrState.startTimeMs += mainFormat.sequenceList.reduce((acc, seq) => acc + (seq.durationMs || 0), 0);
81
- }
82
- }
83
- catch (error) {
84
- this.emit('error', error);
85
- }
86
- }
87
- async fetchMedia(args) {
88
- const { clientAbrState, audioFormatIds, videoFormatIds } = args;
89
- const body = VideoPlaybackAbrRequest.encode({
90
- clientAbrState: clientAbrState,
91
- selectedAudioFormatIds: audioFormatIds,
92
- selectedVideoFormatIds: videoFormatIds,
93
- selectedFormatIds: this.initializedFormats.map((fmt) => fmt.formatId),
94
- videoPlaybackUstreamerConfig: base64ToU8(this.videoPlaybackUstreamerConfig),
95
- streamerContext: {
96
- field5: [],
97
- field6: [],
98
- poToken: this.poToken ? base64ToU8(this.poToken) : undefined,
99
- playbackCookie: this.playbackCookie ? PlaybackCookie.encode(this.playbackCookie).finish() : undefined,
100
- clientInfo: {
101
- clientName: 1,
102
- clientVersion: '2.2040620.05.00',
103
- osName: 'Windows',
104
- osVersion: '10.0'
105
- }
106
- },
107
- bufferedRanges: this.initializedFormats.map((fmt) => fmt._state),
108
- field1000: []
109
- }).finish();
110
- const response = await this.fetchFunction(this.serverAbrStreamingUrl, { method: 'POST', body });
111
- const data = await response.arrayBuffer();
112
- if (response.status !== 200 || !data.byteLength)
113
- throw new Error(`Received an invalid response from the server: ${response.status}`);
114
- return this.parseUMPResponse(new Uint8Array(data));
115
- }
116
- /**
117
- * Parses the UMP response data and updates the initialized formats.
118
- * @param response - The UMP response data as a byte array.
119
- */
120
- async parseUMPResponse(response) {
121
- this.headerIdToFormatKeyMap.clear();
122
- this.initializedFormats.forEach((format) => {
123
- format.sequenceList = [];
124
- format.mediaChunks = [];
125
- });
126
- let sabrError;
127
- let sabrRedirect;
128
- let streamProtectionStatus;
129
- const ump = new UMP(new ChunkedDataBuffer([response]));
130
- ump.parse((part) => {
131
- const data = part.data.chunks[0];
132
- switch (part.type) {
133
- case PART.MEDIA_HEADER:
134
- this.processMediaHeader(data);
135
- break;
136
- case PART.MEDIA:
137
- this.processMediaData(part.data);
138
- break;
139
- case PART.MEDIA_END:
140
- this.processEndOfMedia(part.data);
141
- break;
142
- case PART.NEXT_REQUEST_POLICY:
143
- this.processNextRequestPolicy(data);
144
- break;
145
- case PART.FORMAT_INITIALIZATION_METADATA:
146
- this.processFormatInitialization(data);
147
- break;
148
- case PART.SABR_ERROR:
149
- sabrError = SabrError.decode(data);
150
- break;
151
- case PART.SABR_REDIRECT:
152
- sabrRedirect = this.processSabrRedirect(data);
153
- break;
154
- case PART.STREAM_PROTECTION_STATUS:
155
- streamProtectionStatus = StreamProtectionStatus.decode(data);
156
- break;
157
- default:
158
- break;
159
- }
160
- });
161
- return {
162
- initializedFormats: this.initializedFormats,
163
- streamProtectionStatus,
164
- sabrRedirect,
165
- sabrError
166
- };
167
- }
168
- processMediaHeader(data) {
169
- const mediaHeader = MediaHeader.decode(data);
170
- if (!mediaHeader.formatId)
171
- return;
172
- const formatKey = getFormatKey(mediaHeader.formatId);
173
- let currentFormat = this.formatsByKey.get(formatKey);
174
- if (!currentFormat) {
175
- this.initializedFormats.push({
176
- formatId: mediaHeader.formatId,
177
- formatKey,
178
- durationMs: mediaHeader.durationMs,
179
- mimeType: undefined,
180
- sequenceCount: undefined,
181
- sequenceList: [],
182
- mediaChunks: [],
183
- _state: {
184
- formatId: mediaHeader.formatId,
185
- startTimeMs: 0,
186
- durationMs: 0,
187
- startSegmentIndex: 1,
188
- endSegmentIndex: 0
189
- }
190
- });
191
- this.formatsByKey.set(formatKey, this.initializedFormats[this.initializedFormats.length - 1]);
192
- currentFormat = this.formatsByKey.get(formatKey);
193
- }
194
- // FIXME: This is a hacky workaround to prevent duplicate sequences from being added. This should be fixed in the future (preferably by figuring out how to make the server not send duplicates).
195
- if (mediaHeader.sequenceNumber !== undefined && this.previousSequences.get(formatKey)?.includes(mediaHeader.sequenceNumber))
196
- return;
197
- // Save the header's ID so we can identify its stream data later.
198
- if (mediaHeader.headerId !== undefined) {
199
- if (!this.headerIdToFormatKeyMap.has(mediaHeader.headerId)) {
200
- this.headerIdToFormatKeyMap.set(mediaHeader.headerId, formatKey);
201
- }
202
- }
203
- if (!currentFormat.sequenceList.some((seq) => seq.sequenceNumber === (mediaHeader.sequenceNumber || 0))) {
204
- currentFormat.sequenceList.push({
205
- itag: mediaHeader.itag,
206
- formatId: mediaHeader.formatId,
207
- isInitSegment: mediaHeader.isInitSeg,
208
- durationMs: mediaHeader.durationMs,
209
- startMs: mediaHeader.startMs,
210
- startDataRange: mediaHeader.startDataRange,
211
- sequenceNumber: mediaHeader.sequenceNumber,
212
- contentLength: mediaHeader.contentLength,
213
- timeRange: mediaHeader.timeRange
214
- });
215
- if (typeof mediaHeader.sequenceNumber === 'number') {
216
- currentFormat._state.durationMs += mediaHeader.durationMs || 0;
217
- currentFormat._state.endSegmentIndex += 1;
218
- }
219
- }
220
- }
221
- processMediaData(data) {
222
- const headerId = data.getUint8(0);
223
- const streamData = data.split(1).remainingBuffer;
224
- const formatKey = this.headerIdToFormatKeyMap.get(headerId);
225
- if (!formatKey)
226
- return;
227
- const currentFormat = this.formatsByKey.get(formatKey);
228
- if (!currentFormat)
229
- return;
230
- currentFormat.mediaChunks.push(streamData.chunks[0]);
231
- }
232
- processEndOfMedia(data) {
233
- const headerId = data.getUint8(0);
234
- this.headerIdToFormatKeyMap.delete(headerId);
235
- }
236
- processNextRequestPolicy(data) {
237
- const nextRequestPolicy = NextRequestPolicy.decode(data);
238
- this.playbackCookie = nextRequestPolicy.playbackCookie;
239
- }
240
- processFormatInitialization(data) {
241
- const formatInitializationMetadata = FormatInitializationMetadata.decode(data);
242
- if (!formatInitializationMetadata.formatId)
243
- return;
244
- const formatKey = getFormatKey(formatInitializationMetadata.formatId);
245
- if (!this.formatsByKey.has(formatKey)) {
246
- this.initializedFormats.push({
247
- formatId: formatInitializationMetadata.formatId,
248
- formatKey: getFormatKey(formatInitializationMetadata.formatId),
249
- durationMs: formatInitializationMetadata.durationMs,
250
- mimeType: formatInitializationMetadata.mimeType,
251
- sequenceCount: formatInitializationMetadata.field4,
252
- sequenceList: [],
253
- mediaChunks: [],
254
- _state: {
255
- formatId: formatInitializationMetadata.formatId,
256
- startTimeMs: 0,
257
- durationMs: 0,
258
- startSegmentIndex: 1,
259
- endSegmentIndex: 0
260
- }
261
- });
262
- this.formatsByKey.set(formatKey, this.initializedFormats[this.initializedFormats.length - 1]);
263
- }
264
- }
265
- processSabrRedirect(data) {
266
- const sabrRedirect = SabrRedirect.decode(data);
267
- if (!sabrRedirect.url)
268
- throw new Error('Invalid SABR redirect');
269
- this.serverAbrStreamingUrl = sabrRedirect.url;
270
- return sabrRedirect;
271
- }
272
- }
@@ -1,10 +0,0 @@
1
- import type { Part } from '../index.js';
2
- import type { ChunkedDataBuffer } from './ChunkedDataBuffer.js';
3
- export declare class UMP {
4
- private chunkedDataBuffer;
5
- constructor(chunkedDataBuffer: ChunkedDataBuffer);
6
- parse(handlePart: (part: Part) => void): void;
7
- readVarInt(offset: number): [number, number];
8
- canReadFromCurrentChunk(offset: number, length: number): boolean;
9
- getCurrentDataView(): DataView;
10
- }
@@ -1,109 +0,0 @@
1
- export class UMP {
2
- constructor(chunkedDataBuffer) {
3
- this.chunkedDataBuffer = chunkedDataBuffer;
4
- }
5
- parse(handlePart) {
6
- while (true) {
7
- let offset = 0;
8
- const [partType, newOffset] = this.readVarInt(offset);
9
- offset = newOffset;
10
- const [partSize, finalOffset] = this.readVarInt(offset);
11
- offset = finalOffset;
12
- if (partType < 0 || partSize < 0)
13
- break;
14
- // Note that we don't handle cases like this YET..
15
- if (!this.chunkedDataBuffer.canReadBytes(offset, partSize))
16
- break;
17
- const splitResult = this.chunkedDataBuffer.split(offset).remainingBuffer.split(partSize);
18
- offset = 0;
19
- handlePart({
20
- type: partType,
21
- size: partSize,
22
- data: splitResult.extractedBuffer
23
- });
24
- this.chunkedDataBuffer = splitResult.remainingBuffer;
25
- }
26
- }
27
- readVarInt(offset) {
28
- let byteLength;
29
- if (this.chunkedDataBuffer.canReadBytes(offset, 1)) {
30
- const firstByte = this.chunkedDataBuffer.getUint8(offset);
31
- // Determine the length of the val
32
- if (firstByte < 128) {
33
- byteLength = 1;
34
- }
35
- else if (firstByte < 192) {
36
- byteLength = 2;
37
- }
38
- else if (firstByte < 224) {
39
- byteLength = 3;
40
- }
41
- else if (firstByte < 240) {
42
- byteLength = 4;
43
- }
44
- else {
45
- byteLength = 5;
46
- }
47
- }
48
- else {
49
- byteLength = 0;
50
- }
51
- if (byteLength < 1 || !this.chunkedDataBuffer.canReadBytes(offset, byteLength)) {
52
- return [-1, offset];
53
- }
54
- let value;
55
- // Now read it based on the length
56
- switch (byteLength) {
57
- case 1:
58
- value = this.chunkedDataBuffer.getUint8(offset++);
59
- break;
60
- case 2: {
61
- const byte1 = this.chunkedDataBuffer.getUint8(offset++);
62
- const byte2 = this.chunkedDataBuffer.getUint8(offset++);
63
- value = (byte1 & 0x3f) + 64 * byte2;
64
- break;
65
- }
66
- case 3: {
67
- const byte1 = this.chunkedDataBuffer.getUint8(offset++);
68
- const byte2 = this.chunkedDataBuffer.getUint8(offset++);
69
- const byte3 = this.chunkedDataBuffer.getUint8(offset++);
70
- value = (byte1 & 0x1f) + 32 * (byte2 + 256 * byte3);
71
- break;
72
- }
73
- case 4: {
74
- const byte1 = this.chunkedDataBuffer.getUint8(offset++);
75
- const byte2 = this.chunkedDataBuffer.getUint8(offset++);
76
- const byte3 = this.chunkedDataBuffer.getUint8(offset++);
77
- const byte4 = this.chunkedDataBuffer.getUint8(offset++);
78
- value = (byte1 & 0x0f) + 16 * (byte2 + 256 * (byte3 + 256 * byte4));
79
- break;
80
- }
81
- default: {
82
- const tempOffset = offset + 1;
83
- this.chunkedDataBuffer.focus(tempOffset);
84
- if (this.canReadFromCurrentChunk(tempOffset, 4)) {
85
- value = this.getCurrentDataView().getUint32(tempOffset - this.chunkedDataBuffer.currentChunkOffset, true);
86
- }
87
- else {
88
- const byte3 = this.chunkedDataBuffer.getUint8(tempOffset + 2) + 256 * this.chunkedDataBuffer.getUint8(tempOffset + 3);
89
- value =
90
- this.chunkedDataBuffer.getUint8(tempOffset) +
91
- 256 * (this.chunkedDataBuffer.getUint8(tempOffset + 1) + 256 * byte3);
92
- }
93
- offset += 5;
94
- break;
95
- }
96
- }
97
- return [value, offset];
98
- }
99
- canReadFromCurrentChunk(offset, length) {
100
- return offset - this.chunkedDataBuffer.currentChunkOffset + length <= this.chunkedDataBuffer.chunks[this.chunkedDataBuffer.currentChunkIndex].length;
101
- }
102
- getCurrentDataView() {
103
- if (!this.chunkedDataBuffer.currentDataView) {
104
- const currentChunk = this.chunkedDataBuffer.chunks[this.chunkedDataBuffer.currentChunkIndex];
105
- this.chunkedDataBuffer.currentDataView = new DataView(currentChunk.buffer, currentChunk.byteOffset, currentChunk.length);
106
- }
107
- return this.chunkedDataBuffer.currentDataView;
108
- }
109
- }
@@ -1,3 +0,0 @@
1
- export * from './ChunkedDataBuffer.js';
2
- export * from './UMP.js';
3
- export * from './ServerAbrStream.js';
@@ -1,3 +0,0 @@
1
- export * from './ChunkedDataBuffer.js';
2
- export * from './UMP.js';
3
- export * from './ServerAbrStream.js';
@@ -1,4 +0,0 @@
1
- import * as GoogleVideo from './core/index.js';
2
- export { GoogleVideo };
3
- export default GoogleVideo;
4
- export * from './utils/index.js';
package/dist/src/index.js DELETED
@@ -1,4 +0,0 @@
1
- import * as GoogleVideo from './core/index.js';
2
- export { GoogleVideo };
3
- export default GoogleVideo;
4
- export * from './utils/index.js';
@@ -1,63 +0,0 @@
1
- import type { FormatId } from '../../protos/generated/misc/common.js';
2
- export declare enum QUALITY {
3
- AUTO = 0,
4
- TINY = 144,
5
- SMALL = 240,
6
- MEDIUM = 360,
7
- LIGHT = 144,
8
- LARGE = 480,
9
- HD720 = 720,
10
- HD1080 = 1080,
11
- HD1440 = 1440,
12
- HD2160 = 2160,
13
- HD2880 = 2880,
14
- HIGHRES = 4320
15
- }
16
- export declare enum PART {
17
- ONESIE_HEADER = 10,
18
- ONESIE_DATA = 11,
19
- MEDIA_HEADER = 20,
20
- MEDIA = 21,
21
- MEDIA_END = 22,
22
- LIVE_METADATA = 31,
23
- HOSTNAME_CHANGE_HINT = 32,
24
- LIVE_METADATA_PROMISE = 33,
25
- LIVE_METADATA_PROMISE_CANCELLATION = 34,
26
- NEXT_REQUEST_POLICY = 35,
27
- USTREAMER_VIDEO_AND_FORMAT_DATA = 36,
28
- FORMAT_SELECTION_CONFIG = 37,
29
- USTREAMER_SELECTED_MEDIA_STREAM = 38,
30
- FORMAT_INITIALIZATION_METADATA = 42,
31
- SABR_REDIRECT = 43,
32
- SABR_ERROR = 44,
33
- SABR_SEEK = 45,
34
- RELOAD_PLAYER_RESPONSE = 46,
35
- PLAYBACK_START_POLICY = 47,
36
- ALLOWED_CACHED_FORMATS = 48,
37
- START_BW_SAMPLING_HINT = 49,
38
- PAUSE_BW_SAMPLING_HINT = 50,
39
- SELECTABLE_FORMATS = 51,
40
- REQUEST_IDENTIFIER = 52,
41
- REQUEST_CANCELLATION_POLICY = 53,
42
- ONESIE_PREFETCH_REJECTION = 54,
43
- TIMELINE_CONTEXT = 55,
44
- REQUEST_PIPELINING = 56,
45
- SABR_CONTEXT_UPDATE = 57,
46
- STREAM_PROTECTION_STATUS = 58,
47
- SABR_CONTEXT_SENDING_POLICY = 59,
48
- LAWNMOWER_POLICY = 60,
49
- SABR_ACK = 61,
50
- END_OF_TRACK = 62,
51
- CACHE_LOAD_POLICY = 63,
52
- LAWNMOWER_MESSAGING_POLICY = 64,
53
- PREWARM_CONNECTION = 65
54
- }
55
- export declare function u8ToBase64(u8: Uint8Array): string;
56
- export declare function base64ToU8(base64: string): Uint8Array;
57
- export declare function getFormatKey(formatId: FormatId): string;
58
- export declare function concatenateChunks(chunks: Uint8Array[]): Uint8Array;
59
- export declare class CustomEvent extends Event {
60
- #private;
61
- constructor(type: string, options?: CustomEventInit<any[]>);
62
- get detail(): any[] | null;
63
- }
@@ -1,101 +0,0 @@
1
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
- if (kind === "m") throw new TypeError("Private method is not writable");
3
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
- };
7
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
- };
12
- var _CustomEvent_detail;
13
- export var QUALITY;
14
- (function (QUALITY) {
15
- QUALITY[QUALITY["AUTO"] = 0] = "AUTO";
16
- QUALITY[QUALITY["TINY"] = 144] = "TINY";
17
- QUALITY[QUALITY["SMALL"] = 240] = "SMALL";
18
- QUALITY[QUALITY["MEDIUM"] = 360] = "MEDIUM";
19
- // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
20
- QUALITY[QUALITY["LIGHT"] = 144] = "LIGHT";
21
- QUALITY[QUALITY["LARGE"] = 480] = "LARGE";
22
- QUALITY[QUALITY["HD720"] = 720] = "HD720";
23
- QUALITY[QUALITY["HD1080"] = 1080] = "HD1080";
24
- QUALITY[QUALITY["HD1440"] = 1440] = "HD1440";
25
- QUALITY[QUALITY["HD2160"] = 2160] = "HD2160";
26
- QUALITY[QUALITY["HD2880"] = 2880] = "HD2880";
27
- QUALITY[QUALITY["HIGHRES"] = 4320] = "HIGHRES";
28
- })(QUALITY || (QUALITY = {}));
29
- export var PART;
30
- (function (PART) {
31
- PART[PART["ONESIE_HEADER"] = 10] = "ONESIE_HEADER";
32
- PART[PART["ONESIE_DATA"] = 11] = "ONESIE_DATA";
33
- PART[PART["MEDIA_HEADER"] = 20] = "MEDIA_HEADER";
34
- PART[PART["MEDIA"] = 21] = "MEDIA";
35
- PART[PART["MEDIA_END"] = 22] = "MEDIA_END";
36
- PART[PART["LIVE_METADATA"] = 31] = "LIVE_METADATA";
37
- PART[PART["HOSTNAME_CHANGE_HINT"] = 32] = "HOSTNAME_CHANGE_HINT";
38
- PART[PART["LIVE_METADATA_PROMISE"] = 33] = "LIVE_METADATA_PROMISE";
39
- PART[PART["LIVE_METADATA_PROMISE_CANCELLATION"] = 34] = "LIVE_METADATA_PROMISE_CANCELLATION";
40
- PART[PART["NEXT_REQUEST_POLICY"] = 35] = "NEXT_REQUEST_POLICY";
41
- PART[PART["USTREAMER_VIDEO_AND_FORMAT_DATA"] = 36] = "USTREAMER_VIDEO_AND_FORMAT_DATA";
42
- PART[PART["FORMAT_SELECTION_CONFIG"] = 37] = "FORMAT_SELECTION_CONFIG";
43
- PART[PART["USTREAMER_SELECTED_MEDIA_STREAM"] = 38] = "USTREAMER_SELECTED_MEDIA_STREAM";
44
- PART[PART["FORMAT_INITIALIZATION_METADATA"] = 42] = "FORMAT_INITIALIZATION_METADATA";
45
- PART[PART["SABR_REDIRECT"] = 43] = "SABR_REDIRECT";
46
- PART[PART["SABR_ERROR"] = 44] = "SABR_ERROR";
47
- PART[PART["SABR_SEEK"] = 45] = "SABR_SEEK";
48
- PART[PART["RELOAD_PLAYER_RESPONSE"] = 46] = "RELOAD_PLAYER_RESPONSE";
49
- PART[PART["PLAYBACK_START_POLICY"] = 47] = "PLAYBACK_START_POLICY";
50
- PART[PART["ALLOWED_CACHED_FORMATS"] = 48] = "ALLOWED_CACHED_FORMATS";
51
- PART[PART["START_BW_SAMPLING_HINT"] = 49] = "START_BW_SAMPLING_HINT";
52
- PART[PART["PAUSE_BW_SAMPLING_HINT"] = 50] = "PAUSE_BW_SAMPLING_HINT";
53
- PART[PART["SELECTABLE_FORMATS"] = 51] = "SELECTABLE_FORMATS";
54
- PART[PART["REQUEST_IDENTIFIER"] = 52] = "REQUEST_IDENTIFIER";
55
- PART[PART["REQUEST_CANCELLATION_POLICY"] = 53] = "REQUEST_CANCELLATION_POLICY";
56
- PART[PART["ONESIE_PREFETCH_REJECTION"] = 54] = "ONESIE_PREFETCH_REJECTION";
57
- PART[PART["TIMELINE_CONTEXT"] = 55] = "TIMELINE_CONTEXT";
58
- PART[PART["REQUEST_PIPELINING"] = 56] = "REQUEST_PIPELINING";
59
- PART[PART["SABR_CONTEXT_UPDATE"] = 57] = "SABR_CONTEXT_UPDATE";
60
- PART[PART["STREAM_PROTECTION_STATUS"] = 58] = "STREAM_PROTECTION_STATUS";
61
- PART[PART["SABR_CONTEXT_SENDING_POLICY"] = 59] = "SABR_CONTEXT_SENDING_POLICY";
62
- PART[PART["LAWNMOWER_POLICY"] = 60] = "LAWNMOWER_POLICY";
63
- PART[PART["SABR_ACK"] = 61] = "SABR_ACK";
64
- PART[PART["END_OF_TRACK"] = 62] = "END_OF_TRACK";
65
- PART[PART["CACHE_LOAD_POLICY"] = 63] = "CACHE_LOAD_POLICY";
66
- PART[PART["LAWNMOWER_MESSAGING_POLICY"] = 64] = "LAWNMOWER_MESSAGING_POLICY";
67
- PART[PART["PREWARM_CONNECTION"] = 65] = "PREWARM_CONNECTION";
68
- })(PART || (PART = {}));
69
- export function u8ToBase64(u8) {
70
- return btoa(String.fromCharCode.apply(null, Array.from(u8)));
71
- }
72
- export function base64ToU8(base64) {
73
- const standard_base64 = base64.replace(/-/g, '+').replace(/_/g, '/');
74
- const padded_base64 = standard_base64.padEnd(standard_base64.length + (4 - standard_base64.length % 4) % 4, '=');
75
- return new Uint8Array(atob(padded_base64).split('').map((char) => char.charCodeAt(0)));
76
- }
77
- export function getFormatKey(formatId) {
78
- return `${formatId.itag};${formatId.lastModified};`;
79
- }
80
- export function concatenateChunks(chunks) {
81
- const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
82
- const result = new Uint8Array(totalLength);
83
- let offset = 0;
84
- for (const chunk of chunks) {
85
- result.set(chunk, offset);
86
- offset += chunk.length;
87
- }
88
- return result;
89
- }
90
- // See https://github.com/nodejs/node/issues/40678#issuecomment-1126944677
91
- export class CustomEvent extends Event {
92
- constructor(type, options) {
93
- super(type, options);
94
- _CustomEvent_detail.set(this, void 0);
95
- __classPrivateFieldSet(this, _CustomEvent_detail, options?.detail ?? null, "f");
96
- }
97
- get detail() {
98
- return __classPrivateFieldGet(this, _CustomEvent_detail, "f");
99
- }
100
- }
101
- _CustomEvent_detail = new WeakMap();
@@ -1,65 +0,0 @@
1
- import type { FormatId } from '../../protos/generated/misc/common.js';
2
- import type { SabrError } from '../../protos/generated/video_streaming/sabr_error.js';
3
- import type { SabrRedirect } from '../../protos/generated/video_streaming/sabr_redirect.js';
4
- import type { StreamProtectionStatus } from '../../protos/generated/video_streaming/stream_protection_status.js';
5
- import type { TimeRange } from '../../protos/generated/video_streaming/time_range.js';
6
- import type { BufferedRange } from '../../protos/generated/video_streaming/buffered_range.js';
7
- import type { ClientAbrState } from '../../protos/generated/video_streaming/client_abr_state.js';
8
- import type { ChunkedDataBuffer } from '../core/index.js';
9
- export type Part = {
10
- type: number;
11
- size: number;
12
- data: ChunkedDataBuffer;
13
- };
14
- export type ServerAbrStreamOptions = {
15
- fetch: FetchFunction;
16
- serverAbrStreamingUrl: string;
17
- videoPlaybackUstreamerConfig: string;
18
- poToken?: string;
19
- durationMs: number;
20
- };
21
- export type ServerAbrResponse = {
22
- initializedFormats: InitializedFormat[];
23
- streamProtectionStatus?: StreamProtectionStatus;
24
- sabrRedirect?: SabrRedirect;
25
- sabrError?: SabrError;
26
- };
27
- export type Sequence = {
28
- itag?: number;
29
- formatId?: FormatId;
30
- isInitSegment?: boolean;
31
- durationMs?: number;
32
- startMs?: number;
33
- startDataRange?: number;
34
- sequenceNumber?: number;
35
- contentLength?: number;
36
- timeRange?: TimeRange;
37
- };
38
- export type InitializedFormat = {
39
- formatId: FormatId;
40
- formatKey: string;
41
- durationMs?: number;
42
- mimeType?: string;
43
- sequenceCount?: number;
44
- sequenceList: Sequence[];
45
- mediaChunks: Uint8Array[];
46
- _state: BufferedRange;
47
- };
48
- export type InitOptions = {
49
- audioFormats: Format[];
50
- videoFormats: Format[];
51
- clientAbrState?: ClientAbrState;
52
- };
53
- export type MediaArgs = {
54
- clientAbrState: ClientAbrState;
55
- audioFormatIds: FormatId[];
56
- videoFormatIds: FormatId[];
57
- };
58
- export type Format = {
59
- itag: number;
60
- width?: number;
61
- height?: number;
62
- lastModified: string;
63
- xtags?: string;
64
- };
65
- export type FetchFunction = typeof fetch;
@@ -1 +0,0 @@
1
- export {};