├── .release-please-manifest.json ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── question.yml │ ├── feature.yml │ └── issue.yml └── workflows │ ├── lint.yml │ ├── test.yml │ └── release-please.yml ├── .npmignore ├── src ├── exports │ ├── utils.ts │ ├── protos.ts │ ├── sabr-stream.ts │ ├── ump.ts │ └── sabr-streaming-adapter.ts ├── utils │ ├── index.ts │ ├── RequestMetadataManager.ts │ ├── EventEmitterLike.ts │ └── Logger.ts ├── types │ └── shared.ts └── core │ └── UmpWriter.ts ├── protos ├── video_streaming │ ├── sabr_redirect.proto │ ├── snackbar_message.proto │ ├── request_identifier.proto │ ├── sabr_error.proto │ ├── stream_protection_status.proto │ ├── time_range.proto │ ├── format_selection_config.proto │ ├── sabr_context_sending_policy.proto │ ├── crypto_params.proto │ ├── reload_player_response.proto │ ├── sabr_seek.proto │ ├── request_cancellation_policy.proto │ ├── onesie_innertube_request.proto │ ├── onesie_innertube_response.proto │ ├── playback_start_policy.proto │ ├── playback_cookie.proto │ ├── onesie_header_type.proto │ ├── onesie_proxy_status.proto │ ├── format_initialization_metadata.proto │ ├── next_request_policy.proto │ ├── live_metadata.proto │ ├── innertube_request.proto │ ├── media_header.proto │ ├── media_capabilities.proto │ ├── onesie_header.proto │ ├── onesie_request.proto │ ├── buffered_range.proto │ ├── sabr_context_update.proto │ ├── video_playback_abr_request.proto │ ├── streamer_context.proto │ ├── ump_part_id.proto │ └── client_abr_state.proto └── generated │ └── video_streaming │ ├── onesie_header_type.ts │ ├── onesie_proxy_status.ts │ ├── sabr_redirect.ts │ ├── snackbar_message.ts │ ├── request_identifier.ts │ ├── sabr_error.ts │ ├── stream_protection_status.ts │ ├── time_range.ts │ ├── crypto_params.ts │ ├── sabr_seek.ts │ ├── ump_part_id.ts │ ├── format_selection_config.ts │ └── playback_cookie.ts ├── .vscode └── settings.json ├── .editorconfig ├── docs └── api │ ├── exports │ ├── ump │ │ ├── README.md │ │ └── classes │ │ │ └── UmpWriter.md │ ├── protos │ │ ├── variables │ │ │ ├── Range.md │ │ │ ├── FormatId.md │ │ │ ├── HttpHeader.md │ │ │ ├── KeyValuePair.md │ │ │ ├── SabrError.md │ │ │ ├── IdentifierToken.md │ │ │ ├── AuthorizedFormat.md │ │ │ ├── MediaHeader.md │ │ │ ├── ClientInfo.md │ │ │ ├── CryptoParams.md │ │ │ ├── LiveMetadata.md │ │ │ ├── OnesieHeader.md │ │ │ ├── SabrRedirect.md │ │ │ ├── BufferedRange.md │ │ │ ├── OnesieRequest.md │ │ │ ├── PlaybackAuthorization.md │ │ │ ├── PlaybackCookie.md │ │ │ ├── ClientAbrState.md │ │ │ ├── UstreamerFlags.md │ │ │ ├── SnackbarMessage.md │ │ │ ├── StreamerContext.md │ │ │ ├── InnertubeRequest.md │ │ │ ├── SabrContextValue.md │ │ │ ├── MediaCapabilities.md │ │ │ ├── NextRequestPolicy.md │ │ │ ├── RequestIdentifier.md │ │ │ ├── SabrContextUpdate.md │ │ │ ├── PlaybackStartPolicy.md │ │ │ ├── ReloadPlaybackParams.md │ │ │ ├── ReloadPlaybackContext.md │ │ │ ├── FormatSelectionConfig.md │ │ │ ├── OnesieInnertubeRequest.md │ │ │ ├── StreamProtectionStatus.md │ │ │ ├── OnesieInnertubeResponse.md │ │ │ ├── VideoPlaybackAbrRequest.md │ │ │ ├── SabrContextSendingPolicy.md │ │ │ ├── RequestCancellationPolicy.md │ │ │ └── FormatInitializationMetadata.md │ │ ├── interfaces │ │ │ ├── SabrRedirect.md │ │ │ ├── SnackbarMessage.md │ │ │ ├── RequestIdentifier.md │ │ │ ├── ReloadPlaybackParams.md │ │ │ ├── UstreamerFlags.md │ │ │ ├── ReloadPlaybackContext.md │ │ │ ├── HttpHeader.md │ │ │ ├── KeyValuePair.md │ │ │ ├── AuthorizedFormat.md │ │ │ ├── IdentifierToken.md │ │ │ ├── SabrError.md │ │ │ ├── PlaybackAuthorization.md │ │ │ ├── StreamProtectionStatus.md │ │ │ ├── FormatId.md │ │ │ ├── PlaybackStartPolicy.md │ │ │ ├── CryptoParams.md │ │ │ ├── FormatSelectionConfig.md │ │ │ ├── Range.md │ │ │ ├── SabrContextValue.md │ │ │ ├── RequestCancellationPolicy.md │ │ │ ├── SabrContextSendingPolicy.md │ │ │ ├── MediaCapabilities.md │ │ │ ├── PlaybackCookie.md │ │ │ ├── OnesieInnertubeResponse.md │ │ │ ├── SabrContextUpdate.md │ │ │ ├── OnesieInnertubeRequest.md │ │ │ ├── StreamerContext.md │ │ │ └── NextRequestPolicy.md │ │ └── enumerations │ │ │ ├── CompressionType.md │ │ │ ├── NetworkMeteredState.md │ │ │ ├── SabrContextWritePolicy.md │ │ │ ├── VideoQualitySetting.md │ │ │ ├── AudioQuality.md │ │ │ └── OnesieRequestTarget.md │ ├── utils │ │ ├── variables │ │ │ └── MAX_INT32_VALUE.md │ │ ├── functions │ │ │ ├── u8ToBase64.md │ │ │ ├── base64ToU8.md │ │ │ ├── wait.md │ │ │ ├── concatenateChunks.md │ │ │ ├── parseRangeHeader.md │ │ │ ├── buildSabrFormat.md │ │ │ └── isGoogleVideoURL.md │ │ ├── namespaces │ │ │ └── FormatKeyUtils │ │ │ │ ├── README.md │ │ │ │ └── functions │ │ │ │ ├── createKey.md │ │ │ │ ├── fromMediaHeader.md │ │ │ │ ├── fromFormat.md │ │ │ │ ├── getUniqueFormatId.md │ │ │ │ ├── createSegmentCacheKeyFromMetadata.md │ │ │ │ ├── fromFormatInitializationMetadata.md │ │ │ │ └── createSegmentCacheKey.md │ │ ├── interfaces │ │ │ └── CacheEntry.md │ │ ├── enumerations │ │ │ ├── EnabledTrackTypes.md │ │ │ └── LogLevel.md │ │ ├── README.md │ │ └── classes │ │ │ └── RequestMetadataManager.md │ ├── sabr-stream │ │ ├── README.md │ │ └── interfaces │ │ │ └── InitializedFormat.md │ └── sabr-streaming-adapter │ │ ├── type-aliases │ │ ├── RequestFilter.md │ │ └── ResponseFilter.md │ │ ├── interfaces │ │ ├── UmpProcessingResult.md │ │ ├── RequestSegment.md │ │ ├── PlayerHttpRequest.md │ │ ├── PlayerHttpResponse.md │ │ └── SabrOptions.md │ │ ├── README.md │ │ ├── variables │ │ └── SABR_CONSTANTS.md │ │ └── classes │ │ └── SabrUmpProcessor.md │ ├── README.md │ └── types │ └── shared │ ├── type-aliases │ ├── FetchFunction.md │ └── Part.md │ └── README.md ├── typedoc.json ├── examples ├── onesie-request │ ├── package.json │ ├── utils.ts │ └── package-lock.json ├── sabr-shaka-example │ ├── tsconfig.json │ ├── package.json │ ├── scripts │ │ └── patchShaka.mjs │ ├── index.html │ └── README.md ├── README.md └── downloader │ ├── package.json │ ├── utils │ └── webpo-helper.ts │ └── main.ts ├── release-please-config.json ├── jsr.json ├── LICENSE ├── .gitignore ├── dev-scripts └── generate-proto.mjs └── package.json /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "4.0.4" 3 | } 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | ** 2 | 3 | src/ 4 | docs/ 5 | !dist/** 6 | !README.md 7 | !LICENSE 8 | !bundle/** -------------------------------------------------------------------------------- /src/exports/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This module contains general utilities. 3 | * @module 4 | */ 5 | 6 | export * from '../utils/index.js'; -------------------------------------------------------------------------------- /src/exports/protos.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This module contains protobuf definitions. 3 | * @module 4 | */ 5 | 6 | export * from '../utils/Protos.js'; -------------------------------------------------------------------------------- /protos/video_streaming/sabr_redirect.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | message SabrRedirect { 5 | optional string url = 1; 6 | } 7 | -------------------------------------------------------------------------------- /protos/video_streaming/snackbar_message.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | message SnackbarMessage { 5 | optional int32 id = 1; 6 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules\\typescript\\lib", 3 | "protoc": { 4 | "options": [ 5 | "--proto_path=protos", 6 | ] 7 | } 8 | } -------------------------------------------------------------------------------- /protos/video_streaming/request_identifier.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | package video_streaming; 4 | 5 | message RequestIdentifier { 6 | optional string token = 1; 7 | } -------------------------------------------------------------------------------- /protos/video_streaming/sabr_error.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | message SabrError { 5 | optional string type = 1; 6 | optional int32 code = 2; 7 | } 8 | -------------------------------------------------------------------------------- /src/exports/sabr-stream.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This module contains a SABR client for downloading videos. 3 | * @module 4 | */ 5 | 6 | export * from '../core/SabrStream.js'; 7 | export type * from '../types/sabrStreamTypes.js'; -------------------------------------------------------------------------------- /protos/video_streaming/stream_protection_status.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | message StreamProtectionStatus { 5 | optional int32 status = 1; 6 | optional int32 max_retries = 2; 7 | } 8 | -------------------------------------------------------------------------------- /protos/video_streaming/time_range.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | message TimeRange { 5 | optional int64 start_ticks = 1; 6 | optional int64 duration_ticks = 2; 7 | optional int32 timescale = 3; 8 | } 9 | -------------------------------------------------------------------------------- /src/exports/ump.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This module contains utilities for writing and reading UMP data. 3 | * @module 4 | */ 5 | 6 | export * from '../core/UmpReader.js'; 7 | export * from '../core/UmpWriter.js'; 8 | export * from '../core/CompositeBuffer.js'; -------------------------------------------------------------------------------- /protos/video_streaming/format_selection_config.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | package video_streaming; 4 | 5 | message FormatSelectionConfig { 6 | repeated int32 itags = 2; 7 | optional string video_id = 3; 8 | optional int32 resolution = 4; 9 | } -------------------------------------------------------------------------------- /protos/video_streaming/sabr_context_sending_policy.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | message SabrContextSendingPolicy { 5 | repeated int32 start_policy = 1; 6 | repeated int32 stop_policy = 2; 7 | repeated int32 discard_policy = 3; 8 | } -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Logger.js'; 2 | export * from './shared.js'; 3 | export * from './CacheManager.js'; 4 | export * from './EventEmitterLike.js'; 5 | export * from './RequestMetadataManager.js'; 6 | export * as FormatKeyUtils from './formatKeyUtils.js'; -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = false 12 | insert_final_newline = false -------------------------------------------------------------------------------- /protos/video_streaming/crypto_params.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | import "misc/common.proto"; 5 | 6 | message CryptoParams { 7 | optional bytes hmac = 4; 8 | optional bytes iv = 5; 9 | optional .misc.CompressionType compression_type = 6; 10 | } 11 | -------------------------------------------------------------------------------- /protos/video_streaming/reload_player_response.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | package video_streaming; 4 | 5 | message ReloadPlaybackParams { 6 | optional string token = 1; 7 | } 8 | 9 | message ReloadPlaybackContext { 10 | optional ReloadPlaybackParams reload_playback_params = 1; 11 | } -------------------------------------------------------------------------------- /protos/video_streaming/sabr_seek.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | import "misc/common.proto"; 5 | 6 | message SabrSeek { 7 | optional int64 seek_media_time = 1; 8 | optional int32 seek_media_timescale = 2; 9 | optional .misc.SeekSource seek_source = 3; 10 | } 11 | -------------------------------------------------------------------------------- /docs/api/exports/ump/README.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../README.md) / exports/ump 2 | 3 | # exports/ump 4 | 5 | This module contains utilities for writing and reading UMP data. 6 | 7 | ## Classes 8 | 9 | - [CompositeBuffer](classes/CompositeBuffer.md) 10 | - [UmpReader](classes/UmpReader.md) 11 | - [UmpWriter](classes/UmpWriter.md) 12 | -------------------------------------------------------------------------------- /docs/api/README.md: -------------------------------------------------------------------------------- 1 | # googlevideo 2 | 3 | ## Modules 4 | 5 | - [exports/protos](exports/protos/README.md) 6 | - [exports/sabr-stream](exports/sabr-stream/README.md) 7 | - [exports/sabr-streaming-adapter](exports/sabr-streaming-adapter/README.md) 8 | - [exports/ump](exports/ump/README.md) 9 | - [exports/utils](exports/utils/README.md) 10 | - [types/shared](types/shared/README.md) 11 | -------------------------------------------------------------------------------- /docs/api/types/shared/type-aliases/FetchFunction.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [types/shared](../README.md) / FetchFunction 2 | 3 | # Type Alias: FetchFunction 4 | 5 | > **FetchFunction** = *typeof* `fetch` 6 | 7 | Defined in: [codeberg/googlevideo/src/types/shared.ts:71](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/shared.ts#L71) 8 | -------------------------------------------------------------------------------- /protos/video_streaming/request_cancellation_policy.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | message RequestCancellationPolicy { 5 | message Item { 6 | optional int32 fR = 1; 7 | optional int32 NK = 2; 8 | optional int32 minReadaheadMs = 3; 9 | } 10 | 11 | optional int32 N0 = 1; 12 | repeated Item items = 2; 13 | optional int32 jq = 3; 14 | } 15 | -------------------------------------------------------------------------------- /src/exports/sabr-streaming-adapter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This module contains the core classes, types, and utilities required to integrate YouTube's SABR streaming protocol 3 | * into a media player. 4 | * @module 5 | */ 6 | 7 | export * from '../core/SabrStreamingAdapter.js'; 8 | export * from '../core/SabrUmpProcessor.js'; 9 | export type * from '../types/sabrStreamingAdapterTypes.js'; 10 | -------------------------------------------------------------------------------- /protos/video_streaming/onesie_innertube_request.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | import "misc/common.proto"; 5 | 6 | message OnesieInnertubeRequest { 7 | optional string url = 1; 8 | repeated misc.HttpHeader headers = 2; 9 | optional string body = 3; 10 | optional bool proxied_by_trusted_bandaid = 4; 11 | optional bool skip_response_encryption = 6; 12 | } 13 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/Range.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / Range 2 | 3 | # Variable: Range 4 | 5 | > **Range**: `MessageFns`\<[`Range`](../interfaces/Range.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:192](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L192) 8 | -------------------------------------------------------------------------------- /docs/api/exports/utils/variables/MAX_INT32_VALUE.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/utils](../README.md) / MAX\_INT32\_VALUE 2 | 3 | # Variable: MAX\_INT32\_VALUE 4 | 5 | > `const` **MAX\_INT32\_VALUE**: `2147483647` = `2147483647` 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/shared.ts:3](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/shared.ts#L3) 8 | -------------------------------------------------------------------------------- /docs/api/types/shared/README.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../README.md) / types/shared 2 | 3 | # types/shared 4 | 5 | This module contains type definitions used across the library. 6 | 7 | ## Interfaces 8 | 9 | - [FormatStream](interfaces/FormatStream.md) 10 | - [SabrFormat](interfaces/SabrFormat.md) 11 | 12 | ## Type Aliases 13 | 14 | - [FetchFunction](type-aliases/FetchFunction.md) 15 | - [Part](type-aliases/Part.md) 16 | -------------------------------------------------------------------------------- /protos/video_streaming/onesie_innertube_response.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | import "misc/common.proto"; 5 | import "video_streaming/onesie_proxy_status.proto"; 6 | 7 | message OnesieInnertubeResponse { 8 | optional OnesieProxyStatus onesie_proxy_status = 1; 9 | optional int32 http_status = 2; 10 | repeated .misc.HttpHeader headers = 3; 11 | optional bytes body = 4; 12 | } 13 | -------------------------------------------------------------------------------- /protos/video_streaming/playback_start_policy.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | message PlaybackStartPolicy { 5 | message ReadaheadPolicy { 6 | optional int32 min_readahead_ms = 2; 7 | optional int32 min_bandwidth_bytes_per_sec = 1; 8 | } 9 | 10 | optional ReadaheadPolicy start_min_readahead_policy = 1; 11 | optional ReadaheadPolicy resume_min_readahead_policy = 2; 12 | } 13 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/FormatId.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / FormatId 2 | 3 | # Variable: FormatId 4 | 5 | > **FormatId**: `MessageFns`\<[`FormatId`](../interfaces/FormatId.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:186](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L186) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/HttpHeader.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / HttpHeader 2 | 3 | # Variable: HttpHeader 4 | 5 | > **HttpHeader**: `MessageFns`\<[`HttpHeader`](../interfaces/HttpHeader.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:181](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L181) 8 | -------------------------------------------------------------------------------- /protos/video_streaming/playback_cookie.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | import "misc/common.proto"; 5 | 6 | message PlaybackCookie { 7 | optional int32 resolution = 1; // Always 999999 when resolution is set manually, or if the auto selected one is the max available resolution. 8 | optional int32 field2 = 2; 9 | optional .misc.FormatId video_fmt = 7; 10 | optional .misc.FormatId audio_fmt = 8; 11 | } 12 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "readme": "none", 3 | "entryPoints": [ 4 | "src/exports/ump.ts", 5 | "src/exports/sabr-streaming-adapter.ts", 6 | "src/exports/sabr-stream.ts", 7 | "src/exports/protos.ts", 8 | "src/exports/utils.ts", 9 | "src/types/shared.ts" 10 | ], 11 | "out": "docs/api", 12 | "plugin": [ 13 | "typedoc-plugin-markdown" 14 | ], 15 | "hidePageHeader": true, 16 | "tsconfig": "tsconfig.json" 17 | } -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/KeyValuePair.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / KeyValuePair 2 | 3 | # Variable: KeyValuePair 4 | 5 | > **KeyValuePair**: `MessageFns`\<[`KeyValuePair`](../interfaces/KeyValuePair.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:204](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L204) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/SabrError.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / SabrError 2 | 3 | # Variable: SabrError 4 | 5 | > **SabrError**: `MessageFns`\<[`SabrError`](../interfaces/SabrError.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_error.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_error.ts#L12) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/IdentifierToken.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / IdentifierToken 2 | 3 | # Variable: IdentifierToken 4 | 5 | > **IdentifierToken**: `MessageFns`\<[`IdentifierToken`](../interfaces/IdentifierToken.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:199](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L199) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/AuthorizedFormat.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / AuthorizedFormat 2 | 3 | # Variable: AuthorizedFormat 4 | 5 | > **AuthorizedFormat**: `MessageFns`\<[`AuthorizedFormat`](../interfaces/AuthorizedFormat.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:209](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L209) 8 | -------------------------------------------------------------------------------- /examples/onesie-request/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "name": "onesie-request", 4 | "version": "1.0.0", 5 | "description": "", 6 | "main": "main.js", 7 | "module": "main.js", 8 | "scripts": { 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "googlevideo": "file:../..", 16 | "youtubei.js": "^16.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/MediaHeader.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / MediaHeader 2 | 3 | # Variable: MediaHeader 4 | 5 | > **MediaHeader**: `MessageFns`\<[`MediaHeader`](../interfaces/MediaHeader.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/media\_header.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/media_header.ts#L14) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/ClientInfo.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / ClientInfo 2 | 3 | # Variable: ClientInfo 4 | 5 | > **ClientInfo**: `MessageFns`\<[`ClientInfo`](../interfaces/ClientInfo.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/streamer\_context.ts:30](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/streamer_context.ts#L30) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/CryptoParams.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / CryptoParams 2 | 3 | # Variable: CryptoParams 4 | 5 | > **CryptoParams**: `MessageFns`\<[`CryptoParams`](../interfaces/CryptoParams.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/crypto\_params.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/crypto_params.ts#L13) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/LiveMetadata.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / LiveMetadata 2 | 3 | # Variable: LiveMetadata 4 | 5 | > **LiveMetadata**: `MessageFns`\<[`LiveMetadata`](../interfaces/LiveMetadata.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/live\_metadata.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/live_metadata.ts#L12) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/OnesieHeader.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / OnesieHeader 2 | 3 | # Variable: OnesieHeader 4 | 5 | > **OnesieHeader**: `MessageFns`\<[`OnesieHeader`](../interfaces/OnesieHeader.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_header.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_header.ts#L14) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/SabrRedirect.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / SabrRedirect 2 | 3 | # Variable: SabrRedirect 4 | 5 | > **SabrRedirect**: `MessageFns`\<[`SabrRedirect`](../interfaces/SabrRedirect.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_redirect.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_redirect.ts#L12) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/BufferedRange.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / BufferedRange 2 | 3 | # Variable: BufferedRange 4 | 5 | > **BufferedRange**: `MessageFns`\<[`BufferedRange`](../interfaces/BufferedRange.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/buffered\_range.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/buffered_range.ts#L14) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/OnesieRequest.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / OnesieRequest 2 | 3 | # Variable: OnesieRequest 4 | 5 | > **OnesieRequest**: `MessageFns`\<[`OnesieRequest`](../interfaces/OnesieRequest.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_request.ts:18](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_request.ts#L18) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/PlaybackAuthorization.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / PlaybackAuthorization 2 | 3 | # Variable: PlaybackAuthorization 4 | 5 | > **PlaybackAuthorization**: `MessageFns`\<[`PlaybackAuthorization`](../interfaces/PlaybackAuthorization.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:214](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L214) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/PlaybackCookie.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / PlaybackCookie 2 | 3 | # Variable: PlaybackCookie 4 | 5 | > **PlaybackCookie**: `MessageFns`\<[`PlaybackCookie`](../interfaces/PlaybackCookie.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/playback\_cookie.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/playback_cookie.ts#L13) 8 | -------------------------------------------------------------------------------- /examples/sabr-shaka-example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ESNext", "DOM"], 7 | "moduleResolution": "bundler", 8 | "strict": true, 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "esModuleInterop": true, 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true 15 | }, 16 | "include": ["src"] 17 | } -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/ClientAbrState.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / ClientAbrState 2 | 3 | # Variable: ClientAbrState 4 | 5 | > **ClientAbrState**: `MessageFns`\<[`ClientAbrState`](../interfaces/ClientAbrState.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/client\_abr\_state.ts:20](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/client_abr_state.ts#L20) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/UstreamerFlags.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / UstreamerFlags 2 | 3 | # Variable: UstreamerFlags 4 | 5 | > **UstreamerFlags**: `MessageFns`\<[`UstreamerFlags`](../interfaces/UstreamerFlags.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/innertube\_request.ts:27](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/innertube_request.ts#L27) 8 | -------------------------------------------------------------------------------- /protos/video_streaming/onesie_header_type.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | enum OnesieHeaderType { 5 | ONESIE_PLAYER_RESPONSE = 0; 6 | MEDIA = 1; 7 | MEDIA_DECRYPTION_KEY = 2; 8 | CLEAR_MEDIA = 3; 9 | CLEAR_INIT_SEGMENT = 4; 10 | ACK = 5; 11 | MEDIA_STREAMER_HOSTNAME = 6; 12 | MEDIA_SIZE_HINT = 7; 13 | PLAYER_SERVICE_RESPONSE_PUSH_URL = 8; 14 | LAST_HIGH_PRIORITY_HINT = 9; 15 | STREAM_METADATA = 16; 16 | ENCRYPTED_INNERTUBE_RESPONSE_PART = 25; 17 | } 18 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/SnackbarMessage.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / SnackbarMessage 2 | 3 | # Variable: SnackbarMessage 4 | 5 | > **SnackbarMessage**: `MessageFns`\<[`SnackbarMessage`](../interfaces/SnackbarMessage.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/snackbar\_message.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/snackbar_message.ts#L12) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/StreamerContext.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / StreamerContext 2 | 3 | # Variable: StreamerContext 4 | 5 | > **StreamerContext**: `MessageFns`\<[`StreamerContext`](../interfaces/StreamerContext.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/streamer\_context.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/streamer_context.ts#L12) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/InnertubeRequest.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / InnertubeRequest 2 | 3 | # Variable: InnertubeRequest 4 | 5 | > **InnertubeRequest**: `MessageFns`\<[`InnertubeRequest`](../interfaces/InnertubeRequest.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/innertube\_request.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/innertube_request.ts#L12) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/SabrContextValue.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / SabrContextValue 2 | 3 | # Variable: SabrContextValue 4 | 5 | > **SabrContextValue**: `MessageFns`\<[`SabrContextValue`](../interfaces/SabrContextValue.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:37](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L37) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/MediaCapabilities.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / MediaCapabilities 2 | 3 | # Variable: MediaCapabilities 4 | 5 | > **MediaCapabilities**: `MessageFns`\<[`MediaCapabilities`](../interfaces/MediaCapabilities.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/media\_capabilities.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/media_capabilities.ts#L12) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/NextRequestPolicy.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / NextRequestPolicy 2 | 3 | # Variable: NextRequestPolicy 4 | 5 | > **NextRequestPolicy**: `MessageFns`\<[`NextRequestPolicy`](../interfaces/NextRequestPolicy.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/next\_request\_policy.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/next_request_policy.ts#L13) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/RequestIdentifier.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / RequestIdentifier 2 | 3 | # Variable: RequestIdentifier 4 | 5 | > **RequestIdentifier**: `MessageFns`\<[`RequestIdentifier`](../interfaces/RequestIdentifier.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/request\_identifier.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/request_identifier.ts#L12) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/SabrContextUpdate.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / SabrContextUpdate 2 | 3 | # Variable: SabrContextUpdate 4 | 5 | > **SabrContextUpdate**: `MessageFns`\<[`SabrContextUpdate`](../interfaces/SabrContextUpdate.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L12) 8 | -------------------------------------------------------------------------------- /docs/api/exports/sabr-stream/README.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../README.md) / exports/sabr-stream 2 | 3 | # exports/sabr-stream 4 | 5 | This module contains a SABR client for downloading videos. 6 | 7 | ## Classes 8 | 9 | - [SabrStream](classes/SabrStream.md) 10 | 11 | ## Interfaces 12 | 13 | - [InitializedFormat](interfaces/InitializedFormat.md) 14 | - [SabrPlaybackOptions](interfaces/SabrPlaybackOptions.md) 15 | - [SabrStreamConfig](interfaces/SabrStreamConfig.md) 16 | - [SabrStreamState](interfaces/SabrStreamState.md) 17 | -------------------------------------------------------------------------------- /docs/api/exports/utils/functions/u8ToBase64.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/utils](../README.md) / u8ToBase64 2 | 3 | # Function: u8ToBase64() 4 | 5 | > **u8ToBase64**(`u8`): `string` 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/shared.ts:71](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/shared.ts#L71) 8 | 9 | Converts a Uint8Array to a Base64 string. 10 | 11 | ## Parameters 12 | 13 | ### u8 14 | 15 | `Uint8Array` 16 | 17 | ## Returns 18 | 19 | `string` 20 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | ## SABR/UMP Player 2 | See [sabr-shaka-example/README.md](./sabr-shaka-example/README.md). 3 | 4 | ## Downloader Example 5 | 6 | ```bash 7 | npm run build # If you haven't built the library yet. 8 | cd examples/downloader 9 | npm install 10 | npx tsx main.ts 11 | 12 | # Example with ffmpeg 13 | npx tsx ffmpeg-example.ts 14 | ``` 15 | 16 | ## "Onesie" Request Example 17 | 18 | ```bash 19 | npm run build # If you haven't built the library yet. 20 | cd examples/onesie-request 21 | npm install 22 | npx tsx main.ts 23 | ``` -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/PlaybackStartPolicy.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / PlaybackStartPolicy 2 | 3 | # Variable: PlaybackStartPolicy 4 | 5 | > **PlaybackStartPolicy**: `MessageFns`\<[`PlaybackStartPolicy`](../interfaces/PlaybackStartPolicy.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/playback\_start\_policy.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/playback_start_policy.ts#L12) 8 | -------------------------------------------------------------------------------- /docs/api/exports/utils/functions/base64ToU8.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/utils](../README.md) / base64ToU8 2 | 3 | # Function: base64ToU8() 4 | 5 | > **base64ToU8**(`base64`): `Uint8Array` 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/shared.ts:79](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/shared.ts#L79) 8 | 9 | Converts a Base64 string to a Uint8Array. 10 | 11 | ## Parameters 12 | 13 | ### base64 14 | 15 | `string` 16 | 17 | ## Returns 18 | 19 | `Uint8Array` 20 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/ReloadPlaybackParams.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / ReloadPlaybackParams 2 | 3 | # Variable: ReloadPlaybackParams 4 | 5 | > **ReloadPlaybackParams**: `MessageFns`\<[`ReloadPlaybackParams`](../interfaces/ReloadPlaybackParams.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/reload\_player\_response.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/reload_player_response.ts#L12) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/ReloadPlaybackContext.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / ReloadPlaybackContext 2 | 3 | # Variable: ReloadPlaybackContext 4 | 5 | > **ReloadPlaybackContext**: `MessageFns`\<[`ReloadPlaybackContext`](../interfaces/ReloadPlaybackContext.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/reload\_player\_response.ts:16](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/reload_player_response.ts#L16) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/FormatSelectionConfig.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / FormatSelectionConfig 2 | 3 | # Variable: FormatSelectionConfig 4 | 5 | > **FormatSelectionConfig**: `MessageFns`\<[`FormatSelectionConfig`](../interfaces/FormatSelectionConfig.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/format\_selection\_config.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/format_selection_config.ts#L12) 8 | -------------------------------------------------------------------------------- /protos/video_streaming/onesie_proxy_status.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | enum OnesieProxyStatus { 5 | UNKNOWN = 0; 6 | OK = 1; 7 | DECRYPTION_FAILED = 2; 8 | PARSING_FAILED = 3; 9 | MISSING_X_FORWARDED_FOR = 4; 10 | INVALID_X_FORWARDED_FOR = 5; 11 | INVALID_CONTENT_TYPE = 6; 12 | BACKEND_ERROR = 7; 13 | CLIENT_ERROR = 8; 14 | MISSING_CRYPTER = 9; 15 | RESPONSE_JSON_SERIALIZATION_FAILED = 10; 16 | DECOMPRESSION_FAILED = 11; 17 | JSON_PARSING_FAILED = 12; 18 | UNKNOWN_COMPRESSION_TYPE = 13; 19 | } 20 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/OnesieInnertubeRequest.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / OnesieInnertubeRequest 2 | 3 | # Variable: OnesieInnertubeRequest 4 | 5 | > **OnesieInnertubeRequest**: `MessageFns`\<[`OnesieInnertubeRequest`](../interfaces/OnesieInnertubeRequest.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_innertube\_request.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_innertube_request.ts#L13) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/StreamProtectionStatus.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / StreamProtectionStatus 2 | 3 | # Variable: StreamProtectionStatus 4 | 5 | > **StreamProtectionStatus**: `MessageFns`\<[`StreamProtectionStatus`](../interfaces/StreamProtectionStatus.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/stream\_protection\_status.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/stream_protection_status.ts#L12) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/OnesieInnertubeResponse.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / OnesieInnertubeResponse 2 | 3 | # Variable: OnesieInnertubeResponse 4 | 5 | > **OnesieInnertubeResponse**: `MessageFns`\<[`OnesieInnertubeResponse`](../interfaces/OnesieInnertubeResponse.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_innertube\_response.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_innertube_response.ts#L14) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/VideoPlaybackAbrRequest.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / VideoPlaybackAbrRequest 2 | 3 | # Variable: VideoPlaybackAbrRequest 4 | 5 | > **VideoPlaybackAbrRequest**: `MessageFns`\<[`VideoPlaybackAbrRequest`](../interfaces/VideoPlaybackAbrRequest.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/video\_playback\_abr\_request.ts:17](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/video_playback_abr_request.ts#L17) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/SabrContextSendingPolicy.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / SabrContextSendingPolicy 2 | 3 | # Variable: SabrContextSendingPolicy 4 | 5 | > **SabrContextSendingPolicy**: `MessageFns`\<[`SabrContextSendingPolicy`](../interfaces/SabrContextSendingPolicy.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_sending\_policy.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_sending_policy.ts#L12) 8 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/RequestCancellationPolicy.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / RequestCancellationPolicy 2 | 3 | # Variable: RequestCancellationPolicy 4 | 5 | > **RequestCancellationPolicy**: `MessageFns`\<[`RequestCancellationPolicy`](../interfaces/RequestCancellationPolicy.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/request\_cancellation\_policy.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/request_cancellation_policy.ts#L12) 8 | -------------------------------------------------------------------------------- /examples/sabr-shaka-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sabr-shaka-example", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "tsc && vite build", 8 | "patch:shaka": "node ./scripts/patchShaka.mjs", 9 | "postinstall": "npm run patch:shaka" 10 | }, 11 | "dependencies": { 12 | "bgutils-js": "^3.2.0", 13 | "googlevideo": "^4.0.4", 14 | "shaka-player": "^4.16.2", 15 | "youtubei.js": "^16.0.0" 16 | }, 17 | "devDependencies": { 18 | "typescript": "^5.4.5", 19 | "vite": "^7.1.11" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /release-please-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": { 3 | ".": { 4 | "changelog-path": "CHANGELOG.md", 5 | "release-type": "node", 6 | "bump-minor-pre-major": false, 7 | "bump-patch-for-minor-pre-major": false, 8 | "draft": false, 9 | "prerelease": false, 10 | "extra-files": [ 11 | { 12 | "type": "json", 13 | "path": "jsr.json", 14 | "jsonpath": "$.version" 15 | } 16 | ] 17 | } 18 | }, 19 | "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json" 20 | } -------------------------------------------------------------------------------- /protos/video_streaming/format_initialization_metadata.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | import "misc/common.proto"; 5 | 6 | message FormatInitializationMetadata { 7 | optional string video_id = 1; 8 | optional .misc.FormatId format_id = 2; 9 | optional int64 end_time_ms = 3; 10 | optional int64 end_segment_number = 4; 11 | optional string mime_type = 5; 12 | optional .misc.Range init_range = 6; 13 | optional .misc.Range index_range = 7; 14 | optional int64 field8 = 8; 15 | optional int64 duration_units = 9; 16 | optional int64 duration_timescale = 10; 17 | } -------------------------------------------------------------------------------- /protos/video_streaming/next_request_policy.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | import "video_streaming/playback_cookie.proto"; 5 | 6 | message NextRequestPolicy { 7 | optional int32 target_audio_readahead_ms = 1; 8 | optional int32 target_video_readahead_ms = 2; 9 | optional int32 max_time_since_last_request_ms = 3; 10 | optional int32 backoff_time_ms = 4; 11 | optional int32 min_audio_readahead_ms = 5; 12 | optional int32 min_video_readahead_ms = 6; 13 | optional .video_streaming.PlaybackCookie playback_cookie = 7; 14 | optional string video_id = 8; 15 | } 16 | -------------------------------------------------------------------------------- /docs/api/exports/utils/functions/wait.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/utils](../README.md) / wait 2 | 3 | # Function: wait() 4 | 5 | > **wait**(`ms`): `Promise`\<`void`\> 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/shared.ts:136](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/shared.ts#L136) 8 | 9 | Returns a promise that resolves after a specified number of milliseconds. 10 | 11 | ## Parameters 12 | 13 | ### ms 14 | 15 | `number` 16 | 17 | The number of milliseconds to wait. 18 | 19 | ## Returns 20 | 21 | `Promise`\<`void`\> 22 | -------------------------------------------------------------------------------- /protos/video_streaming/live_metadata.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | message LiveMetadata { 5 | optional string broadcast_id = 1; 6 | optional int64 head_sequence_number = 3; 7 | optional int64 head_time_ms = 4; 8 | optional int64 wall_time_ms = 5; 9 | optional string video_id = 6; 10 | optional bool post_live_dvr = 8; 11 | optional int64 headm = 10; 12 | optional int64 min_seekable_time_ticks = 12; 13 | optional int32 min_seekable_timescale = 13; 14 | optional int64 max_seekable_time_ticks = 14; 15 | optional int32 max_seekable_timescale = 15; 16 | } 17 | -------------------------------------------------------------------------------- /docs/api/exports/protos/variables/FormatInitializationMetadata.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / FormatInitializationMetadata 2 | 3 | # Variable: FormatInitializationMetadata 4 | 5 | > **FormatInitializationMetadata**: `MessageFns`\<[`FormatInitializationMetadata`](../interfaces/FormatInitializationMetadata.md)\> 6 | 7 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/format\_initialization\_metadata.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/format_initialization_metadata.ts#L13) 8 | -------------------------------------------------------------------------------- /docs/api/exports/utils/functions/concatenateChunks.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/utils](../README.md) / concatenateChunks 2 | 3 | # Function: concatenateChunks() 4 | 5 | > **concatenateChunks**(`chunks`): `Uint8Array` 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/shared.ts:89](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/shared.ts#L89) 8 | 9 | Concatenates multiple Uint8Array chunks into a single Uint8Array. 10 | 11 | ## Parameters 12 | 13 | ### chunks 14 | 15 | `Uint8Array`\<`ArrayBufferLike`\>[] 16 | 17 | ## Returns 18 | 19 | `Uint8Array` 20 | -------------------------------------------------------------------------------- /docs/api/exports/utils/namespaces/FormatKeyUtils/README.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../../README.md) / [exports/utils](../../README.md) / FormatKeyUtils 2 | 3 | # FormatKeyUtils 4 | 5 | ## Functions 6 | 7 | - [createKey](functions/createKey.md) 8 | - [createSegmentCacheKey](functions/createSegmentCacheKey.md) 9 | - [createSegmentCacheKeyFromMetadata](functions/createSegmentCacheKeyFromMetadata.md) 10 | - [fromFormat](functions/fromFormat.md) 11 | - [fromFormatInitializationMetadata](functions/fromFormatInitializationMetadata.md) 12 | - [fromMediaHeader](functions/fromMediaHeader.md) 13 | - [getUniqueFormatId](functions/getUniqueFormatId.md) 14 | -------------------------------------------------------------------------------- /docs/api/exports/utils/functions/parseRangeHeader.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/utils](../README.md) / parseRangeHeader 2 | 3 | # Function: parseRangeHeader() 4 | 5 | > **parseRangeHeader**(`rangeHeaderValue`): `undefined` \| `Range` 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/shared.ts:54](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/shared.ts#L54) 8 | 9 | Parses the Range header value to extract the start and end byte positions. 10 | 11 | ## Parameters 12 | 13 | ### rangeHeaderValue 14 | 15 | `undefined` | `string` 16 | 17 | ## Returns 18 | 19 | `undefined` \| `Range` 20 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/SabrRedirect.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / SabrRedirect 2 | 3 | # Interface: SabrRedirect 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_redirect.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_redirect.ts#L12) 6 | 7 | ## Properties 8 | 9 | ### url? 10 | 11 | > `optional` **url**: `string` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_redirect.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_redirect.ts#L13) 14 | -------------------------------------------------------------------------------- /docs/api/exports/utils/namespaces/FormatKeyUtils/functions/createKey.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../../../README.md) / [exports/utils](../../../README.md) / [FormatKeyUtils](../README.md) / createKey 2 | 3 | # Function: createKey() 4 | 5 | > **createKey**(`itag`, `xtags`): `string` 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/formatKeyUtils.ts:10](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/formatKeyUtils.ts#L10) 8 | 9 | Creates a format key based on itag and xtags. 10 | 11 | ## Parameters 12 | 13 | ### itag 14 | 15 | `undefined` | `number` 16 | 17 | ### xtags 18 | 19 | `undefined` | `string` 20 | 21 | ## Returns 22 | 23 | `string` 24 | 25 | A string format key. 26 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/SnackbarMessage.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / SnackbarMessage 2 | 3 | # Interface: SnackbarMessage 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/snackbar\_message.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/snackbar_message.ts#L12) 6 | 7 | ## Properties 8 | 9 | ### id? 10 | 11 | > `optional` **id**: `number` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/snackbar\_message.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/snackbar_message.ts#L13) 14 | -------------------------------------------------------------------------------- /docs/api/exports/utils/namespaces/FormatKeyUtils/functions/fromMediaHeader.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../../../README.md) / [exports/utils](../../../README.md) / [FormatKeyUtils](../README.md) / fromMediaHeader 2 | 3 | # Function: fromMediaHeader() 4 | 5 | > **fromMediaHeader**(`mediaHeader`): `string` 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/formatKeyUtils.ts:27](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/formatKeyUtils.ts#L27) 8 | 9 | Creates a format key from a MediaHeader object. 10 | 11 | ## Parameters 12 | 13 | ### mediaHeader 14 | 15 | [`MediaHeader`](../../../../protos/interfaces/MediaHeader.md) 16 | 17 | ## Returns 18 | 19 | `string` 20 | 21 | A string format key. 22 | -------------------------------------------------------------------------------- /docs/api/exports/utils/functions/buildSabrFormat.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/utils](../README.md) / buildSabrFormat 2 | 3 | # Function: buildSabrFormat() 4 | 5 | > **buildSabrFormat**(`formatStream`): [`SabrFormat`](../../../types/shared/interfaces/SabrFormat.md) 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/shared.ts:104](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/shared.ts#L104) 8 | 9 | Converts a FormatStream object to a SabrFormat object. 10 | 11 | ## Parameters 12 | 13 | ### formatStream 14 | 15 | [`FormatStream`](../../../types/shared/interfaces/FormatStream.md) 16 | 17 | ## Returns 18 | 19 | [`SabrFormat`](../../../types/shared/interfaces/SabrFormat.md) 20 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/RequestIdentifier.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / RequestIdentifier 2 | 3 | # Interface: RequestIdentifier 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/request\_identifier.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/request_identifier.ts#L12) 6 | 7 | ## Properties 8 | 9 | ### token? 10 | 11 | > `optional` **token**: `string` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/request\_identifier.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/request_identifier.ts#L13) 14 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: lint 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | lint: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/setup-node@v3 15 | with: 16 | node-version: 20 17 | - name: Install protoc 18 | run: | 19 | sudo apt-get update 20 | sudo apt-get install -y unzip 21 | curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-linux-x86_64.zip 22 | unzip protoc-21.12-linux-x86_64.zip -d protoc21 23 | sudo mv protoc21/bin/protoc /usr/local/bin/ 24 | - run: npm ci 25 | - run: npm run lint -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/ReloadPlaybackParams.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / ReloadPlaybackParams 2 | 3 | # Interface: ReloadPlaybackParams 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/reload\_player\_response.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/reload_player_response.ts#L12) 6 | 7 | ## Properties 8 | 9 | ### token? 10 | 11 | > `optional` **token**: `string` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/reload\_player\_response.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/reload_player_response.ts#L13) 14 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/UstreamerFlags.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / UstreamerFlags 2 | 3 | # Interface: UstreamerFlags 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/innertube\_request.ts:27](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/innertube_request.ts#L27) 6 | 7 | ## Properties 8 | 9 | ### sendVideoPlaybackConfig? 10 | 11 | > `optional` **sendVideoPlaybackConfig**: `boolean` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/innertube\_request.ts:28](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/innertube_request.ts#L28) 14 | -------------------------------------------------------------------------------- /jsr.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@luanrt/googlevideo", 3 | "version": "4.0.4", 4 | "exports": { 5 | "./ump": "./src/exports/ump.ts", 6 | "./sabr-streaming-adapter": "./src/exports/sabr-streaming-adapter.ts", 7 | "./sabr-stream": "./src/exports/sabr-stream.ts", 8 | "./protos": "./src/exports/protos.ts", 9 | "./utils": "./src/exports/utils.ts", 10 | "./shared-types": "./src/types/shared.ts" 11 | }, 12 | "imports": { 13 | "@bufbuild/protobuf": "npm:@bufbuild/protobuf@^2.0.0" 14 | }, 15 | "publish": { 16 | "include": [ 17 | "LICENSE", 18 | "README.md", 19 | "protos/generated/**/*.ts", 20 | "src/**/*.ts" 21 | ], 22 | "exclude": [ 23 | "tests", 24 | "dev-scripts", 25 | "examples" 26 | ] 27 | } 28 | } -------------------------------------------------------------------------------- /docs/api/exports/utils/namespaces/FormatKeyUtils/functions/fromFormat.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../../../README.md) / [exports/utils](../../../README.md) / [FormatKeyUtils](../README.md) / fromFormat 2 | 3 | # Function: fromFormat() 4 | 5 | > **fromFormat**(`format?`): `undefined` \| `string` 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/formatKeyUtils.ts:18](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/formatKeyUtils.ts#L18) 8 | 9 | Creates a format key from a SabrFormat object. 10 | 11 | ## Parameters 12 | 13 | ### format? 14 | 15 | #### itag? 16 | 17 | `number` 18 | 19 | #### xtags? 20 | 21 | `string` 22 | 23 | ## Returns 24 | 25 | `undefined` \| `string` 26 | 27 | A string format key or undefined if format is undefined. 28 | -------------------------------------------------------------------------------- /protos/generated/video_streaming/onesie_header_type.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.7.5 4 | // protoc v5.28.0 5 | // source: video_streaming/onesie_header_type.proto 6 | 7 | /* eslint-disable */ 8 | 9 | export const protobufPackage = "video_streaming"; 10 | 11 | export enum OnesieHeaderType { 12 | ONESIE_PLAYER_RESPONSE = 0, 13 | MEDIA = 1, 14 | MEDIA_DECRYPTION_KEY = 2, 15 | CLEAR_MEDIA = 3, 16 | CLEAR_INIT_SEGMENT = 4, 17 | ACK = 5, 18 | MEDIA_STREAMER_HOSTNAME = 6, 19 | MEDIA_SIZE_HINT = 7, 20 | PLAYER_SERVICE_RESPONSE_PUSH_URL = 8, 21 | LAST_HIGH_PRIORITY_HINT = 9, 22 | STREAM_METADATA = 16, 23 | ENCRYPTED_INNERTUBE_RESPONSE_PART = 25, 24 | UNRECOGNIZED = -1, 25 | } 26 | -------------------------------------------------------------------------------- /protos/video_streaming/innertube_request.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | message InnertubeRequest { 5 | optional bytes context = 1; 6 | optional bytes encrypted_onesie_innertube_request = 2; 7 | optional bytes encrypted_client_key = 5; 8 | optional bytes iv = 6; 9 | optional bytes hmac = 7; 10 | optional string reverse_proxy_config = 9; 11 | optional bool serialize_response_as_json = 10; 12 | optional bool enable_ad_placements_preroll = 13; 13 | optional bool enable_compression = 14; 14 | optional UstreamerFlags ustreamer_flags = 15; 15 | optional bytes unencrypted_onesie_innertube_request = 16; 16 | optional bool use_jsonformatter_to_parse_player_response = 17; 17 | } 18 | 19 | message UstreamerFlags { 20 | optional bool send_video_playback_config = 2; 21 | } -------------------------------------------------------------------------------- /docs/api/exports/utils/namespaces/FormatKeyUtils/functions/getUniqueFormatId.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../../../README.md) / [exports/utils](../../../README.md) / [FormatKeyUtils](../README.md) / getUniqueFormatId 2 | 3 | # Function: getUniqueFormatId() 4 | 5 | > **getUniqueFormatId**(`format`): `string` 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/formatKeyUtils.ts:85](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/formatKeyUtils.ts#L85) 8 | 9 | Generates a unique format ID based on the SabrFormat properties. 10 | 11 | ## Parameters 12 | 13 | ### format 14 | 15 | [`SabrFormat`](../../../../../types/shared/interfaces/SabrFormat.md) 16 | 17 | The SabrFormat object. 18 | 19 | ## Returns 20 | 21 | `string` 22 | 23 | A unique string identifier for the format. 24 | -------------------------------------------------------------------------------- /examples/downloader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "downloader", 3 | "version": "1.0.0", 4 | "description": "", 5 | "type": "module", 6 | "module": "main.js", 7 | "main": "main.js", 8 | "scripts": { 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "bgutils-js": "^3.1.0", 16 | "cli-progress": "^3.12.0", 17 | "fluent-ffmpeg": "^2.1.3", 18 | "googlevideo": "file:../..", 19 | "jsdom": "^25.0.1", 20 | "shaka-player": "^4.11.2", 21 | "youtubei.js": "^16.0.0" 22 | }, 23 | "devDependencies": { 24 | "@types/cli-progress": "^3.11.6", 25 | "@types/fluent-ffmpeg": "^2.1.26", 26 | "@types/jsdom": "^21.1.7", 27 | "typescript": "^5.6.2" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /protos/generated/video_streaming/onesie_proxy_status.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.7.5 4 | // protoc v5.28.0 5 | // source: video_streaming/onesie_proxy_status.proto 6 | 7 | /* eslint-disable */ 8 | 9 | export const protobufPackage = "video_streaming"; 10 | 11 | export enum OnesieProxyStatus { 12 | UNKNOWN = 0, 13 | OK = 1, 14 | DECRYPTION_FAILED = 2, 15 | PARSING_FAILED = 3, 16 | MISSING_X_FORWARDED_FOR = 4, 17 | INVALID_X_FORWARDED_FOR = 5, 18 | INVALID_CONTENT_TYPE = 6, 19 | BACKEND_ERROR = 7, 20 | CLIENT_ERROR = 8, 21 | MISSING_CRYPTER = 9, 22 | RESPONSE_JSON_SERIALIZATION_FAILED = 10, 23 | DECOMPRESSION_FAILED = 11, 24 | JSON_PARSING_FAILED = 12, 25 | UNKNOWN_COMPRESSION_TYPE = 13, 26 | UNRECOGNIZED = -1, 27 | } 28 | -------------------------------------------------------------------------------- /protos/video_streaming/media_header.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | import "misc/common.proto"; 5 | import "video_streaming/time_range.proto"; 6 | 7 | message MediaHeader { 8 | optional uint32 header_id = 1; 9 | optional string video_id = 2; 10 | optional int32 itag = 3; 11 | optional uint64 lmt = 4; 12 | optional string xtags = 5; 13 | optional int64 start_range = 6; 14 | optional .misc.CompressionType compression_algorithm = 7; 15 | optional bool is_init_seg = 8; 16 | optional int32 sequence_number = 9; 17 | optional int64 bitrate_bps = 10; 18 | optional int64 start_ms = 11; 19 | optional int64 duration_ms = 12; 20 | optional .misc.FormatId format_id = 13; 21 | optional int64 content_length = 14; 22 | optional TimeRange time_range = 15; 23 | optional uint64 sequence_lmt = 16; 24 | } 25 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/ReloadPlaybackContext.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / ReloadPlaybackContext 2 | 3 | # Interface: ReloadPlaybackContext 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/reload\_player\_response.ts:16](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/reload_player_response.ts#L16) 6 | 7 | ## Properties 8 | 9 | ### reloadPlaybackParams? 10 | 11 | > `optional` **reloadPlaybackParams**: [`ReloadPlaybackParams`](ReloadPlaybackParams.md) 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/reload\_player\_response.ts:17](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/reload_player_response.ts#L17) 14 | -------------------------------------------------------------------------------- /protos/video_streaming/media_capabilities.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | message MediaCapabilities { 5 | repeated VideoFormatCapability video_format_capabilities = 1; 6 | repeated AudioFormatCapability audio_format_capabilities = 2; 7 | optional int32 hdr_mode_bitmask = 5; 8 | 9 | message VideoFormatCapability { 10 | optional int32 video_codec = 1; 11 | optional int32 max_height = 3; 12 | optional int32 max_width = 4; 13 | optional int32 max_framerate = 11; 14 | optional int32 max_bitrate_bps = 12; 15 | optional bool is_10_bit_supported = 15; 16 | } 17 | 18 | message AudioFormatCapability { 19 | optional int32 audio_codec = 1; 20 | optional int32 num_channels = 2; 21 | optional int32 max_bitrate_bps = 3; 22 | optional int32 spatial_capability_bitmask = 6; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docs/api/exports/utils/namespaces/FormatKeyUtils/functions/createSegmentCacheKeyFromMetadata.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../../../README.md) / [exports/utils](../../../README.md) / [FormatKeyUtils](../README.md) / createSegmentCacheKeyFromMetadata 2 | 3 | # Function: createSegmentCacheKeyFromMetadata() 4 | 5 | > **createSegmentCacheKeyFromMetadata**(`requestMetadata`): `string` 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/formatKeyUtils.ts:61](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/formatKeyUtils.ts#L61) 8 | 9 | Creates a cache key from request metadata. 10 | 11 | ## Parameters 12 | 13 | ### requestMetadata 14 | 15 | [`SabrRequestMetadata`](../../../../sabr-streaming-adapter/interfaces/SabrRequestMetadata.md) 16 | 17 | ## Returns 18 | 19 | `string` 20 | 21 | A string key for caching segments. 22 | -------------------------------------------------------------------------------- /protos/video_streaming/onesie_header.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | import "video_streaming/crypto_params.proto"; 5 | import "video_streaming/onesie_header_type.proto"; 6 | 7 | message OnesieHeader { 8 | message UnknownMessage1 { 9 | optional string video_id = 2; 10 | } 11 | 12 | message UnknownMessage2 { 13 | repeated string itag_denylist = 1; 14 | } 15 | 16 | optional OnesieHeaderType type = 1; 17 | optional string video_id = 2; 18 | optional string itag = 3; 19 | optional CryptoParams crypto_params = 4; 20 | optional uint64 last_modified = 5; 21 | optional int64 expected_media_size_bytes = 7; 22 | repeated string restricted_formats = 11; 23 | optional string xtags = 15; 24 | optional int64 sequence_number = 18; 25 | optional UnknownMessage1 field23 = 23; 26 | optional UnknownMessage2 field34 = 34; 27 | } 28 | -------------------------------------------------------------------------------- /docs/api/exports/utils/namespaces/FormatKeyUtils/functions/fromFormatInitializationMetadata.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../../../README.md) / [exports/utils](../../../README.md) / [FormatKeyUtils](../README.md) / fromFormatInitializationMetadata 2 | 3 | # Function: fromFormatInitializationMetadata() 4 | 5 | > **fromFormatInitializationMetadata**(`formatInitMetadata`): `string` 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/formatKeyUtils.ts:35](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/formatKeyUtils.ts#L35) 8 | 9 | Creates a format key from FormatInitializationMetadata. 10 | 11 | ## Parameters 12 | 13 | ### formatInitMetadata 14 | 15 | [`FormatInitializationMetadata`](../../../../protos/interfaces/FormatInitializationMetadata.md) 16 | 17 | ## Returns 18 | 19 | `string` 20 | 21 | A string format key or undefined if formatId is undefined. 22 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/HttpHeader.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / HttpHeader 2 | 3 | # Interface: HttpHeader 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:181](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L181) 6 | 7 | ## Properties 8 | 9 | ### name? 10 | 11 | > `optional` **name**: `string` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:182](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L182) 14 | 15 | *** 16 | 17 | ### value? 18 | 19 | > `optional` **value**: `string` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:183](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L183) 22 | -------------------------------------------------------------------------------- /docs/api/exports/sabr-streaming-adapter/type-aliases/RequestFilter.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/sabr-streaming-adapter](../README.md) / RequestFilter 2 | 3 | # Type Alias: RequestFilter() 4 | 5 | > **RequestFilter** = (`request`) => `Promise`\<[`PlayerHttpRequest`](../interfaces/PlayerHttpRequest.md) \| `undefined`\> \| [`PlayerHttpRequest`](../interfaces/PlayerHttpRequest.md) \| `undefined` 6 | 7 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:96](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L96) 8 | 9 | ## Parameters 10 | 11 | ### request 12 | 13 | [`PlayerHttpRequest`](../interfaces/PlayerHttpRequest.md) 14 | 15 | ## Returns 16 | 17 | `Promise`\<[`PlayerHttpRequest`](../interfaces/PlayerHttpRequest.md) \| `undefined`\> \| [`PlayerHttpRequest`](../interfaces/PlayerHttpRequest.md) \| `undefined` 18 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/KeyValuePair.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / KeyValuePair 2 | 3 | # Interface: KeyValuePair 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:204](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L204) 6 | 7 | ## Properties 8 | 9 | ### key? 10 | 11 | > `optional` **key**: `string` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:205](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L205) 14 | 15 | *** 16 | 17 | ### value? 18 | 19 | > `optional` **value**: `string` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:206](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L206) 22 | -------------------------------------------------------------------------------- /docs/api/exports/sabr-streaming-adapter/type-aliases/ResponseFilter.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/sabr-streaming-adapter](../README.md) / ResponseFilter 2 | 3 | # Type Alias: ResponseFilter() 4 | 5 | > **ResponseFilter** = (`response`) => `Promise`\<[`PlayerHttpResponse`](../interfaces/PlayerHttpResponse.md) \| `undefined`\> \| [`PlayerHttpResponse`](../interfaces/PlayerHttpResponse.md) \| `undefined` 6 | 7 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:97](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L97) 8 | 9 | ## Parameters 10 | 11 | ### response 12 | 13 | [`PlayerHttpResponse`](../interfaces/PlayerHttpResponse.md) 14 | 15 | ## Returns 16 | 17 | `Promise`\<[`PlayerHttpResponse`](../interfaces/PlayerHttpResponse.md) \| `undefined`\> \| [`PlayerHttpResponse`](../interfaces/PlayerHttpResponse.md) \| `undefined` 18 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/AuthorizedFormat.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / AuthorizedFormat 2 | 3 | # Interface: AuthorizedFormat 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:209](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L209) 6 | 7 | ## Properties 8 | 9 | ### isHdr? 10 | 11 | > `optional` **isHdr**: `boolean` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:211](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L211) 14 | 15 | *** 16 | 17 | ### trackType? 18 | 19 | > `optional` **trackType**: `number` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:210](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L210) 22 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/IdentifierToken.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / IdentifierToken 2 | 3 | # Interface: IdentifierToken 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:199](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L199) 6 | 7 | ## Properties 8 | 9 | ### field5? 10 | 11 | > `optional` **field5**: `number` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:201](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L201) 14 | 15 | *** 16 | 17 | ### requestNumber? 18 | 19 | > `optional` **requestNumber**: `number` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:200](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L200) 22 | -------------------------------------------------------------------------------- /docs/api/exports/utils/namespaces/FormatKeyUtils/functions/createSegmentCacheKey.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../../../README.md) / [exports/utils](../../../README.md) / [FormatKeyUtils](../README.md) / createSegmentCacheKey 2 | 3 | # Function: createSegmentCacheKey() 4 | 5 | > **createSegmentCacheKey**(`mediaHeader`, `format?`): `string` 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/formatKeyUtils.ts:47](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/formatKeyUtils.ts#L47) 8 | 9 | Creates a segment cache key. 10 | 11 | ## Parameters 12 | 13 | ### mediaHeader 14 | 15 | [`MediaHeader`](../../../../protos/interfaces/MediaHeader.md) 16 | 17 | The MediaHeader object. 18 | 19 | ### format? 20 | 21 | [`SabrFormat`](../../../../../types/shared/interfaces/SabrFormat.md) 22 | 23 | Format object (needed for init segments.) 24 | 25 | ## Returns 26 | 27 | `string` 28 | 29 | A string key for caching segments. 30 | -------------------------------------------------------------------------------- /protos/video_streaming/onesie_request.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | import "misc/common.proto"; 5 | import "video_streaming/buffered_range.proto"; 6 | import "video_streaming/client_abr_state.proto"; 7 | import "video_streaming/innertube_request.proto"; 8 | import "video_streaming/streamer_context.proto"; 9 | import "video_streaming/reload_player_response.proto"; 10 | 11 | message OnesieRequest { 12 | repeated string urls = 1; 13 | optional ClientAbrState client_abr_state = 2; 14 | optional InnertubeRequest innertube_request = 3; 15 | optional bytes onesie_ustreamer_config = 4; 16 | optional int32 max_vp9_height = 5; 17 | optional int32 client_display_height = 6; 18 | optional StreamerContext streamer_context = 10; 19 | optional .misc.OnesieRequestTarget request_target = 13; // MLOnesieRequestTarget 20 | repeated BufferedRange buffered_ranges = 14; 21 | optional ReloadPlaybackParams reload_playback_params = 15; 22 | } -------------------------------------------------------------------------------- /docs/api/exports/sabr-streaming-adapter/interfaces/UmpProcessingResult.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/sabr-streaming-adapter](../README.md) / UmpProcessingResult 2 | 3 | # Interface: UmpProcessingResult 4 | 5 | Defined in: [codeberg/googlevideo/src/core/SabrUmpProcessor.ts:33](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/SabrUmpProcessor.ts#L33) 6 | 7 | ## Properties 8 | 9 | ### data? 10 | 11 | > `optional` **data**: `Uint8Array`\<`ArrayBufferLike`\> 12 | 13 | Defined in: [codeberg/googlevideo/src/core/SabrUmpProcessor.ts:34](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/SabrUmpProcessor.ts#L34) 14 | 15 | *** 16 | 17 | ### done 18 | 19 | > **done**: `boolean` 20 | 21 | Defined in: [codeberg/googlevideo/src/core/SabrUmpProcessor.ts:35](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/SabrUmpProcessor.ts#L35) 22 | -------------------------------------------------------------------------------- /protos/video_streaming/buffered_range.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | import "misc/common.proto"; 5 | import "video_streaming/time_range.proto"; 6 | 7 | message BufferedRange { 8 | message UnknownMessage1 { 9 | message UnknownInnerMessage { 10 | optional string video_id = 1; 11 | optional uint64 lmt = 2; 12 | } 13 | repeated UnknownInnerMessage field1 = 1; 14 | } 15 | 16 | message UnknownMessage2 { 17 | optional int32 field1 = 1; 18 | optional int32 field2 = 2; 19 | optional int32 field3 = 3; 20 | } 21 | 22 | required .misc.FormatId format_id = 1; 23 | required int64 start_time_ms = 2; 24 | required int64 duration_ms = 3; 25 | required int32 start_segment_index = 4; 26 | required int32 end_segment_index = 5; 27 | optional TimeRange time_range = 6; 28 | optional UnknownMessage1 field9 = 9; 29 | optional UnknownMessage2 field11 = 11; 30 | optional UnknownMessage2 field12 = 12; 31 | } -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/SabrError.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / SabrError 2 | 3 | # Interface: SabrError 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_error.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_error.ts#L12) 6 | 7 | ## Properties 8 | 9 | ### code? 10 | 11 | > `optional` **code**: `number` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_error.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_error.ts#L14) 14 | 15 | *** 16 | 17 | ### type? 18 | 19 | > `optional` **type**: `string` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_error.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_error.ts#L13) 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.yml: -------------------------------------------------------------------------------- 1 | name: Question 2 | description: Use this template to ask a question about the project 3 | labels: [question] 4 | body: 5 | 6 | - type: textarea 7 | id: question 8 | attributes: 9 | label: Question 10 | placeholder: What do you want to know? 11 | validations: 12 | required: true 13 | 14 | - type: textarea 15 | id: other-details 16 | attributes: 17 | label: Other details 18 | placeholder: | 19 | Additional details and attachments. 20 | 21 | - type: checkboxes 22 | id: checklist 23 | attributes: 24 | label: Checklist 25 | options: 26 | - label: I am running the latest version. 27 | required: true 28 | - label: I checked the documentation and found no answer. 29 | required: true 30 | - label: I have searched the existing issues and made sure this is not a duplicate. 31 | required: true 32 | - label: I have provided sufficient information. 33 | required: true -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Use this template to suggest new features 3 | labels: [enhancement] 4 | body: 5 | 6 | - type: textarea 7 | id: feature-description 8 | attributes: 9 | label: Describe your suggestion 10 | placeholder: How would it work? 11 | validations: 12 | required: true 13 | 14 | - type: textarea 15 | id: other-details 16 | attributes: 17 | label: Other details 18 | placeholder: | 19 | Additional details and attachments. 20 | 21 | - type: checkboxes 22 | id: checklist 23 | attributes: 24 | label: Checklist 25 | options: 26 | - label: I am running the latest version. 27 | required: true 28 | - label: I checked the documentation and found no answer. 29 | required: true 30 | - label: I have searched the existing issues and made sure this is not a duplicate. 31 | required: true 32 | - label: I have provided sufficient information. 33 | required: true -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/PlaybackAuthorization.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / PlaybackAuthorization 2 | 3 | # Interface: PlaybackAuthorization 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:214](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L214) 6 | 7 | ## Properties 8 | 9 | ### authorizedFormats 10 | 11 | > **authorizedFormats**: [`AuthorizedFormat`](AuthorizedFormat.md)[] 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:215](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L215) 14 | 15 | *** 16 | 17 | ### sabrLicenseConstraint? 18 | 19 | > `optional` **sabrLicenseConstraint**: `Uint8Array`\<`ArrayBufferLike`\> 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:216](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L216) 22 | -------------------------------------------------------------------------------- /examples/sabr-shaka-example/scripts/patchShaka.mjs: -------------------------------------------------------------------------------- 1 | import { readFile, appendFile } from 'node:fs/promises'; 2 | import path from 'node:path'; 3 | import * as url from 'node:url'; 4 | 5 | const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); 6 | 7 | async function main() { 8 | const fileNames = [ 'shaka-player.ui.d.ts', 'shaka-player.ui.debug.d.ts' ]; 9 | 10 | for (const filename of fileNames) { 11 | await fixTypes(filename); 12 | } 13 | } 14 | 15 | async function fixTypes(filename) { 16 | const filePath = path.join(__dirname, '..', 'node_modules', 'shaka-player', 'dist', filename); 17 | 18 | const shakaTs = await readFile(filePath, 'utf-8'); 19 | 20 | if (!shakaTs.includes('export default shaka')) { 21 | await appendFile(filePath, 'export default shaka;'); 22 | console.log(`[PatchShaka] Fixed types in ${filename}`); 23 | } else { 24 | console.log(`[PatchShaka] No changes needed in ${filename}`); 25 | } 26 | } 27 | 28 | main().catch(() => { 29 | console.error('[PatchShaka]', 'Failed to patch shaka-player'); 30 | }); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 LuanRT 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Run Tests 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | node-version: [20.x] 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v4 20 | 21 | - name: Use Node.js ${{ matrix.node-version }} 22 | uses: actions/setup-node@v4 23 | with: 24 | node-version: ${{ matrix.node-version }} 25 | cache: 'npm' 26 | 27 | - name: Install protoc 28 | run: | 29 | sudo apt-get update 30 | sudo apt-get install -y unzip 31 | curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-linux-x86_64.zip 32 | unzip protoc-21.12-linux-x86_64.zip -d protoc21 33 | sudo mv protoc21/bin/protoc /usr/local/bin/ 34 | 35 | - name: Install dependencies 36 | run: npm install 37 | 38 | - name: Run tests 39 | run: npm test 40 | -------------------------------------------------------------------------------- /docs/api/exports/sabr-streaming-adapter/README.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../README.md) / exports/sabr-streaming-adapter 2 | 3 | # exports/sabr-streaming-adapter 4 | 5 | This module contains the core classes, types, and utilities required to integrate YouTube's SABR streaming protocol 6 | into a media player. 7 | 8 | ## Classes 9 | 10 | - [SabrStreamingAdapter](classes/SabrStreamingAdapter.md) 11 | - [SabrUmpProcessor](classes/SabrUmpProcessor.md) 12 | 13 | ## Interfaces 14 | 15 | - [PlayerHttpRequest](interfaces/PlayerHttpRequest.md) 16 | - [PlayerHttpResponse](interfaces/PlayerHttpResponse.md) 17 | - [RequestSegment](interfaces/RequestSegment.md) 18 | - [SabrOptions](interfaces/SabrOptions.md) 19 | - [SabrPlayerAdapter](interfaces/SabrPlayerAdapter.md) 20 | - [SabrRequestMetadata](interfaces/SabrRequestMetadata.md) 21 | - [UmpProcessingResult](interfaces/UmpProcessingResult.md) 22 | 23 | ## Type Aliases 24 | 25 | - [RequestFilter](type-aliases/RequestFilter.md) 26 | - [ResponseFilter](type-aliases/ResponseFilter.md) 27 | 28 | ## Variables 29 | 30 | - [SABR\_CONSTANTS](variables/SABR_CONSTANTS.md) 31 | -------------------------------------------------------------------------------- /docs/api/exports/utils/interfaces/CacheEntry.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/utils](../README.md) / CacheEntry 2 | 3 | # Interface: CacheEntry 4 | 5 | Defined in: [codeberg/googlevideo/src/utils/CacheManager.ts:3](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/CacheManager.ts#L3) 6 | 7 | ## Properties 8 | 9 | ### data 10 | 11 | > **data**: `Uint8Array` 12 | 13 | Defined in: [codeberg/googlevideo/src/utils/CacheManager.ts:4](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/CacheManager.ts#L4) 14 | 15 | *** 16 | 17 | ### size 18 | 19 | > **size**: `number` 20 | 21 | Defined in: [codeberg/googlevideo/src/utils/CacheManager.ts:6](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/CacheManager.ts#L6) 22 | 23 | *** 24 | 25 | ### timestamp 26 | 27 | > **timestamp**: `number` 28 | 29 | Defined in: [codeberg/googlevideo/src/utils/CacheManager.ts:5](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/CacheManager.ts#L5) 30 | -------------------------------------------------------------------------------- /docs/api/exports/sabr-streaming-adapter/interfaces/RequestSegment.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/sabr-streaming-adapter](../README.md) / RequestSegment 2 | 3 | # Interface: RequestSegment 4 | 5 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:91](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L91) 6 | 7 | ## Properties 8 | 9 | ### getStartTime() 10 | 11 | > **getStartTime**: () => `null` \| `number` 12 | 13 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:92](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L92) 14 | 15 | #### Returns 16 | 17 | `null` \| `number` 18 | 19 | *** 20 | 21 | ### isInit() 22 | 23 | > **isInit**: () => `boolean` 24 | 25 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:93](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L93) 26 | 27 | #### Returns 28 | 29 | `boolean` 30 | -------------------------------------------------------------------------------- /docs/api/exports/utils/enumerations/EnabledTrackTypes.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/utils](../README.md) / EnabledTrackTypes 2 | 3 | # Enumeration: EnabledTrackTypes 4 | 5 | Defined in: [codeberg/googlevideo/src/utils/shared.ts:5](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/shared.ts#L5) 6 | 7 | ## Enumeration Members 8 | 9 | ### AUDIO\_ONLY 10 | 11 | > **AUDIO\_ONLY**: `1` 12 | 13 | Defined in: [codeberg/googlevideo/src/utils/shared.ts:7](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/shared.ts#L7) 14 | 15 | *** 16 | 17 | ### VIDEO\_AND\_AUDIO 18 | 19 | > **VIDEO\_AND\_AUDIO**: `0` 20 | 21 | Defined in: [codeberg/googlevideo/src/utils/shared.ts:6](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/shared.ts#L6) 22 | 23 | *** 24 | 25 | ### VIDEO\_ONLY 26 | 27 | > **VIDEO\_ONLY**: `2` 28 | 29 | Defined in: [codeberg/googlevideo/src/utils/shared.ts:8](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/shared.ts#L8) 30 | -------------------------------------------------------------------------------- /docs/api/types/shared/type-aliases/Part.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [types/shared](../README.md) / Part 2 | 3 | # Type Alias: Part 4 | 5 | > **Part** = `object` 6 | 7 | Defined in: [codeberg/googlevideo/src/types/shared.ts:8](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/shared.ts#L8) 8 | 9 | ## Properties 10 | 11 | ### data 12 | 13 | > **data**: [`CompositeBuffer`](../../../exports/ump/classes/CompositeBuffer.md) 14 | 15 | Defined in: [codeberg/googlevideo/src/types/shared.ts:11](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/shared.ts#L11) 16 | 17 | *** 18 | 19 | ### size 20 | 21 | > **size**: `number` 22 | 23 | Defined in: [codeberg/googlevideo/src/types/shared.ts:10](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/shared.ts#L10) 24 | 25 | *** 26 | 27 | ### type 28 | 29 | > **type**: `number` 30 | 31 | Defined in: [codeberg/googlevideo/src/types/shared.ts:9](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/shared.ts#L9) 32 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/StreamProtectionStatus.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / StreamProtectionStatus 2 | 3 | # Interface: StreamProtectionStatus 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/stream\_protection\_status.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/stream_protection_status.ts#L12) 6 | 7 | ## Properties 8 | 9 | ### maxRetries? 10 | 11 | > `optional` **maxRetries**: `number` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/stream\_protection\_status.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/stream_protection_status.ts#L14) 14 | 15 | *** 16 | 17 | ### status? 18 | 19 | > `optional` **status**: `number` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/stream\_protection\_status.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/stream_protection_status.ts#L13) 22 | -------------------------------------------------------------------------------- /docs/api/exports/utils/functions/isGoogleVideoURL.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/utils](../README.md) / isGoogleVideoURL 2 | 3 | # Function: isGoogleVideoURL() 4 | 5 | > **isGoogleVideoURL**(`url`): `boolean` 6 | 7 | Defined in: [codeberg/googlevideo/src/utils/shared.ts:23](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/shared.ts#L23) 8 | 9 | Determines if a given URL is a Google video URL, specifically for YouTube or SABR-related content. 10 | 11 | ## Parameters 12 | 13 | ### url 14 | 15 | `string` 16 | 17 | The URL to check. 18 | 19 | The function checks the following conditions: 20 | 1. If the URL starts with the `sabr://` protocol, it is considered a Google video URL. 21 | 2. If the URL ends with `/videoplayback`, it parses the query parameters to check for specific keys 22 | (`source=youtube`, `sabr`, `lsig`, or `expire`) that indicate a Google video URL. 23 | 3. If the URL contains `/videoplayback/` (e.g., for live or post-live content), it checks the path 24 | segments for specific keywords (`videoplayback`, `sabr`, `lsig`, or `expire`). 25 | 26 | ## Returns 27 | 28 | `boolean` 29 | -------------------------------------------------------------------------------- /docs/api/exports/sabr-streaming-adapter/variables/SABR_CONSTANTS.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/sabr-streaming-adapter](../README.md) / SABR\_CONSTANTS 2 | 3 | # Variable: SABR\_CONSTANTS 4 | 5 | > `const` **SABR\_CONSTANTS**: `object` 6 | 7 | Defined in: [codeberg/googlevideo/src/core/SabrStreamingAdapter.ts:49](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/SabrStreamingAdapter.ts#L49) 8 | 9 | ## Type declaration 10 | 11 | ### DEFAULT\_OPTIONS 12 | 13 | > `readonly` **DEFAULT\_OPTIONS**: `object` 14 | 15 | #### DEFAULT\_OPTIONS.enableCaching 16 | 17 | > `readonly` **enableCaching**: `true` = `true` 18 | 19 | #### DEFAULT\_OPTIONS.enableVerboseRequestLogging 20 | 21 | > `readonly` **enableVerboseRequestLogging**: `false` = `false` 22 | 23 | #### DEFAULT\_OPTIONS.maxCacheAgeSeconds 24 | 25 | > `readonly` **maxCacheAgeSeconds**: `300` = `300` 26 | 27 | #### DEFAULT\_OPTIONS.maxCacheSizeMB 28 | 29 | > `readonly` **maxCacheSizeMB**: `3` = `3` 30 | 31 | ### KEY\_PARAM 32 | 33 | > `readonly` **KEY\_PARAM**: `"key"` = `'key'` 34 | 35 | ### PROTOCOL 36 | 37 | > `readonly` **PROTOCOL**: `"sabr:"` = `'sabr:'` 38 | -------------------------------------------------------------------------------- /docs/api/exports/utils/README.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../README.md) / exports/utils 2 | 3 | # exports/utils 4 | 5 | This module contains general utilities. 6 | 7 | ## Namespaces 8 | 9 | - [FormatKeyUtils](namespaces/FormatKeyUtils/README.md) 10 | 11 | ## Enumerations 12 | 13 | - [EnabledTrackTypes](enumerations/EnabledTrackTypes.md) 14 | - [LogLevel](enumerations/LogLevel.md) 15 | 16 | ## Classes 17 | 18 | - [CacheManager](classes/CacheManager.md) 19 | - [EventEmitterLike](classes/EventEmitterLike.md) 20 | - [Logger](classes/Logger.md) 21 | - [RequestMetadataManager](classes/RequestMetadataManager.md) 22 | - [SabrAdapterError](classes/SabrAdapterError.md) 23 | 24 | ## Interfaces 25 | 26 | - [CacheEntry](interfaces/CacheEntry.md) 27 | 28 | ## Variables 29 | 30 | - [MAX\_INT32\_VALUE](variables/MAX_INT32_VALUE.md) 31 | 32 | ## Functions 33 | 34 | - [base64ToU8](functions/base64ToU8.md) 35 | - [buildSabrFormat](functions/buildSabrFormat.md) 36 | - [concatenateChunks](functions/concatenateChunks.md) 37 | - [isGoogleVideoURL](functions/isGoogleVideoURL.md) 38 | - [parseRangeHeader](functions/parseRangeHeader.md) 39 | - [u8ToBase64](functions/u8ToBase64.md) 40 | - [wait](functions/wait.md) 41 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/FormatId.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / FormatId 2 | 3 | # Interface: FormatId 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:186](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L186) 6 | 7 | ## Properties 8 | 9 | ### itag? 10 | 11 | > `optional` **itag**: `number` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:187](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L187) 14 | 15 | *** 16 | 17 | ### lastModified? 18 | 19 | > `optional` **lastModified**: `number` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:188](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L188) 22 | 23 | *** 24 | 25 | ### xtags? 26 | 27 | > `optional` **xtags**: `string` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:189](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L189) 30 | -------------------------------------------------------------------------------- /protos/video_streaming/sabr_context_update.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | message SabrContextUpdate { 5 | enum SabrContextScope { 6 | UNKNOWN = 0; 7 | PLAYBACK = 1; 8 | REQUEST = 2; 9 | WATCH_ENDPOINT = 3; 10 | CONTENT_ADS = 4; 11 | } 12 | 13 | enum SabrContextWritePolicy { 14 | UNSPECIFIED = 0; 15 | OVERWRITE = 1; 16 | KEEP_EXISTING = 2; 17 | } 18 | 19 | optional int32 type = 1; 20 | optional SabrContextScope scope = 2; 21 | 22 | optional bytes value = 3; 23 | optional bool send_by_default = 4; 24 | optional SabrContextWritePolicy write_policy = 5; 25 | } 26 | 27 | // For debugging 28 | message SabrContextValue { 29 | message ContentInfo { 30 | optional string content_id = 1; // Looks like a content identifier of some sort "mQxOaLekHJ2f-LAPtq3hwQ4" 31 | optional int32 content_type = 2; // Value of 1 observed (unsure what it truly means/is) 32 | } 33 | 34 | message TimingInfo { 35 | optional int64 timestamp_ms = 1; 36 | optional int32 duration_ms = 2; 37 | optional ContentInfo content = 3; 38 | } 39 | 40 | optional TimingInfo timing = 1; 41 | optional bytes signature = 2; 42 | optional int32 field5 = 5; 43 | } 44 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/PlaybackStartPolicy.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / PlaybackStartPolicy 2 | 3 | # Interface: PlaybackStartPolicy 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/playback\_start\_policy.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/playback_start_policy.ts#L12) 6 | 7 | ## Properties 8 | 9 | ### resumeMinReadaheadPolicy? 10 | 11 | > `optional` **resumeMinReadaheadPolicy**: `PlaybackStartPolicy_ReadaheadPolicy` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/playback\_start\_policy.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/playback_start_policy.ts#L14) 14 | 15 | *** 16 | 17 | ### startMinReadaheadPolicy? 18 | 19 | > `optional` **startMinReadaheadPolicy**: `PlaybackStartPolicy_ReadaheadPolicy` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/playback\_start\_policy.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/playback_start_policy.ts#L13) 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # YouTube player cache directory 2 | cache/ 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # WebStorm 14 | .idea/ 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | *.lcov 19 | 20 | # Dependency directories 21 | node_modules/ 22 | jspm_packages/ 23 | 24 | # TypeScript cache 25 | *.tsbuildinfo 26 | 27 | # Optional npm cache directory 28 | .npm 29 | 30 | # Optional eslint cache 31 | .eslintcache 32 | 33 | # Optional stylelint cache 34 | .stylelintcache 35 | 36 | # Output of 'npm pack' 37 | *.tgz 38 | 39 | # Yarn Integrity file 40 | .yarn-integrity 41 | 42 | # dotenv environment variable files 43 | .env 44 | .env.development.local 45 | .env.test.local 46 | .env.production.local 47 | .env.local 48 | 49 | # yarn v2 50 | .yarn/cache 51 | .yarn/unplugged 52 | .yarn/build-state.yml 53 | .yarn/install-state.gz 54 | .pnp.* 55 | 56 | # pnpm 57 | .pnpm-debug.log* 58 | pnpm-lock.yaml 59 | 60 | # Downloaded assets 61 | *.mp4 62 | *.webm 63 | *.mkv 64 | 65 | # Temporary files for testing 66 | tmp/ 67 | 68 | # Build output 69 | dist/ 70 | bundle/*.js.* 71 | bundle/*.js 72 | bundle/*.cjs 73 | bundle/*.cjs.* 74 | deno/ 75 | 76 | # MacOS 77 | .DS_Store 78 | -------------------------------------------------------------------------------- /examples/sabr-shaka-example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SABR Shaka Player Example 7 | 16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 | 24 |
25 |
Ready. Enter a video ID and click "Load Video".
26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /examples/sabr-shaka-example/README.md: -------------------------------------------------------------------------------- 1 | # SABR + Shaka Player Example 2 | 3 | This project provides a minimal, self-contained example of how to use [Shaka Player](https://shaka-player-demo.appspot.com/) with the `SabrStreamingAdapter` from the [googlevideo](https://github.com/LuanRT/googlevideo) library to play YouTube videos. 4 | 5 | ## Note 6 | 7 | For an implementation that includes a proper user interface, advanced features, and best practices, please see the main **[Kira](https://github.com/LuanRT/kira)** project this example is derived from. 8 | 9 | Things **not included** in this minimal example but available in the main project: 10 | * A proper watch page and user interface. 11 | * Support for DRM-protected content. 12 | * A recommendation system and persistent user sessions. 13 | * Saving and resuming playback position. 14 | * Advanced error handling and UI feedback. 15 | * A video/audio downloader. 16 | 17 | ## How to Run 18 | 19 | 1. **Install dependencies:** 20 | ```bash 21 | npm install 22 | ``` 23 | 24 | 2. **Start the development server:** 25 | ```bash 26 | npm run dev 27 | ``` 28 | 29 | 3. Open your browser and navigate to the local URL provided by Vite (e.g., `http://localhost:5173`). 30 | 31 | ## License 32 | Distributed under the [MIT](../../LICENSE) License. -------------------------------------------------------------------------------- /docs/api/exports/sabr-stream/interfaces/InitializedFormat.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/sabr-stream](../README.md) / InitializedFormat 2 | 3 | # Interface: InitializedFormat 4 | 5 | Defined in: [codeberg/googlevideo/src/core/SabrStream.ts:57](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/SabrStream.ts#L57) 6 | 7 | ## Properties 8 | 9 | ### downloadedSegments 10 | 11 | > **downloadedSegments**: `Map`\<`number`, `Segment`\> 12 | 13 | Defined in: [codeberg/googlevideo/src/core/SabrStream.ts:59](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/SabrStream.ts#L59) 14 | 15 | *** 16 | 17 | ### formatInitializationMetadata 18 | 19 | > **formatInitializationMetadata**: [`FormatInitializationMetadata`](../../protos/interfaces/FormatInitializationMetadata.md) 20 | 21 | Defined in: [codeberg/googlevideo/src/core/SabrStream.ts:58](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/SabrStream.ts#L58) 22 | 23 | *** 24 | 25 | ### lastMediaHeaders 26 | 27 | > **lastMediaHeaders**: [`MediaHeader`](../../protos/interfaces/MediaHeader.md)[] 28 | 29 | Defined in: [codeberg/googlevideo/src/core/SabrStream.ts:60](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/SabrStream.ts#L60) 30 | -------------------------------------------------------------------------------- /docs/api/exports/ump/classes/UmpWriter.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/ump](../README.md) / UmpWriter 2 | 3 | # Class: UmpWriter 4 | 5 | Defined in: [codeberg/googlevideo/src/core/UmpWriter.ts:6](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/UmpWriter.ts#L6) 6 | 7 | A serialization module that encodes data into the UMP binary format with proper type and size encoding. 8 | 9 | ## Constructors 10 | 11 | ### Constructor 12 | 13 | > **new UmpWriter**(`compositeBuffer`): `UmpWriter` 14 | 15 | Defined in: [codeberg/googlevideo/src/core/UmpWriter.ts:7](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/UmpWriter.ts#L7) 16 | 17 | #### Parameters 18 | 19 | ##### compositeBuffer 20 | 21 | [`CompositeBuffer`](CompositeBuffer.md) 22 | 23 | #### Returns 24 | 25 | `UmpWriter` 26 | 27 | ## Methods 28 | 29 | ### write() 30 | 31 | > **write**(`partType`, `partData`): `void` 32 | 33 | Defined in: [codeberg/googlevideo/src/core/UmpWriter.ts:16](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/UmpWriter.ts#L16) 34 | 35 | Writes a part to the buffer. 36 | 37 | #### Parameters 38 | 39 | ##### partType 40 | 41 | `number` 42 | 43 | The type of the part. 44 | 45 | ##### partData 46 | 47 | `Uint8Array` 48 | 49 | The data of the part. 50 | 51 | #### Returns 52 | 53 | `void` 54 | -------------------------------------------------------------------------------- /docs/api/exports/protos/enumerations/CompressionType.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / CompressionType 2 | 3 | # Enumeration: CompressionType 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L12) 6 | 7 | ## Enumeration Members 8 | 9 | ### BROTLI 10 | 11 | > **BROTLI**: `2` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:15](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L15) 14 | 15 | *** 16 | 17 | ### GZIP 18 | 19 | > **GZIP**: `1` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L14) 22 | 23 | *** 24 | 25 | ### UNKNOWN 26 | 27 | > **UNKNOWN**: `0` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L13) 30 | 31 | *** 32 | 33 | ### UNRECOGNIZED 34 | 35 | > **UNRECOGNIZED**: `-1` 36 | 37 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:16](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L16) 38 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/CryptoParams.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / CryptoParams 2 | 3 | # Interface: CryptoParams 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/crypto\_params.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/crypto_params.ts#L13) 6 | 7 | ## Properties 8 | 9 | ### compressionType? 10 | 11 | > `optional` **compressionType**: [`CompressionType`](../enumerations/CompressionType.md) 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/crypto\_params.ts:16](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/crypto_params.ts#L16) 14 | 15 | *** 16 | 17 | ### hmac? 18 | 19 | > `optional` **hmac**: `Uint8Array`\<`ArrayBufferLike`\> 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/crypto\_params.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/crypto_params.ts#L14) 22 | 23 | *** 24 | 25 | ### iv? 26 | 27 | > `optional` **iv**: `Uint8Array`\<`ArrayBufferLike`\> 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/crypto\_params.ts:15](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/crypto_params.ts#L15) 30 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/FormatSelectionConfig.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / FormatSelectionConfig 2 | 3 | # Interface: FormatSelectionConfig 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/format\_selection\_config.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/format_selection_config.ts#L12) 6 | 7 | ## Properties 8 | 9 | ### itags 10 | 11 | > **itags**: `number`[] 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/format\_selection\_config.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/format_selection_config.ts#L13) 14 | 15 | *** 16 | 17 | ### resolution? 18 | 19 | > `optional` **resolution**: `number` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/format\_selection\_config.ts:15](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/format_selection_config.ts#L15) 22 | 23 | *** 24 | 25 | ### videoId? 26 | 27 | > `optional` **videoId**: `string` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/format\_selection\_config.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/format_selection_config.ts#L14) 30 | -------------------------------------------------------------------------------- /docs/api/exports/protos/enumerations/NetworkMeteredState.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / NetworkMeteredState 2 | 3 | # Enumeration: NetworkMeteredState 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:53](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L53) 6 | 7 | ## Enumeration Members 8 | 9 | ### METERED 10 | 11 | > **METERED**: `2` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:56](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L56) 14 | 15 | *** 16 | 17 | ### UNKNOWN 18 | 19 | > **UNKNOWN**: `0` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:54](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L54) 22 | 23 | *** 24 | 25 | ### UNMETERED 26 | 27 | > **UNMETERED**: `1` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:55](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L55) 30 | 31 | *** 32 | 33 | ### UNRECOGNIZED 34 | 35 | > **UNRECOGNIZED**: `-1` 36 | 37 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:57](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L57) 38 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/Range.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / Range 2 | 3 | # Interface: Range 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:192](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L192) 6 | 7 | ## Properties 8 | 9 | ### end? 10 | 11 | > `optional` **end**: `number` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:196](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L196) 14 | 15 | *** 16 | 17 | ### legacyEnd? 18 | 19 | > `optional` **legacyEnd**: `number` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:194](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L194) 22 | 23 | *** 24 | 25 | ### legacyStart? 26 | 27 | > `optional` **legacyStart**: `number` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:193](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L193) 30 | 31 | *** 32 | 33 | ### start? 34 | 35 | > `optional` **start**: `number` 36 | 37 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:195](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L195) 38 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/SabrContextValue.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / SabrContextValue 2 | 3 | # Interface: SabrContextValue 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:37](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L37) 6 | 7 | For debugging 8 | 9 | ## Properties 10 | 11 | ### field5? 12 | 13 | > `optional` **field5**: `number` 14 | 15 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:40](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L40) 16 | 17 | *** 18 | 19 | ### signature? 20 | 21 | > `optional` **signature**: `Uint8Array`\<`ArrayBufferLike`\> 22 | 23 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:39](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L39) 24 | 25 | *** 26 | 27 | ### timing? 28 | 29 | > `optional` **timing**: `SabrContextValue_TimingInfo` 30 | 31 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:38](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L38) 32 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/RequestCancellationPolicy.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / RequestCancellationPolicy 2 | 3 | # Interface: RequestCancellationPolicy 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/request\_cancellation\_policy.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/request_cancellation_policy.ts#L12) 6 | 7 | ## Properties 8 | 9 | ### items 10 | 11 | > **items**: `RequestCancellationPolicy_Item`[] 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/request\_cancellation\_policy.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/request_cancellation_policy.ts#L14) 14 | 15 | *** 16 | 17 | ### jq? 18 | 19 | > `optional` **jq**: `number` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/request\_cancellation\_policy.ts:15](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/request_cancellation_policy.ts#L15) 22 | 23 | *** 24 | 25 | ### N0? 26 | 27 | > `optional` **N0**: `number` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/request\_cancellation\_policy.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/request_cancellation_policy.ts#L13) 30 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/SabrContextSendingPolicy.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / SabrContextSendingPolicy 2 | 3 | # Interface: SabrContextSendingPolicy 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_sending\_policy.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_sending_policy.ts#L12) 6 | 7 | ## Properties 8 | 9 | ### discardPolicy 10 | 11 | > **discardPolicy**: `number`[] 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_sending\_policy.ts:15](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_sending_policy.ts#L15) 14 | 15 | *** 16 | 17 | ### startPolicy 18 | 19 | > **startPolicy**: `number`[] 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_sending\_policy.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_sending_policy.ts#L13) 22 | 23 | *** 24 | 25 | ### stopPolicy 26 | 27 | > **stopPolicy**: `number`[] 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_sending\_policy.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_sending_policy.ts#L14) 30 | -------------------------------------------------------------------------------- /examples/downloader/utils/webpo-helper.ts: -------------------------------------------------------------------------------- 1 | import { BG, type BgConfig } from 'bgutils-js'; 2 | import { JSDOM } from 'jsdom'; 3 | 4 | export async function generateWebPoToken(contentBinding: string) { 5 | const requestKey = 'O43z0dpjhgX20SCx4KAo'; 6 | 7 | if (!contentBinding) 8 | throw new Error('Could not get visitor data'); 9 | 10 | const dom = new JSDOM(); 11 | 12 | Object.assign(globalThis, { 13 | window: dom.window, 14 | document: dom.window.document 15 | }); 16 | 17 | const bgConfig: BgConfig = { 18 | fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => fetch(input, init), 19 | globalObj: globalThis, 20 | identifier: contentBinding, 21 | requestKey 22 | }; 23 | 24 | const bgChallenge = await BG.Challenge.create(bgConfig); 25 | 26 | if (!bgChallenge) 27 | throw new Error('Could not get challenge'); 28 | 29 | const interpreterJavascript = bgChallenge.interpreterJavascript.privateDoNotAccessOrElseSafeScriptWrappedValue; 30 | 31 | if (interpreterJavascript) { 32 | new Function(interpreterJavascript)(); 33 | } else throw new Error('Could not load VM'); 34 | 35 | const poTokenResult = await BG.PoToken.generate({ 36 | program: bgChallenge.program, 37 | globalName: bgChallenge.globalName, 38 | bgConfig 39 | }); 40 | 41 | const placeholderPoToken = BG.PoToken.generatePlaceholder(contentBinding); 42 | 43 | return { 44 | visitorData: contentBinding, 45 | placeholderPoToken, 46 | poToken: poTokenResult.poToken, 47 | }; 48 | } -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/MediaCapabilities.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / MediaCapabilities 2 | 3 | # Interface: MediaCapabilities 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/media\_capabilities.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/media_capabilities.ts#L12) 6 | 7 | ## Properties 8 | 9 | ### audioFormatCapabilities 10 | 11 | > **audioFormatCapabilities**: `MediaCapabilities_AudioFormatCapability`[] 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/media\_capabilities.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/media_capabilities.ts#L14) 14 | 15 | *** 16 | 17 | ### hdrModeBitmask? 18 | 19 | > `optional` **hdrModeBitmask**: `number` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/media\_capabilities.ts:15](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/media_capabilities.ts#L15) 22 | 23 | *** 24 | 25 | ### videoFormatCapabilities 26 | 27 | > **videoFormatCapabilities**: `MediaCapabilities_VideoFormatCapability`[] 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/media\_capabilities.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/media_capabilities.ts#L13) 30 | -------------------------------------------------------------------------------- /docs/api/exports/utils/enumerations/LogLevel.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/utils](../README.md) / LogLevel 2 | 3 | # Enumeration: LogLevel 4 | 5 | Defined in: [codeberg/googlevideo/src/utils/Logger.ts:1](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/Logger.ts#L1) 6 | 7 | ## Enumeration Members 8 | 9 | ### ALL 10 | 11 | > **ALL**: `99` 12 | 13 | Defined in: [codeberg/googlevideo/src/utils/Logger.ts:7](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/Logger.ts#L7) 14 | 15 | *** 16 | 17 | ### DEBUG 18 | 19 | > **DEBUG**: `4` 20 | 21 | Defined in: [codeberg/googlevideo/src/utils/Logger.ts:6](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/Logger.ts#L6) 22 | 23 | *** 24 | 25 | ### ERROR 26 | 27 | > **ERROR**: `1` 28 | 29 | Defined in: [codeberg/googlevideo/src/utils/Logger.ts:3](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/Logger.ts#L3) 30 | 31 | *** 32 | 33 | ### INFO 34 | 35 | > **INFO**: `3` 36 | 37 | Defined in: [codeberg/googlevideo/src/utils/Logger.ts:5](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/Logger.ts#L5) 38 | 39 | *** 40 | 41 | ### NONE 42 | 43 | > **NONE**: `0` 44 | 45 | Defined in: [codeberg/googlevideo/src/utils/Logger.ts:2](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/Logger.ts#L2) 46 | 47 | *** 48 | 49 | ### WARN 50 | 51 | > **WARN**: `2` 52 | 53 | Defined in: [codeberg/googlevideo/src/utils/Logger.ts:4](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/Logger.ts#L4) 54 | -------------------------------------------------------------------------------- /docs/api/exports/protos/enumerations/SabrContextWritePolicy.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / SabrContextWritePolicy 2 | 3 | # Enumeration: SabrContextWritePolicy 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:29](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L29) 6 | 7 | ## Enumeration Members 8 | 9 | ### KEEP\_EXISTING 10 | 11 | > **KEEP\_EXISTING**: `2` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:32](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L32) 14 | 15 | *** 16 | 17 | ### OVERWRITE 18 | 19 | > **OVERWRITE**: `1` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:31](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L31) 22 | 23 | *** 24 | 25 | ### UNRECOGNIZED 26 | 27 | > **UNRECOGNIZED**: `-1` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:33](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L33) 30 | 31 | *** 32 | 33 | ### UNSPECIFIED 34 | 35 | > **UNSPECIFIED**: `0` 36 | 37 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:30](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L30) 38 | -------------------------------------------------------------------------------- /docs/api/exports/protos/enumerations/VideoQualitySetting.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / VideoQualitySetting 2 | 3 | # Enumeration: VideoQualitySetting 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:28](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L28) 6 | 7 | ## Enumeration Members 8 | 9 | ### ADVANCED\_MENU 10 | 11 | > **ADVANCED\_MENU**: `3` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:32](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L32) 14 | 15 | *** 16 | 17 | ### DATA\_SAVER 18 | 19 | > **DATA\_SAVER**: `2` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:31](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L31) 22 | 23 | *** 24 | 25 | ### HIGHER\_QUALITY 26 | 27 | > **HIGHER\_QUALITY**: `1` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:30](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L30) 30 | 31 | *** 32 | 33 | ### UNKNOWN 34 | 35 | > **UNKNOWN**: `0` 36 | 37 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:29](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L29) 38 | 39 | *** 40 | 41 | ### UNRECOGNIZED 42 | 43 | > **UNRECOGNIZED**: `-1` 44 | 45 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:33](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L33) 46 | -------------------------------------------------------------------------------- /dev-scripts/generate-proto.mjs: -------------------------------------------------------------------------------- 1 | import { exec } from 'child_process'; 2 | import { existsSync, mkdirSync, readdirSync, statSync } from 'fs'; 3 | import { join } from 'path'; 4 | import path from 'path'; 5 | import url from 'url'; 6 | import os from 'os'; 7 | 8 | const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); 9 | 10 | const protoDir = './protos'; 11 | const outDir = './protos/generated'; 12 | 13 | if (!existsSync(outDir)) { 14 | mkdirSync(outDir, { recursive: true }); 15 | } 16 | 17 | const protocGenTs = path.join( 18 | __dirname, 19 | '../node_modules', 20 | '.bin', 21 | os.platform() === 'win32' ? 'protoc-gen-ts_proto.cmd' : 'protoc-gen-ts_proto' 22 | ); 23 | 24 | function listProtoFiles(dir) { 25 | let protoFiles = []; 26 | const items = readdirSync(dir); 27 | 28 | for (const item of items) { 29 | const fullPath = join(dir, item); 30 | if (statSync(fullPath).isDirectory()) { 31 | protoFiles = protoFiles.concat(listProtoFiles(fullPath)); 32 | } else if (item.endsWith('.proto')) { 33 | protoFiles.push(fullPath); 34 | } 35 | } 36 | 37 | return protoFiles; 38 | } 39 | 40 | const protoFiles = listProtoFiles(protoDir); 41 | 42 | if (!protoFiles.length) { 43 | console.log('No .proto files found.'); 44 | process.exit(0); 45 | } 46 | 47 | protoFiles.forEach((file) => { 48 | const command = `protoc --proto_path=${protoDir} --plugin=protoc-gen-ts=${protocGenTs} --ts_opt=env=browser --ts_opt=forceLong=string --ts_opt=importSuffix=.js --ts_out=${outDir} --ts_opt=outputJsonMethods=false --ts_opt=outputPartialMethods=false --ts_opt=removeEnumPrefix=true ${file}`; 49 | exec(command, (error, _stdout, stderr) => { 50 | if (error) { 51 | console.error(`Error compiling ${file}:`, stderr); 52 | } 53 | }); 54 | }); -------------------------------------------------------------------------------- /protos/generated/video_streaming/sabr_redirect.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.7.5 4 | // protoc v5.28.0 5 | // source: video_streaming/sabr_redirect.proto 6 | 7 | /* eslint-disable */ 8 | import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; 9 | 10 | export const protobufPackage = "video_streaming"; 11 | 12 | export interface SabrRedirect { 13 | url?: string | undefined; 14 | } 15 | 16 | function createBaseSabrRedirect(): SabrRedirect { 17 | return { url: "" }; 18 | } 19 | 20 | export const SabrRedirect: MessageFns = { 21 | encode(message: SabrRedirect, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { 22 | if (message.url !== undefined && message.url !== "") { 23 | writer.uint32(10).string(message.url); 24 | } 25 | return writer; 26 | }, 27 | 28 | decode(input: BinaryReader | Uint8Array, length?: number): SabrRedirect { 29 | const reader = input instanceof BinaryReader ? input : new BinaryReader(input); 30 | const end = length === undefined ? reader.len : reader.pos + length; 31 | const message = createBaseSabrRedirect(); 32 | while (reader.pos < end) { 33 | const tag = reader.uint32(); 34 | switch (tag >>> 3) { 35 | case 1: { 36 | if (tag !== 10) { 37 | break; 38 | } 39 | 40 | message.url = reader.string(); 41 | continue; 42 | } 43 | } 44 | if ((tag & 7) === 4 || tag === 0) { 45 | break; 46 | } 47 | reader.skip(tag & 7); 48 | } 49 | return message; 50 | }, 51 | }; 52 | 53 | export interface MessageFns { 54 | encode(message: T, writer?: BinaryWriter): BinaryWriter; 55 | decode(input: BinaryReader | Uint8Array, length?: number): T; 56 | } 57 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/PlaybackCookie.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / PlaybackCookie 2 | 3 | # Interface: PlaybackCookie 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/playback\_cookie.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/playback_cookie.ts#L13) 6 | 7 | ## Properties 8 | 9 | ### audioFmt? 10 | 11 | > `optional` **audioFmt**: [`FormatId`](FormatId.md) 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/playback\_cookie.ts:18](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/playback_cookie.ts#L18) 14 | 15 | *** 16 | 17 | ### field2? 18 | 19 | > `optional` **field2**: `number` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/playback\_cookie.ts:16](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/playback_cookie.ts#L16) 22 | 23 | *** 24 | 25 | ### resolution? 26 | 27 | > `optional` **resolution**: `number` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/playback\_cookie.ts:15](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/playback_cookie.ts#L15) 30 | 31 | Always 999999 when resolution is set manually, or if the auto selected one is the max available resolution. 32 | 33 | *** 34 | 35 | ### videoFmt? 36 | 37 | > `optional` **videoFmt**: [`FormatId`](FormatId.md) 38 | 39 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/playback\_cookie.ts:17](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/playback_cookie.ts#L17) 40 | -------------------------------------------------------------------------------- /protos/generated/video_streaming/snackbar_message.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.7.5 4 | // protoc v5.28.0 5 | // source: video_streaming/snackbar_message.proto 6 | 7 | /* eslint-disable */ 8 | import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; 9 | 10 | export const protobufPackage = "video_streaming"; 11 | 12 | export interface SnackbarMessage { 13 | id?: number | undefined; 14 | } 15 | 16 | function createBaseSnackbarMessage(): SnackbarMessage { 17 | return { id: 0 }; 18 | } 19 | 20 | export const SnackbarMessage: MessageFns = { 21 | encode(message: SnackbarMessage, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { 22 | if (message.id !== undefined && message.id !== 0) { 23 | writer.uint32(8).int32(message.id); 24 | } 25 | return writer; 26 | }, 27 | 28 | decode(input: BinaryReader | Uint8Array, length?: number): SnackbarMessage { 29 | const reader = input instanceof BinaryReader ? input : new BinaryReader(input); 30 | const end = length === undefined ? reader.len : reader.pos + length; 31 | const message = createBaseSnackbarMessage(); 32 | while (reader.pos < end) { 33 | const tag = reader.uint32(); 34 | switch (tag >>> 3) { 35 | case 1: { 36 | if (tag !== 8) { 37 | break; 38 | } 39 | 40 | message.id = reader.int32(); 41 | continue; 42 | } 43 | } 44 | if ((tag & 7) === 4 || tag === 0) { 45 | break; 46 | } 47 | reader.skip(tag & 7); 48 | } 49 | return message; 50 | }, 51 | }; 52 | 53 | export interface MessageFns { 54 | encode(message: T, writer?: BinaryWriter): BinaryWriter; 55 | decode(input: BinaryReader | Uint8Array, length?: number): T; 56 | } 57 | -------------------------------------------------------------------------------- /src/types/shared.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This module contains type definitions used across the library. 3 | * @module 4 | */ 5 | 6 | import type { CompositeBuffer } from '../core/CompositeBuffer.js'; 7 | 8 | export type Part = { 9 | type: number; 10 | size: number; 11 | data: CompositeBuffer; 12 | }; 13 | 14 | export interface SabrFormat { 15 | itag: number; 16 | lastModified: string; 17 | xtags?: string; 18 | width?: number; 19 | height?: number; 20 | contentLength?: number; 21 | audioTrackId?: string; 22 | mimeType?: string; 23 | isDrc?: boolean; 24 | quality?: string; 25 | qualityLabel?: string; 26 | averageBitrate?: number; 27 | bitrate: number; 28 | audioQuality?: string; 29 | approxDurationMs: number; 30 | language?: string | null; 31 | isDubbed?: boolean; 32 | isAutoDubbed?: boolean; 33 | isDescriptive?: boolean; 34 | isSecondary?: boolean; 35 | isOriginal?: boolean; 36 | } 37 | 38 | export interface FormatStream { 39 | itag: number; 40 | last_modified_ms?: string; 41 | lastModified?: string; 42 | xtags?: string; 43 | width?: number; 44 | height?: number; 45 | mime_type?: string; 46 | mimeType?: string; 47 | audio_quality?: string; 48 | audioQuality?: string; 49 | bitrate: number; 50 | average_bitrate?: number; 51 | averageBitrate?: number; 52 | quality?: string; 53 | quality_label?: string; 54 | qualityLabel?: string; 55 | audio_track?: { id: string }; 56 | audioTrackId?: string; 57 | is_drc?: boolean; 58 | isDrc?: boolean; 59 | approx_duration_ms?: number; 60 | approxDurationMs?: string; 61 | content_length?: number; 62 | contentLength?: string; 63 | is_auto_dubbed?: boolean; 64 | is_descriptive?: boolean; 65 | is_dubbed?: boolean; 66 | language?: string | null; 67 | is_original?: boolean; 68 | is_secondary?: boolean; 69 | } 70 | 71 | export type FetchFunction = typeof fetch; -------------------------------------------------------------------------------- /protos/generated/video_streaming/request_identifier.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.7.5 4 | // protoc v5.28.0 5 | // source: video_streaming/request_identifier.proto 6 | 7 | /* eslint-disable */ 8 | import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; 9 | 10 | export const protobufPackage = "video_streaming"; 11 | 12 | export interface RequestIdentifier { 13 | token?: string | undefined; 14 | } 15 | 16 | function createBaseRequestIdentifier(): RequestIdentifier { 17 | return { token: "" }; 18 | } 19 | 20 | export const RequestIdentifier: MessageFns = { 21 | encode(message: RequestIdentifier, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { 22 | if (message.token !== undefined && message.token !== "") { 23 | writer.uint32(10).string(message.token); 24 | } 25 | return writer; 26 | }, 27 | 28 | decode(input: BinaryReader | Uint8Array, length?: number): RequestIdentifier { 29 | const reader = input instanceof BinaryReader ? input : new BinaryReader(input); 30 | const end = length === undefined ? reader.len : reader.pos + length; 31 | const message = createBaseRequestIdentifier(); 32 | while (reader.pos < end) { 33 | const tag = reader.uint32(); 34 | switch (tag >>> 3) { 35 | case 1: { 36 | if (tag !== 10) { 37 | break; 38 | } 39 | 40 | message.token = reader.string(); 41 | continue; 42 | } 43 | } 44 | if ((tag & 7) === 4 || tag === 0) { 45 | break; 46 | } 47 | reader.skip(tag & 7); 48 | } 49 | return message; 50 | }, 51 | }; 52 | 53 | export interface MessageFns { 54 | encode(message: T, writer?: BinaryWriter): BinaryWriter; 55 | decode(input: BinaryReader | Uint8Array, length?: number): T; 56 | } 57 | -------------------------------------------------------------------------------- /protos/video_streaming/video_playback_abr_request.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | import "misc/common.proto"; 5 | import "video_streaming/buffered_range.proto"; 6 | import "video_streaming/client_abr_state.proto"; 7 | import "video_streaming/streamer_context.proto"; 8 | import "video_streaming/time_range.proto"; 9 | 10 | message VideoPlaybackAbrRequest { 11 | optional ClientAbrState client_abr_state = 1; 12 | repeated .misc.FormatId selected_format_ids = 2; 13 | repeated BufferedRange buffered_ranges = 3; 14 | optional int64 player_time_ms = 4; // `osts` (Onesie Start Time Seconds) param on Onesie requests. 15 | optional bytes video_playback_ustreamer_config = 5; 16 | optional UnknownMessage1 field6 = 6; 17 | repeated .misc.FormatId preferred_audio_format_ids = 16; // `pai` (Preferred Audio Itags) param on Onesie requests. 18 | repeated .misc.FormatId preferred_video_format_ids = 17; // `pvi` (Preferred Video Itags) param on Onesie requests. 19 | repeated .misc.FormatId preferred_subtitle_format_ids = 18; 20 | optional StreamerContext streamer_context = 19; 21 | optional UnknownMessage2 field21 = 21; 22 | optional int32 field22 = 22; 23 | optional int32 field23 = 23; 24 | repeated UnknownMessage3 field1000 = 1000; 25 | } 26 | 27 | message UnknownMessage1 { 28 | optional .misc.FormatId format_id = 1; 29 | optional sint64 lmt = 2; 30 | optional int32 sequence_number = 3; 31 | optional TimeRange time_range = 4; 32 | optional int32 field5 = 5; 33 | } 34 | 35 | message UnknownMessage2 { 36 | repeated string field1 = 1; 37 | optional bytes field2 = 2; 38 | optional string field3 = 3; 39 | optional int32 field4 = 4; 40 | optional int32 field5 = 5; 41 | optional string field6 = 6; 42 | } 43 | 44 | message UnknownMessage3 { 45 | repeated .misc.FormatId format_ids = 1; 46 | repeated BufferedRange ud = 2; 47 | optional string clip_id = 3; 48 | } -------------------------------------------------------------------------------- /.github/workflows/release-please.yml: -------------------------------------------------------------------------------- 1 | name: release-please 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | permissions: 9 | contents: write 10 | pull-requests: write 11 | id-token: write 12 | 13 | jobs: 14 | release-please: 15 | permissions: 16 | contents: write 17 | pull-requests: write 18 | id-token: write 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: googleapis/release-please-action@v4 22 | id: release 23 | with: 24 | token: ${{ secrets.GITHUB_TOKEN }} 25 | config-file: release-please-config.json 26 | manifest-file: .release-please-manifest.json 27 | 28 | - uses: actions/checkout@v4 29 | if: ${{ steps.release.outputs.release_created }} 30 | 31 | - uses: actions/setup-node@v4 32 | with: 33 | node-version: "20" 34 | registry-url: "https://registry.npmjs.org" 35 | if: ${{ steps.release.outputs.release_created }} 36 | 37 | - name: Install protoc 38 | run: | 39 | sudo apt-get update 40 | sudo apt-get install -y unzip 41 | curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-linux-x86_64.zip 42 | unzip protoc-21.12-linux-x86_64.zip -d protoc21 43 | sudo mv protoc21/bin/protoc /usr/local/bin/ 44 | if: ${{ steps.release.outputs.release_created }} 45 | 46 | - run: npm ci 47 | if: ${{ steps.release.outputs.release_created }} 48 | 49 | - name: Publish to NPM 50 | run: | 51 | npm publish 52 | env: 53 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 54 | if: ${{ steps.release.outputs.release_created }} 55 | 56 | - name: Publish to JSR 57 | run: | 58 | npm run build 59 | npx jsr publish --allow-dirty 60 | if: ${{ steps.release.outputs.release_created }} -------------------------------------------------------------------------------- /src/core/UmpWriter.ts: -------------------------------------------------------------------------------- 1 | import type { CompositeBuffer } from './CompositeBuffer.js'; 2 | 3 | /** 4 | * A serialization module that encodes data into the UMP binary format with proper type and size encoding. 5 | */ 6 | export class UmpWriter { 7 | constructor( 8 | private compositeBuffer: CompositeBuffer 9 | ) { } 10 | 11 | /** 12 | * Writes a part to the buffer. 13 | * @param partType - The type of the part. 14 | * @param partData - The data of the part. 15 | */ 16 | public write(partType: number, partData: Uint8Array): void { 17 | const partSize = partData.length; 18 | this.writeVarInt(partType); 19 | this.writeVarInt(partSize); 20 | this.compositeBuffer.append(partData); 21 | } 22 | 23 | /** 24 | * Writes a variable-length integer to the buffer. 25 | * @param value - The integer to write. 26 | */ 27 | private writeVarInt(value: number): void { 28 | if (value < 0) 29 | throw new Error('VarInt value cannot be negative.'); 30 | 31 | if (value < 128) { 32 | this.compositeBuffer.append(new Uint8Array([ value ])); 33 | } else if (value < 16384) { 34 | this.compositeBuffer.append(new Uint8Array([ 35 | (value & 0x3F) | 0x80, 36 | value >> 6 37 | ])); 38 | } else if (value < 2097152) { 39 | this.compositeBuffer.append(new Uint8Array([ 40 | (value & 0x1F) | 0xC0, 41 | (value >> 5) & 0xFF, 42 | value >> 13 43 | ])); 44 | } else if (value < 268435456) { 45 | this.compositeBuffer.append(new Uint8Array([ 46 | (value & 0x0F) | 0xE0, 47 | (value >> 4) & 0xFF, 48 | (value >> 12) & 0xFF, 49 | value >> 20 50 | ])); 51 | } else { 52 | const data = new Uint8Array(5); 53 | const view = new DataView(data.buffer); 54 | data[0] = 0xF0; 55 | view.setUint32(1, value, true); 56 | this.compositeBuffer.append(data); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/OnesieInnertubeResponse.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / OnesieInnertubeResponse 2 | 3 | # Interface: OnesieInnertubeResponse 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_innertube\_response.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_innertube_response.ts#L14) 6 | 7 | ## Properties 8 | 9 | ### body? 10 | 11 | > `optional` **body**: `Uint8Array`\<`ArrayBufferLike`\> 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_innertube\_response.ts:18](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_innertube_response.ts#L18) 14 | 15 | *** 16 | 17 | ### headers 18 | 19 | > **headers**: [`HttpHeader`](HttpHeader.md)[] 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_innertube\_response.ts:17](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_innertube_response.ts#L17) 22 | 23 | *** 24 | 25 | ### httpStatus? 26 | 27 | > `optional` **httpStatus**: `number` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_innertube\_response.ts:16](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_innertube_response.ts#L16) 30 | 31 | *** 32 | 33 | ### onesieProxyStatus? 34 | 35 | > `optional` **onesieProxyStatus**: [`OnesieProxyStatus`](../enumerations/OnesieProxyStatus.md) 36 | 37 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_innertube\_response.ts:15](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_innertube_response.ts#L15) 38 | -------------------------------------------------------------------------------- /docs/api/exports/sabr-streaming-adapter/interfaces/PlayerHttpRequest.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/sabr-streaming-adapter](../README.md) / PlayerHttpRequest 2 | 3 | # Interface: PlayerHttpRequest 4 | 5 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:83](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L83) 6 | 7 | ## Properties 8 | 9 | ### body? 10 | 11 | > `optional` **body**: `null` \| `ArrayBuffer` \| `ArrayBufferView`\<`ArrayBufferLike`\> 12 | 13 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:88](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L88) 14 | 15 | *** 16 | 17 | ### headers 18 | 19 | > **headers**: `Record`\<`string`, `string`\> 20 | 21 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:86](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L86) 22 | 23 | *** 24 | 25 | ### method 26 | 27 | > **method**: `string` 28 | 29 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:85](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L85) 30 | 31 | *** 32 | 33 | ### segment 34 | 35 | > **segment**: [`RequestSegment`](RequestSegment.md) 36 | 37 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:87](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L87) 38 | 39 | *** 40 | 41 | ### url 42 | 43 | > **url**: `string` 44 | 45 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:84](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L84) 46 | -------------------------------------------------------------------------------- /examples/downloader/main.ts: -------------------------------------------------------------------------------- 1 | import { EnabledTrackTypes } from 'googlevideo/utils'; 2 | 3 | import { 4 | createOutputStream, 5 | createStreamSink, 6 | createSabrStream, 7 | createMultiProgressBar, 8 | setupProgressBar 9 | } from './utils/sabr-stream-factory.js'; 10 | 11 | import type { SabrPlaybackOptions } from 'googlevideo/sabr-stream'; 12 | 13 | const VIDEO_ID = 'xjHO_02jZco'; 14 | const OPTIONS: SabrPlaybackOptions = { 15 | preferWebM: true, 16 | preferOpus: true, 17 | videoQuality: '720p', 18 | audioQuality: 'AUDIO_QUALITY_MEDIUM', 19 | enabledTrackTypes: EnabledTrackTypes.VIDEO_AND_AUDIO 20 | }; 21 | 22 | async function main() { 23 | const progressBars = createMultiProgressBar(); 24 | 25 | try { 26 | const { streamResults } = await createSabrStream(VIDEO_ID, OPTIONS); 27 | const { videoStream, audioStream, selectedFormats, videoTitle } = streamResults; 28 | 29 | const audioOutputStream = createOutputStream(videoTitle, selectedFormats.audioFormat.mimeType!); 30 | const videoOutputStream = createOutputStream(videoTitle, selectedFormats.videoFormat.mimeType!); 31 | 32 | const audioBar = setupProgressBar(progressBars, 'audio', selectedFormats.audioFormat.contentLength || 0); 33 | const videoBar = setupProgressBar(progressBars, 'video', selectedFormats.videoFormat.contentLength || 0); 34 | 35 | await Promise.all([ 36 | videoStream.pipeTo(createStreamSink(selectedFormats.videoFormat, videoOutputStream.stream, videoBar)), 37 | audioStream.pipeTo(createStreamSink(selectedFormats.audioFormat, audioOutputStream.stream, audioBar)) 38 | ]); 39 | 40 | progressBars.stop(); 41 | 42 | console.log(`Download completed! Files saved as: 43 | Audio: ${audioOutputStream.filePath}, 44 | Video: ${videoOutputStream.filePath}`); 45 | } catch (error) { 46 | console.error('Download failed:', error); 47 | progressBars.stop(); 48 | process.exit(1); 49 | } 50 | } 51 | 52 | main().then(); -------------------------------------------------------------------------------- /docs/api/exports/protos/enumerations/AudioQuality.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / AudioQuality 2 | 3 | # Enumeration: AudioQuality 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:19](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L19) 6 | 7 | ## Enumeration Members 8 | 9 | ### HIGH 10 | 11 | > **HIGH**: `30` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:24](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L24) 14 | 15 | *** 16 | 17 | ### LOW 18 | 19 | > **LOW**: `10` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:22](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L22) 22 | 23 | *** 24 | 25 | ### MEDIUM 26 | 27 | > **MEDIUM**: `20` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:23](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L23) 30 | 31 | *** 32 | 33 | ### ULTRALOW 34 | 35 | > **ULTRALOW**: `5` 36 | 37 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:21](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L21) 38 | 39 | *** 40 | 41 | ### UNKNOWN 42 | 43 | > **UNKNOWN**: `0` 44 | 45 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:20](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L20) 46 | 47 | *** 48 | 49 | ### UNRECOGNIZED 50 | 51 | > **UNRECOGNIZED**: `-1` 52 | 53 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:25](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L25) 54 | -------------------------------------------------------------------------------- /src/utils/RequestMetadataManager.ts: -------------------------------------------------------------------------------- 1 | import type { SabrRequestMetadata } from '../types/sabrStreamingAdapterTypes.js'; 2 | 3 | /** 4 | * Manages request metadata objects. 5 | */ 6 | export class RequestMetadataManager { 7 | public metadataMap: Map; 8 | private lastCleanup: number; 9 | private readonly CLEANUP_INTERVAL = 30000; 10 | private readonly ENTRY_EXPIRATION_TIME = 1000 * 60 * 3; 11 | 12 | constructor() { 13 | this.metadataMap = new Map(); 14 | this.lastCleanup = Date.now(); 15 | } 16 | 17 | public getRequestMetadata(url: string, del = false): SabrRequestMetadata | undefined { 18 | const requestNumber = new URL(url).searchParams.get('rn') || ''; 19 | 20 | const streamingContext = this.metadataMap.get(requestNumber); 21 | 22 | // Check if this specific entry is expired. 23 | if (streamingContext && Date.now() - streamingContext.timestamp > this.ENTRY_EXPIRATION_TIME) { 24 | this.metadataMap.delete(requestNumber); 25 | return undefined; 26 | } 27 | 28 | if (del) { 29 | this.metadataMap.delete(requestNumber); 30 | } 31 | 32 | this.conditionalCleanUp(); 33 | 34 | return streamingContext; 35 | } 36 | 37 | public setRequestMetadata(url: string, context: SabrRequestMetadata) { 38 | const requestNumber = new URL(url).searchParams.get('rn'); 39 | if (requestNumber) { 40 | this.metadataMap.set(requestNumber, context); 41 | this.conditionalCleanUp(); 42 | } 43 | } 44 | 45 | private conditionalCleanUp() { 46 | const now = Date.now(); 47 | if (now - this.lastCleanup > this.CLEANUP_INTERVAL) { 48 | this.cleanUp(); 49 | this.lastCleanup = now; 50 | } 51 | } 52 | 53 | private cleanUp() { 54 | // Should rarely run. This is only for requests that fail and never get handled (e.g., network errors). 55 | for (const [ key, context ] of this.metadataMap.entries()) { 56 | if (Date.now() - context.timestamp > this.ENTRY_EXPIRATION_TIME) { 57 | this.metadataMap.delete(key); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /protos/generated/video_streaming/sabr_error.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.7.5 4 | // protoc v5.28.0 5 | // source: video_streaming/sabr_error.proto 6 | 7 | /* eslint-disable */ 8 | import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; 9 | 10 | export const protobufPackage = "video_streaming"; 11 | 12 | export interface SabrError { 13 | type?: string | undefined; 14 | code?: number | undefined; 15 | } 16 | 17 | function createBaseSabrError(): SabrError { 18 | return { type: "", code: 0 }; 19 | } 20 | 21 | export const SabrError: MessageFns = { 22 | encode(message: SabrError, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { 23 | if (message.type !== undefined && message.type !== "") { 24 | writer.uint32(10).string(message.type); 25 | } 26 | if (message.code !== undefined && message.code !== 0) { 27 | writer.uint32(16).int32(message.code); 28 | } 29 | return writer; 30 | }, 31 | 32 | decode(input: BinaryReader | Uint8Array, length?: number): SabrError { 33 | const reader = input instanceof BinaryReader ? input : new BinaryReader(input); 34 | const end = length === undefined ? reader.len : reader.pos + length; 35 | const message = createBaseSabrError(); 36 | while (reader.pos < end) { 37 | const tag = reader.uint32(); 38 | switch (tag >>> 3) { 39 | case 1: { 40 | if (tag !== 10) { 41 | break; 42 | } 43 | 44 | message.type = reader.string(); 45 | continue; 46 | } 47 | case 2: { 48 | if (tag !== 16) { 49 | break; 50 | } 51 | 52 | message.code = reader.int32(); 53 | continue; 54 | } 55 | } 56 | if ((tag & 7) === 4 || tag === 0) { 57 | break; 58 | } 59 | reader.skip(tag & 7); 60 | } 61 | return message; 62 | }, 63 | }; 64 | 65 | export interface MessageFns { 66 | encode(message: T, writer?: BinaryWriter): BinaryWriter; 67 | decode(input: BinaryReader | Uint8Array, length?: number): T; 68 | } 69 | -------------------------------------------------------------------------------- /docs/api/exports/protos/enumerations/OnesieRequestTarget.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / OnesieRequestTarget 2 | 3 | # Enumeration: OnesieRequestTarget 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:172](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L172) 6 | 7 | ## Enumeration Members 8 | 9 | ### ENCRYPTED\_PLAYER\_SERVICE 10 | 11 | > **ENCRYPTED\_PLAYER\_SERVICE**: `1` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:174](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L174) 14 | 15 | *** 16 | 17 | ### ENCRYPTED\_WATCH\_SERVICE 18 | 19 | > **ENCRYPTED\_WATCH\_SERVICE**: `3` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:176](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L176) 22 | 23 | *** 24 | 25 | ### ENCRYPTED\_WATCH\_SERVICE\_DEPRECATED 26 | 27 | > **ENCRYPTED\_WATCH\_SERVICE\_DEPRECATED**: `2` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:175](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L175) 30 | 31 | *** 32 | 33 | ### INNERTUBE\_ENCRYPTED\_SERVICE 34 | 35 | > **INNERTUBE\_ENCRYPTED\_SERVICE**: `4` 36 | 37 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:177](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L177) 38 | 39 | *** 40 | 41 | ### UNKNOWN 42 | 43 | > **UNKNOWN**: `0` 44 | 45 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:173](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L173) 46 | 47 | *** 48 | 49 | ### UNRECOGNIZED 50 | 51 | > **UNRECOGNIZED**: `-1` 52 | 53 | Defined in: [codeberg/googlevideo/protos/generated/misc/common.ts:178](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/misc/common.ts#L178) 54 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/SabrContextUpdate.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / SabrContextUpdate 2 | 3 | # Interface: SabrContextUpdate 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L12) 6 | 7 | ## Properties 8 | 9 | ### scope? 10 | 11 | > `optional` **scope**: `SabrContextUpdate_SabrContextScope` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L14) 14 | 15 | *** 16 | 17 | ### sendByDefault? 18 | 19 | > `optional` **sendByDefault**: `boolean` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:16](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L16) 22 | 23 | *** 24 | 25 | ### type? 26 | 27 | > `optional` **type**: `number` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L13) 30 | 31 | *** 32 | 33 | ### value? 34 | 35 | > `optional` **value**: `Uint8Array`\<`ArrayBufferLike`\> 36 | 37 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:15](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L15) 38 | 39 | *** 40 | 41 | ### writePolicy? 42 | 43 | > `optional` **writePolicy**: [`SabrContextWritePolicy`](../enumerations/SabrContextWritePolicy.md) 44 | 45 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/sabr\_context\_update.ts:17](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/sabr_context_update.ts#L17) 46 | -------------------------------------------------------------------------------- /docs/api/exports/sabr-streaming-adapter/interfaces/PlayerHttpResponse.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/sabr-streaming-adapter](../README.md) / PlayerHttpResponse 2 | 3 | # Interface: PlayerHttpResponse 4 | 5 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:75](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L75) 6 | 7 | ## Properties 8 | 9 | ### data? 10 | 11 | > `optional` **data**: `ArrayBuffer` \| `ArrayBufferView`\<`ArrayBufferLike`\> 12 | 13 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:79](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L79) 14 | 15 | *** 16 | 17 | ### headers 18 | 19 | > **headers**: `Record`\<`string`, `string`\> 20 | 21 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:78](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L78) 22 | 23 | *** 24 | 25 | ### makeRequest() 26 | 27 | > **makeRequest**: (`url`, `headers`) => `Promise`\<`Omit`\<`PlayerHttpResponse`, `"makeRequest"`\>\> 28 | 29 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:80](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L80) 30 | 31 | #### Parameters 32 | 33 | ##### url 34 | 35 | `string` 36 | 37 | ##### headers 38 | 39 | `Record`\<`string`, `string`\> 40 | 41 | #### Returns 42 | 43 | `Promise`\<`Omit`\<`PlayerHttpResponse`, `"makeRequest"`\>\> 44 | 45 | *** 46 | 47 | ### method 48 | 49 | > **method**: `string` 50 | 51 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:77](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L77) 52 | 53 | *** 54 | 55 | ### url 56 | 57 | > **url**: `string` 58 | 59 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:76](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L76) 60 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/OnesieInnertubeRequest.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / OnesieInnertubeRequest 2 | 3 | # Interface: OnesieInnertubeRequest 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_innertube\_request.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_innertube_request.ts#L13) 6 | 7 | ## Properties 8 | 9 | ### body? 10 | 11 | > `optional` **body**: `string` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_innertube\_request.ts:16](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_innertube_request.ts#L16) 14 | 15 | *** 16 | 17 | ### headers 18 | 19 | > **headers**: [`HttpHeader`](HttpHeader.md)[] 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_innertube\_request.ts:15](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_innertube_request.ts#L15) 22 | 23 | *** 24 | 25 | ### proxiedByTrustedBandaid? 26 | 27 | > `optional` **proxiedByTrustedBandaid**: `boolean` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_innertube\_request.ts:17](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_innertube_request.ts#L17) 30 | 31 | *** 32 | 33 | ### skipResponseEncryption? 34 | 35 | > `optional` **skipResponseEncryption**: `boolean` 36 | 37 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_innertube\_request.ts:18](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_innertube_request.ts#L18) 38 | 39 | *** 40 | 41 | ### url? 42 | 43 | > `optional` **url**: `string` 44 | 45 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/onesie\_innertube\_request.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/onesie_innertube_request.ts#L14) 46 | -------------------------------------------------------------------------------- /protos/video_streaming/streamer_context.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | message StreamerContext { 5 | message ClientInfo { 6 | optional string device_make = 12; 7 | optional string device_model = 13; 8 | optional int32 client_name = 16; 9 | optional string client_version = 17; 10 | optional string os_name = 18; 11 | optional string os_version = 19; 12 | optional string accept_language = 21; 13 | optional string accept_region = 22; 14 | optional int32 screen_width_points = 37; 15 | optional int32 screen_height_points = 38; 16 | optional float screen_width_inches = 39; 17 | optional float screen_height_inches = 40; 18 | optional int32 screen_pixel_density = 41; 19 | optional ClientFormFactor client_form_factor = 46; 20 | optional int32 gmscore_version_code = 50; // e.g. 243731017 21 | optional int32 window_width_points = 55; 22 | optional int32 window_height_points = 56; 23 | optional int32 android_sdk_version = 64; 24 | optional float screen_density_float = 65; 25 | optional int64 utc_offset_minutes = 67; 26 | optional string time_zone = 80; 27 | optional string chipset = 92; // e.g. "qcom;taro" 28 | optional GLDeviceInfo gl_device_info = 102; 29 | } 30 | 31 | enum ClientFormFactor { 32 | UNKNOWN_FORM_FACTOR = 0; 33 | FORM_FACTOR_VAL1 = 1; 34 | FORM_FACTOR_VAL2 = 2; 35 | } 36 | 37 | message GLDeviceInfo { 38 | optional string gl_renderer = 1; 39 | optional int32 gl_es_version_major = 2; 40 | optional int32 gl_es_version_minor = 3; 41 | } 42 | 43 | message SabrContext { 44 | optional int32 type = 1; 45 | optional bytes value = 2; 46 | } 47 | 48 | message UnknownMessage1 { 49 | message UnknownInnerMessage1 { 50 | optional int32 code = 1; 51 | optional string message = 2; 52 | } 53 | 54 | optional bytes field1 = 1; 55 | optional UnknownInnerMessage1 field2 = 2; 56 | } 57 | 58 | optional ClientInfo client_info = 1; 59 | optional bytes po_token = 2; 60 | optional bytes playback_cookie = 3; 61 | optional bytes field4 = 4; 62 | repeated SabrContext sabr_contexts = 5; 63 | repeated int32 unsent_sabr_contexts = 6; 64 | optional string field7 = 7; 65 | optional UnknownMessage1 field8 = 8; 66 | } -------------------------------------------------------------------------------- /protos/generated/video_streaming/stream_protection_status.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.7.5 4 | // protoc v5.28.0 5 | // source: video_streaming/stream_protection_status.proto 6 | 7 | /* eslint-disable */ 8 | import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; 9 | 10 | export const protobufPackage = "video_streaming"; 11 | 12 | export interface StreamProtectionStatus { 13 | status?: number | undefined; 14 | maxRetries?: number | undefined; 15 | } 16 | 17 | function createBaseStreamProtectionStatus(): StreamProtectionStatus { 18 | return { status: 0, maxRetries: 0 }; 19 | } 20 | 21 | export const StreamProtectionStatus: MessageFns = { 22 | encode(message: StreamProtectionStatus, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { 23 | if (message.status !== undefined && message.status !== 0) { 24 | writer.uint32(8).int32(message.status); 25 | } 26 | if (message.maxRetries !== undefined && message.maxRetries !== 0) { 27 | writer.uint32(16).int32(message.maxRetries); 28 | } 29 | return writer; 30 | }, 31 | 32 | decode(input: BinaryReader | Uint8Array, length?: number): StreamProtectionStatus { 33 | const reader = input instanceof BinaryReader ? input : new BinaryReader(input); 34 | const end = length === undefined ? reader.len : reader.pos + length; 35 | const message = createBaseStreamProtectionStatus(); 36 | while (reader.pos < end) { 37 | const tag = reader.uint32(); 38 | switch (tag >>> 3) { 39 | case 1: { 40 | if (tag !== 8) { 41 | break; 42 | } 43 | 44 | message.status = reader.int32(); 45 | continue; 46 | } 47 | case 2: { 48 | if (tag !== 16) { 49 | break; 50 | } 51 | 52 | message.maxRetries = reader.int32(); 53 | continue; 54 | } 55 | } 56 | if ((tag & 7) === 4 || tag === 0) { 57 | break; 58 | } 59 | reader.skip(tag & 7); 60 | } 61 | return message; 62 | }, 63 | }; 64 | 65 | export interface MessageFns { 66 | encode(message: T, writer?: BinaryWriter): BinaryWriter; 67 | decode(input: BinaryReader | Uint8Array, length?: number): T; 68 | } 69 | -------------------------------------------------------------------------------- /protos/video_streaming/ump_part_id.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | package video_streaming; 4 | 5 | enum UMPPartId { 6 | UNKNOWN = 0; 7 | ONESIE_HEADER = 10; 8 | ONESIE_DATA = 11; 9 | ONESIE_ENCRYPTED_MEDIA = 12; 10 | // Header for a media segment; includes sequence and timing information. 11 | MEDIA_HEADER = 20; 12 | // Chunk of media segment data. 13 | MEDIA = 21; 14 | // Indicates end of media segment; finalizes segment processing. 15 | MEDIA_END = 22; 16 | CONFIG = 30; 17 | LIVE_METADATA = 31; 18 | HOSTNAME_CHANGE_HINT_DEPRECATED = 32; 19 | LIVE_METADATA_PROMISE = 33; 20 | LIVE_METADATA_PROMISE_CANCELLATION = 34; 21 | // Server's policy for the next request; includes backoff time and playback cookie. 22 | NEXT_REQUEST_POLICY = 35; 23 | USTREAMER_VIDEO_AND_FORMAT_METADATA = 36; 24 | FORMAT_SELECTION_CONFIG = 37; 25 | USTREAMER_SELECTED_MEDIA_STREAM = 38; 26 | // Metadata for format initialization; contains total number of segments, duration, etc. 27 | FORMAT_INITIALIZATION_METADATA = 42; 28 | // Indicates a redirect to a different streaming URL. 29 | SABR_REDIRECT = 43; 30 | // Indicates a SABR error; happens when the payload is invalid or the server cannot process the request. 31 | SABR_ERROR = 44; 32 | SABR_SEEK = 45; 33 | // Directive to reload the player with new parameters. 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 | // Updates SABR context data; usually used for ads. 46 | SABR_CONTEXT_UPDATE = 57; 47 | // Status of stream protection; indicates whether attestation is required. 48 | STREAM_PROTECTION_STATUS = 58; 49 | // Policy indicating which SABR contexts to send or discard in future requests. 50 | SABR_CONTEXT_SENDING_POLICY = 59; 51 | LAWNMOWER_POLICY = 60; 52 | SABR_ACK = 61; 53 | END_OF_TRACK = 62; 54 | CACHE_LOAD_POLICY = 63; 55 | LAWNMOWER_MESSAGING_POLICY = 64; 56 | PREWARM_CONNECTION = 65; 57 | PLAYBACK_DEBUG_INFO = 66; 58 | // Directive to show the user a notification message. 59 | SNACKBAR_MESSAGE = 67; 60 | } -------------------------------------------------------------------------------- /examples/onesie-request/utils.ts: -------------------------------------------------------------------------------- 1 | import crypto from 'crypto'; 2 | 3 | type Encrypted = { 4 | encrypted: Uint8Array; 5 | hmac: Uint8Array; 6 | iv: Uint8Array; 7 | }; 8 | 9 | export async function encryptRequest(clientKey: Uint8Array, data: Uint8Array): Promise { 10 | if (clientKey.length !== 32) 11 | throw new Error('Invalid client key length'); 12 | 13 | const aesKeyData = clientKey.slice(0, 16); 14 | const hmacKeyData = clientKey.slice(16, 32); 15 | 16 | const iv = crypto.getRandomValues(new Uint8Array(16)); 17 | 18 | const aesKey = await crypto.subtle.importKey( 19 | 'raw', 20 | aesKeyData, 21 | { name: 'AES-CTR', length: 128 }, 22 | false, 23 | [ 'encrypt' ] 24 | ); 25 | 26 | const encrypted = new Uint8Array(await crypto.subtle.encrypt( 27 | { name: 'AES-CTR', counter: iv, length: 128 }, 28 | aesKey, 29 | data 30 | )); 31 | 32 | const hmacKey = await crypto.subtle.importKey( 33 | 'raw', 34 | hmacKeyData, 35 | { name: 'HMAC', hash: { name: 'SHA-256' } }, 36 | false, 37 | [ 'sign' ] 38 | ); 39 | 40 | const hmac = new Uint8Array(await crypto.subtle.sign( 41 | 'HMAC', 42 | hmacKey, 43 | new Uint8Array([ ...encrypted, ...iv ]) 44 | )); 45 | 46 | return { encrypted, hmac, iv }; 47 | } 48 | 49 | export async function decryptResponse(iv?: Uint8Array, hmac?: Uint8Array, data?: Uint8Array, clientKeyData?: Uint8Array): Promise { 50 | if (!iv || !hmac || !data || !clientKeyData) 51 | throw new Error('Invalid input'); 52 | 53 | const aesKey = await crypto.subtle.importKey( 54 | 'raw', 55 | clientKeyData.slice(0, 16), 56 | { name: 'AES-CTR', length: 128 }, 57 | false, 58 | [ 'decrypt' ] 59 | ); 60 | 61 | const decryptedData = new Uint8Array(await crypto.subtle.decrypt( 62 | { name: 'AES-CTR', counter: iv, length: 128 }, 63 | aesKey, 64 | data 65 | )); 66 | 67 | const hmacKey = await crypto.subtle.importKey( 68 | 'raw', 69 | clientKeyData.slice(16, 32), 70 | { name: 'HMAC', hash: { name: 'SHA-256' } }, 71 | false, 72 | [ 'verify' ] 73 | ); 74 | 75 | const isValid = await crypto.subtle.verify( 76 | 'HMAC', 77 | hmacKey, 78 | hmac, 79 | new Uint8Array([ ...data, ...iv ]) 80 | ); 81 | 82 | if (!isValid) 83 | throw new Error('HMAC verification failed'); 84 | 85 | return decryptedData; 86 | } -------------------------------------------------------------------------------- /docs/api/exports/utils/classes/RequestMetadataManager.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/utils](../README.md) / RequestMetadataManager 2 | 3 | # Class: RequestMetadataManager 4 | 5 | Defined in: [codeberg/googlevideo/src/utils/RequestMetadataManager.ts:6](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/RequestMetadataManager.ts#L6) 6 | 7 | Manages request metadata objects. 8 | 9 | ## Constructors 10 | 11 | ### Constructor 12 | 13 | > **new RequestMetadataManager**(): `RequestMetadataManager` 14 | 15 | Defined in: [codeberg/googlevideo/src/utils/RequestMetadataManager.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/RequestMetadataManager.ts#L12) 16 | 17 | #### Returns 18 | 19 | `RequestMetadataManager` 20 | 21 | ## Properties 22 | 23 | ### metadataMap 24 | 25 | > **metadataMap**: `Map`\<`string`, [`SabrRequestMetadata`](../../sabr-streaming-adapter/interfaces/SabrRequestMetadata.md)\> 26 | 27 | Defined in: [codeberg/googlevideo/src/utils/RequestMetadataManager.ts:7](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/RequestMetadataManager.ts#L7) 28 | 29 | ## Methods 30 | 31 | ### getRequestMetadata() 32 | 33 | > **getRequestMetadata**(`url`, `del`): `undefined` \| [`SabrRequestMetadata`](../../sabr-streaming-adapter/interfaces/SabrRequestMetadata.md) 34 | 35 | Defined in: [codeberg/googlevideo/src/utils/RequestMetadataManager.ts:17](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/RequestMetadataManager.ts#L17) 36 | 37 | #### Parameters 38 | 39 | ##### url 40 | 41 | `string` 42 | 43 | ##### del 44 | 45 | `boolean` = `false` 46 | 47 | #### Returns 48 | 49 | `undefined` \| [`SabrRequestMetadata`](../../sabr-streaming-adapter/interfaces/SabrRequestMetadata.md) 50 | 51 | *** 52 | 53 | ### setRequestMetadata() 54 | 55 | > **setRequestMetadata**(`url`, `context`): `void` 56 | 57 | Defined in: [codeberg/googlevideo/src/utils/RequestMetadataManager.ts:37](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/utils/RequestMetadataManager.ts#L37) 58 | 59 | #### Parameters 60 | 61 | ##### url 62 | 63 | `string` 64 | 65 | ##### context 66 | 67 | [`SabrRequestMetadata`](../../sabr-streaming-adapter/interfaces/SabrRequestMetadata.md) 68 | 69 | #### Returns 70 | 71 | `void` 72 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue.yml: -------------------------------------------------------------------------------- 1 | name: Issue Report 2 | title: " " 3 | description: Use this template to report a problem 4 | labels: [bug] 5 | body: 6 | - type: textarea 7 | id: reproduce-steps 8 | attributes: 9 | label: Steps to reproduce 10 | description: Please provide detailed steps for reproducing the issue. 11 | placeholder: | 12 | Example: 13 | 1. Step 1 14 | 2. Step 2 15 | 3. You get it.. 16 | validations: 17 | required: true 18 | 19 | - type: textarea 20 | id: failure-logs 21 | attributes: 22 | label: Failure Logs 23 | description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. 24 | render: shell 25 | validations: 26 | required: true 27 | 28 | - type: textarea 29 | id: expected-behavior 30 | attributes: 31 | label: Expected behavior 32 | description: What did you expect to happen? 33 | validations: 34 | required: true 35 | 36 | - type: textarea 37 | id: current-behavior 38 | attributes: 39 | label: Current behavior 40 | description: What is the current behavior? 41 | validations: 42 | required: true 43 | 44 | - type: dropdown 45 | id: version 46 | attributes: 47 | label: Version 48 | description: What version of the library are you running? 49 | options: 50 | - Default 51 | - Edge 52 | validations: 53 | required: true 54 | 55 | - type: textarea 56 | attributes: 57 | label: Anything else? 58 | description: | 59 | Links? References? Anything that will give us more context about the issue you are encountering! 60 | 61 | Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. 62 | validations: 63 | required: false 64 | 65 | - type: checkboxes 66 | id: checklist 67 | attributes: 68 | label: Checklist 69 | options: 70 | - label: I am running the latest version. 71 | required: false 72 | - label: I checked the documentation and found no answer. 73 | required: true 74 | - label: I have searched the existing issues and made sure this is not a duplicate. 75 | required: true 76 | - label: I have provided sufficient information. 77 | required: true -------------------------------------------------------------------------------- /examples/onesie-request/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "onesie-request", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "onesie-request", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "googlevideo": "file:../..", 13 | "youtubei.js": "^16.0.0" 14 | } 15 | }, 16 | "../..": { 17 | "version": "4.0.4", 18 | "funding": [ 19 | "https://github.com/sponsors/LuanRT" 20 | ], 21 | "license": "MIT", 22 | "dependencies": { 23 | "@bufbuild/protobuf": "^2.0.0" 24 | }, 25 | "devDependencies": { 26 | "@eslint/js": "^9.9.0", 27 | "@stylistic/eslint-plugin": "^2.6.4", 28 | "@types/eslint__js": "^8.42.3", 29 | "eslint": "^9.9.0", 30 | "globals": "^15.9.0", 31 | "ts-patch": "^3.3.0", 32 | "ts-proto": "^2.2.0", 33 | "typedoc": "^0.28.7", 34 | "typedoc-plugin-markdown": "^4.7.1", 35 | "typescript": "^5.5.4", 36 | "typescript-eslint": "^8.2.0", 37 | "vitest": "^3.2.4" 38 | } 39 | }, 40 | "node_modules/@bufbuild/protobuf": { 41 | "version": "2.2.3", 42 | "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.2.3.tgz", 43 | "integrity": "sha512-tFQoXHJdkEOSwj5tRIZSPNUuXK3RaR7T1nUrPgbYX1pUbvqqaaZAsfo+NXBPsz5rZMSKVFrgK1WL8Q/MSLvprg==" 44 | }, 45 | "node_modules/googlevideo": { 46 | "resolved": "../..", 47 | "link": true 48 | }, 49 | "node_modules/meriyah": { 50 | "version": "6.1.4", 51 | "resolved": "https://registry.npmjs.org/meriyah/-/meriyah-6.1.4.tgz", 52 | "integrity": "sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ==", 53 | "license": "ISC", 54 | "engines": { 55 | "node": ">=18.0.0" 56 | } 57 | }, 58 | "node_modules/youtubei.js": { 59 | "version": "16.0.0", 60 | "resolved": "https://registry.npmjs.org/youtubei.js/-/youtubei.js-16.0.0.tgz", 61 | "integrity": "sha512-aMx+ulnrxzsgVsxTr7gbBVnIjti2NQUlMwCoo1/MzICCJS3iMLOPUFdo7bSpwskL6ljzQ/LxmmB4WQC3FtkBlA==", 62 | "funding": [ 63 | "https://github.com/sponsors/LuanRT" 64 | ], 65 | "license": "MIT", 66 | "dependencies": { 67 | "@bufbuild/protobuf": "^2.0.0", 68 | "meriyah": "^6.1.4" 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /protos/video_streaming/client_abr_state.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package video_streaming; 3 | 4 | import "misc/common.proto"; 5 | import "video_streaming/media_capabilities.proto"; 6 | 7 | message ClientAbrState { 8 | optional int64 time_since_last_manual_format_selection_ms = 13; 9 | optional sint32 last_manual_direction = 14; 10 | optional int32 last_manual_selected_resolution = 16; 11 | optional int32 detailed_network_type = 17; 12 | optional int32 client_viewport_width = 18; 13 | optional int32 client_viewport_height = 19; 14 | optional int64 client_bitrate_cap_bytes_per_sec = 20; 15 | optional int32 sticky_resolution = 21; 16 | optional bool client_viewport_is_flexible = 22; 17 | optional int64 bandwidth_estimate = 23; 18 | optional .misc.AudioQuality min_audio_quality = 24; 19 | optional .misc.AudioQuality max_audio_quality = 25; 20 | optional .misc.VideoQualitySetting video_quality_setting = 26; 21 | optional .misc.PlaybackAudioRouteOutputType audio_route = 27; 22 | optional int64 player_time_ms = 28; 23 | optional int64 time_since_last_seek = 29; 24 | optional bool data_saver_mode = 30; 25 | optional .misc.NetworkMeteredState network_metered_state = 32; 26 | optional int32 visibility = 34; 27 | optional float playback_rate = 35; 28 | optional int64 elapsed_wall_time_ms = 36; 29 | optional MediaCapabilities media_capabilities = 38; 30 | optional int64 time_since_last_action_ms = 39; 31 | optional int32 enabled_track_types_bitfield = 40; 32 | optional int32 max_pacing_rate = 43; 33 | optional int64 player_state = 44; 34 | optional bool drc_enabled = 46; 35 | optional int32 field48 = 48; 36 | optional int32 field50 = 50; 37 | optional int32 field51 = 51; 38 | optional int32 sabr_report_request_cancellation_info = 54; 39 | optional bool disable_streaming_xhr = 56; 40 | optional int64 field57 = 57; 41 | optional bool prefer_vp9 = 58; 42 | optional int32 av1_quality_threshold = 59; // 2160 43 | optional int32 field60 = 60; 44 | optional bool is_prefetch = 61; 45 | optional bool sabr_support_quality_constraints = 62; 46 | optional bytes sabr_license_constraint = 63; 47 | optional int32 allow_proxima_live_latency = 64; 48 | optional int32 sabr_force_proxima = 66; 49 | optional int32 field67 = 67; 50 | optional int64 sabr_force_max_network_interruption_duration_ms = 68; 51 | optional string audio_track_id = 69; 52 | optional bool enable_voice_boost = 76; 53 | optional .misc.PlaybackAuthorization playback_authorization = 79; 54 | } 55 | -------------------------------------------------------------------------------- /protos/generated/video_streaming/time_range.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.7.5 4 | // protoc v5.28.0 5 | // source: video_streaming/time_range.proto 6 | 7 | /* eslint-disable */ 8 | import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; 9 | 10 | export const protobufPackage = "video_streaming"; 11 | 12 | export interface TimeRange { 13 | startTicks?: string | undefined; 14 | durationTicks?: string | undefined; 15 | timescale?: number | undefined; 16 | } 17 | 18 | function createBaseTimeRange(): TimeRange { 19 | return { startTicks: "0", durationTicks: "0", timescale: 0 }; 20 | } 21 | 22 | export const TimeRange: MessageFns<TimeRange> = { 23 | encode(message: TimeRange, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { 24 | if (message.startTicks !== undefined && message.startTicks !== "0") { 25 | writer.uint32(8).int64(message.startTicks); 26 | } 27 | if (message.durationTicks !== undefined && message.durationTicks !== "0") { 28 | writer.uint32(16).int64(message.durationTicks); 29 | } 30 | if (message.timescale !== undefined && message.timescale !== 0) { 31 | writer.uint32(24).int32(message.timescale); 32 | } 33 | return writer; 34 | }, 35 | 36 | decode(input: BinaryReader | Uint8Array, length?: number): TimeRange { 37 | const reader = input instanceof BinaryReader ? input : new BinaryReader(input); 38 | const end = length === undefined ? reader.len : reader.pos + length; 39 | const message = createBaseTimeRange(); 40 | while (reader.pos < end) { 41 | const tag = reader.uint32(); 42 | switch (tag >>> 3) { 43 | case 1: { 44 | if (tag !== 8) { 45 | break; 46 | } 47 | 48 | message.startTicks = reader.int64().toString(); 49 | continue; 50 | } 51 | case 2: { 52 | if (tag !== 16) { 53 | break; 54 | } 55 | 56 | message.durationTicks = reader.int64().toString(); 57 | continue; 58 | } 59 | case 3: { 60 | if (tag !== 24) { 61 | break; 62 | } 63 | 64 | message.timescale = reader.int32(); 65 | continue; 66 | } 67 | } 68 | if ((tag & 7) === 4 || tag === 0) { 69 | break; 70 | } 71 | reader.skip(tag & 7); 72 | } 73 | return message; 74 | }, 75 | }; 76 | 77 | export interface MessageFns<T> { 78 | encode(message: T, writer?: BinaryWriter): BinaryWriter; 79 | decode(input: BinaryReader | Uint8Array, length?: number): T; 80 | } 81 | -------------------------------------------------------------------------------- /protos/generated/video_streaming/crypto_params.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.7.5 4 | // protoc v5.28.0 5 | // source: video_streaming/crypto_params.proto 6 | 7 | /* eslint-disable */ 8 | import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; 9 | import { CompressionType } from "../misc/common.js"; 10 | 11 | export const protobufPackage = "video_streaming"; 12 | 13 | export interface CryptoParams { 14 | hmac?: Uint8Array | undefined; 15 | iv?: Uint8Array | undefined; 16 | compressionType?: CompressionType | undefined; 17 | } 18 | 19 | function createBaseCryptoParams(): CryptoParams { 20 | return { hmac: new Uint8Array(0), iv: new Uint8Array(0), compressionType: 0 }; 21 | } 22 | 23 | export const CryptoParams: MessageFns<CryptoParams> = { 24 | encode(message: CryptoParams, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { 25 | if (message.hmac !== undefined && message.hmac.length !== 0) { 26 | writer.uint32(34).bytes(message.hmac); 27 | } 28 | if (message.iv !== undefined && message.iv.length !== 0) { 29 | writer.uint32(42).bytes(message.iv); 30 | } 31 | if (message.compressionType !== undefined && message.compressionType !== 0) { 32 | writer.uint32(48).int32(message.compressionType); 33 | } 34 | return writer; 35 | }, 36 | 37 | decode(input: BinaryReader | Uint8Array, length?: number): CryptoParams { 38 | const reader = input instanceof BinaryReader ? input : new BinaryReader(input); 39 | const end = length === undefined ? reader.len : reader.pos + length; 40 | const message = createBaseCryptoParams(); 41 | while (reader.pos < end) { 42 | const tag = reader.uint32(); 43 | switch (tag >>> 3) { 44 | case 4: { 45 | if (tag !== 34) { 46 | break; 47 | } 48 | 49 | message.hmac = reader.bytes(); 50 | continue; 51 | } 52 | case 5: { 53 | if (tag !== 42) { 54 | break; 55 | } 56 | 57 | message.iv = reader.bytes(); 58 | continue; 59 | } 60 | case 6: { 61 | if (tag !== 48) { 62 | break; 63 | } 64 | 65 | message.compressionType = reader.int32() as any; 66 | continue; 67 | } 68 | } 69 | if ((tag & 7) === 4 || tag === 0) { 70 | break; 71 | } 72 | reader.skip(tag & 7); 73 | } 74 | return message; 75 | }, 76 | }; 77 | 78 | export interface MessageFns<T> { 79 | encode(message: T, writer?: BinaryWriter): BinaryWriter; 80 | decode(input: BinaryReader | Uint8Array, length?: number): T; 81 | } 82 | -------------------------------------------------------------------------------- /protos/generated/video_streaming/sabr_seek.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.7.5 4 | // protoc v5.28.0 5 | // source: video_streaming/sabr_seek.proto 6 | 7 | /* eslint-disable */ 8 | import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; 9 | import { SeekSource } from "../misc/common.js"; 10 | 11 | export const protobufPackage = "video_streaming"; 12 | 13 | export interface SabrSeek { 14 | seekMediaTime?: string | undefined; 15 | seekMediaTimescale?: number | undefined; 16 | seekSource?: SeekSource | undefined; 17 | } 18 | 19 | function createBaseSabrSeek(): SabrSeek { 20 | return { seekMediaTime: "0", seekMediaTimescale: 0, seekSource: 0 }; 21 | } 22 | 23 | export const SabrSeek: MessageFns<SabrSeek> = { 24 | encode(message: SabrSeek, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { 25 | if (message.seekMediaTime !== undefined && message.seekMediaTime !== "0") { 26 | writer.uint32(8).int64(message.seekMediaTime); 27 | } 28 | if (message.seekMediaTimescale !== undefined && message.seekMediaTimescale !== 0) { 29 | writer.uint32(16).int32(message.seekMediaTimescale); 30 | } 31 | if (message.seekSource !== undefined && message.seekSource !== 0) { 32 | writer.uint32(24).int32(message.seekSource); 33 | } 34 | return writer; 35 | }, 36 | 37 | decode(input: BinaryReader | Uint8Array, length?: number): SabrSeek { 38 | const reader = input instanceof BinaryReader ? input : new BinaryReader(input); 39 | const end = length === undefined ? reader.len : reader.pos + length; 40 | const message = createBaseSabrSeek(); 41 | while (reader.pos < end) { 42 | const tag = reader.uint32(); 43 | switch (tag >>> 3) { 44 | case 1: { 45 | if (tag !== 8) { 46 | break; 47 | } 48 | 49 | message.seekMediaTime = reader.int64().toString(); 50 | continue; 51 | } 52 | case 2: { 53 | if (tag !== 16) { 54 | break; 55 | } 56 | 57 | message.seekMediaTimescale = reader.int32(); 58 | continue; 59 | } 60 | case 3: { 61 | if (tag !== 24) { 62 | break; 63 | } 64 | 65 | message.seekSource = reader.int32() as any; 66 | continue; 67 | } 68 | } 69 | if ((tag & 7) === 4 || tag === 0) { 70 | break; 71 | } 72 | reader.skip(tag & 7); 73 | } 74 | return message; 75 | }, 76 | }; 77 | 78 | export interface MessageFns<T> { 79 | encode(message: T, writer?: BinaryWriter): BinaryWriter; 80 | decode(input: BinaryReader | Uint8Array, length?: number): T; 81 | } 82 | -------------------------------------------------------------------------------- /src/utils/EventEmitterLike.ts: -------------------------------------------------------------------------------- 1 | // See https://github.com/nodejs/node/issues/40678#issuecomment-1126944677 2 | class CustomEvent extends Event { 3 | #detail; 4 | 5 | constructor(type: string, options?: CustomEventInit<any[]>) { 6 | super(type, options); 7 | this.#detail = options?.detail ?? null; 8 | } 9 | 10 | get detail(): any[] | null { 11 | return this.#detail; 12 | } 13 | } 14 | 15 | export class SabrAdapterError extends Error { 16 | constructor(message: string, public code?: string) { 17 | super(`[SabrStreamingAdapter] ${message}`); 18 | this.name = 'SabrAdapterError'; 19 | } 20 | } 21 | 22 | export class EventEmitterLike extends EventTarget { 23 | #legacyListeners = new Map<(...args: any[]) => void, { type: string, wrapper: EventListener }>(); 24 | 25 | constructor() { 26 | super(); 27 | } 28 | 29 | emit(type: string, ...args: any[]) { 30 | const event = new CustomEvent(type, { detail: args }); 31 | this.dispatchEvent(event); 32 | } 33 | 34 | on(type: string, listener: (...args: any[]) => void) { 35 | const wrapper: EventListener = (ev) => { 36 | if (ev instanceof CustomEvent) { 37 | listener(...ev.detail as any[]); 38 | } else { 39 | listener(ev); 40 | } 41 | }; 42 | this.#legacyListeners.set(listener, { type, wrapper }); 43 | this.addEventListener(type, wrapper); 44 | } 45 | 46 | once(type: string, listener: (...args: any[]) => void) { 47 | const wrapper: EventListener = (ev) => { 48 | if (ev instanceof CustomEvent) { 49 | listener(...ev.detail as any[]); 50 | } else { 51 | listener(ev); 52 | } 53 | this.off(type, listener); 54 | }; 55 | this.#legacyListeners.set(listener, { type, wrapper }); 56 | this.addEventListener(type, wrapper); 57 | } 58 | 59 | off(type: string, listener: (...args: any[]) => void) { 60 | const listenerData = this.#legacyListeners.get(listener); 61 | if (listenerData && listenerData.type === type) { 62 | this.removeEventListener(type, listenerData.wrapper); 63 | this.#legacyListeners.delete(listener); 64 | } 65 | } 66 | 67 | removeAllListeners(type?: string) { 68 | if (type) { 69 | for (const [ listener, listenerData ] of this.#legacyListeners.entries()) { 70 | if (listenerData.type === type) { 71 | this.removeEventListener(type, listenerData.wrapper); 72 | this.#legacyListeners.delete(listener); 73 | } 74 | } 75 | } else { 76 | for (const [ listener, listenerData ] of this.#legacyListeners.entries()) { 77 | this.removeEventListener(listenerData.type, listenerData.wrapper); 78 | this.#legacyListeners.delete(listener); 79 | } 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /docs/api/exports/sabr-streaming-adapter/classes/SabrUmpProcessor.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/sabr-streaming-adapter](../README.md) / SabrUmpProcessor 2 | 3 | # Class: SabrUmpProcessor 4 | 5 | Defined in: [codeberg/googlevideo/src/core/SabrUmpProcessor.ts:47](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/SabrUmpProcessor.ts#L47) 6 | 7 | This class is responsible for reading a UMP stream, handling different part types 8 | (like media headers, media data, and server directives), and populating a 9 | metadata object with the extracted information. It is supposed to be used 10 | in conjunction with a [`SabrPlayerAdapter`](../interfaces/SabrPlayerAdapter.md) in video player 11 | implementations. 12 | 13 | ## Constructors 14 | 15 | ### Constructor 16 | 17 | > **new SabrUmpProcessor**(`requestMetadata`, `cacheManager?`): `SabrUmpProcessor` 18 | 19 | Defined in: [codeberg/googlevideo/src/core/SabrUmpProcessor.ts:68](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/SabrUmpProcessor.ts#L68) 20 | 21 | #### Parameters 22 | 23 | ##### requestMetadata 24 | 25 | [`SabrRequestMetadata`](../interfaces/SabrRequestMetadata.md) 26 | 27 | ##### cacheManager? 28 | 29 | [`CacheManager`](../../utils/classes/CacheManager.md) 30 | 31 | #### Returns 32 | 33 | `SabrUmpProcessor` 34 | 35 | ## Properties 36 | 37 | ### partialPart? 38 | 39 | > `optional` **partialPart**: [`Part`](../../../types/shared/type-aliases/Part.md) 40 | 41 | Defined in: [codeberg/googlevideo/src/core/SabrUmpProcessor.ts:48](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/SabrUmpProcessor.ts#L48) 42 | 43 | ## Methods 44 | 45 | ### getSegmentInfo() 46 | 47 | > **getSegmentInfo**(): `undefined` \| `Segment` 48 | 49 | Defined in: [codeberg/googlevideo/src/core/SabrUmpProcessor.ts:106](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/SabrUmpProcessor.ts#L106) 50 | 51 | #### Returns 52 | 53 | `undefined` \| `Segment` 54 | 55 | *** 56 | 57 | ### processChunk() 58 | 59 | > **processChunk**(`value`): `Promise`\<`undefined` \| [`UmpProcessingResult`](../interfaces/UmpProcessingResult.md)\> 60 | 61 | Defined in: [codeberg/googlevideo/src/core/SabrUmpProcessor.ts:78](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/core/SabrUmpProcessor.ts#L78) 62 | 63 | Processes a chunk of data from a UMP stream and updates the request context. 64 | 65 | #### Parameters 66 | 67 | ##### value 68 | 69 | `Uint8Array` 70 | 71 | #### Returns 72 | 73 | `Promise`\<`undefined` \| [`UmpProcessingResult`](../interfaces/UmpProcessingResult.md)\> 74 | 75 | A promise that resolves with a processing result if a terminal part is found (e.g., MediaEnd), or undefined otherwise. 76 | -------------------------------------------------------------------------------- /protos/generated/video_streaming/ump_part_id.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.7.5 4 | // protoc v5.28.0 5 | // source: video_streaming/ump_part_id.proto 6 | 7 | /* eslint-disable */ 8 | 9 | export const protobufPackage = "video_streaming"; 10 | 11 | export enum UMPPartId { 12 | UNKNOWN = 0, 13 | ONESIE_HEADER = 10, 14 | ONESIE_DATA = 11, 15 | ONESIE_ENCRYPTED_MEDIA = 12, 16 | /** MEDIA_HEADER - Header for a media segment; includes sequence and timing information. */ 17 | MEDIA_HEADER = 20, 18 | /** MEDIA - Chunk of media segment data. */ 19 | MEDIA = 21, 20 | /** MEDIA_END - Indicates end of media segment; finalizes segment processing. */ 21 | MEDIA_END = 22, 22 | CONFIG = 30, 23 | LIVE_METADATA = 31, 24 | HOSTNAME_CHANGE_HINT_DEPRECATED = 32, 25 | LIVE_METADATA_PROMISE = 33, 26 | LIVE_METADATA_PROMISE_CANCELLATION = 34, 27 | /** NEXT_REQUEST_POLICY - Server's policy for the next request; includes backoff time and playback cookie. */ 28 | NEXT_REQUEST_POLICY = 35, 29 | USTREAMER_VIDEO_AND_FORMAT_METADATA = 36, 30 | FORMAT_SELECTION_CONFIG = 37, 31 | USTREAMER_SELECTED_MEDIA_STREAM = 38, 32 | /** FORMAT_INITIALIZATION_METADATA - Metadata for format initialization; contains total number of segments, duration, etc. */ 33 | FORMAT_INITIALIZATION_METADATA = 42, 34 | /** SABR_REDIRECT - Indicates a redirect to a different streaming URL. */ 35 | SABR_REDIRECT = 43, 36 | /** SABR_ERROR - Indicates a SABR error; happens when the payload is invalid or the server cannot process the request. */ 37 | SABR_ERROR = 44, 38 | SABR_SEEK = 45, 39 | /** RELOAD_PLAYER_RESPONSE - Directive to reload the player with new parameters. */ 40 | RELOAD_PLAYER_RESPONSE = 46, 41 | PLAYBACK_START_POLICY = 47, 42 | ALLOWED_CACHED_FORMATS = 48, 43 | START_BW_SAMPLING_HINT = 49, 44 | PAUSE_BW_SAMPLING_HINT = 50, 45 | SELECTABLE_FORMATS = 51, 46 | REQUEST_IDENTIFIER = 52, 47 | REQUEST_CANCELLATION_POLICY = 53, 48 | ONESIE_PREFETCH_REJECTION = 54, 49 | TIMELINE_CONTEXT = 55, 50 | REQUEST_PIPELINING = 56, 51 | /** SABR_CONTEXT_UPDATE - Updates SABR context data; usually used for ads. */ 52 | SABR_CONTEXT_UPDATE = 57, 53 | /** STREAM_PROTECTION_STATUS - Status of stream protection; indicates whether attestation is required. */ 54 | STREAM_PROTECTION_STATUS = 58, 55 | /** SABR_CONTEXT_SENDING_POLICY - Policy indicating which SABR contexts to send or discard in future requests. */ 56 | SABR_CONTEXT_SENDING_POLICY = 59, 57 | LAWNMOWER_POLICY = 60, 58 | SABR_ACK = 61, 59 | END_OF_TRACK = 62, 60 | CACHE_LOAD_POLICY = 63, 61 | LAWNMOWER_MESSAGING_POLICY = 64, 62 | PREWARM_CONNECTION = 65, 63 | PLAYBACK_DEBUG_INFO = 66, 64 | /** SNACKBAR_MESSAGE - Directive to show the user a notification message. */ 65 | SNACKBAR_MESSAGE = 67, 66 | UNRECOGNIZED = -1, 67 | } 68 | -------------------------------------------------------------------------------- /protos/generated/video_streaming/format_selection_config.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.7.5 4 | // protoc v5.28.0 5 | // source: video_streaming/format_selection_config.proto 6 | 7 | /* eslint-disable */ 8 | import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; 9 | 10 | export const protobufPackage = "video_streaming"; 11 | 12 | export interface FormatSelectionConfig { 13 | itags: number[]; 14 | videoId?: string | undefined; 15 | resolution?: number | undefined; 16 | } 17 | 18 | function createBaseFormatSelectionConfig(): FormatSelectionConfig { 19 | return { itags: [], videoId: "", resolution: 0 }; 20 | } 21 | 22 | export const FormatSelectionConfig: MessageFns<FormatSelectionConfig> = { 23 | encode(message: FormatSelectionConfig, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { 24 | writer.uint32(18).fork(); 25 | for (const v of message.itags) { 26 | writer.int32(v); 27 | } 28 | writer.join(); 29 | if (message.videoId !== undefined && message.videoId !== "") { 30 | writer.uint32(26).string(message.videoId); 31 | } 32 | if (message.resolution !== undefined && message.resolution !== 0) { 33 | writer.uint32(32).int32(message.resolution); 34 | } 35 | return writer; 36 | }, 37 | 38 | decode(input: BinaryReader | Uint8Array, length?: number): FormatSelectionConfig { 39 | const reader = input instanceof BinaryReader ? input : new BinaryReader(input); 40 | const end = length === undefined ? reader.len : reader.pos + length; 41 | const message = createBaseFormatSelectionConfig(); 42 | while (reader.pos < end) { 43 | const tag = reader.uint32(); 44 | switch (tag >>> 3) { 45 | case 2: { 46 | if (tag === 16) { 47 | message.itags.push(reader.int32()); 48 | 49 | continue; 50 | } 51 | 52 | if (tag === 18) { 53 | const end2 = reader.uint32() + reader.pos; 54 | while (reader.pos < end2) { 55 | message.itags.push(reader.int32()); 56 | } 57 | 58 | continue; 59 | } 60 | 61 | break; 62 | } 63 | case 3: { 64 | if (tag !== 26) { 65 | break; 66 | } 67 | 68 | message.videoId = reader.string(); 69 | continue; 70 | } 71 | case 4: { 72 | if (tag !== 32) { 73 | break; 74 | } 75 | 76 | message.resolution = reader.int32(); 77 | continue; 78 | } 79 | } 80 | if ((tag & 7) === 4 || tag === 0) { 81 | break; 82 | } 83 | reader.skip(tag & 7); 84 | } 85 | return message; 86 | }, 87 | }; 88 | 89 | export interface MessageFns<T> { 90 | encode(message: T, writer?: BinaryWriter): BinaryWriter; 91 | decode(input: BinaryReader | Uint8Array, length?: number): T; 92 | } 93 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "googlevideo", 3 | "version": "4.0.4", 4 | "description": "A collection of modules for working with YouTube's proprietary video streaming protocols (UMP/SABR).", 5 | "type": "module", 6 | "scripts": { 7 | "watch": "npx tspc --watch", 8 | "lint": "npx eslint ./src/**/*.ts", 9 | "lint:fix": "npx eslint --fix ./src/**/*.ts", 10 | "clean": "npx rimraf ./dist ./protos/generated", 11 | "build": "npm run clean && npm run lint && npm run build:proto && npm run build:esm", 12 | "build:esm": "npx tspc", 13 | "build:proto": "node ./dev-scripts/generate-proto.mjs", 14 | "build:docs": "typedoc", 15 | "test": "vitest run --reporter verbose", 16 | "test:watch": "vitest", 17 | "prepare": "npm run build" 18 | }, 19 | "author": "LuanRT <luan.lrt4@gmail.com> (https://github.com/LuanRT)", 20 | "funding": [ 21 | "https://github.com/sponsors/LuanRT" 22 | ], 23 | "keywords": [ 24 | "UMP", 25 | "SABR", 26 | "Google", 27 | "YouTube" 28 | ], 29 | "license": "MIT", 30 | "exports": { 31 | "./ump": { 32 | "types": "./dist/src/exports/ump.d.ts", 33 | "import": "./dist/src/exports/ump.js", 34 | "default": "./dist/src/exports/ump.js" 35 | }, 36 | "./sabr-streaming-adapter": { 37 | "types": "./dist/src/exports/sabr-streaming-adapter.d.ts", 38 | "import": "./dist/src/exports/sabr-streaming-adapter.js", 39 | "default": "./dist/src/exports/sabr-streaming-adapter.js" 40 | }, 41 | "./sabr-stream": { 42 | "types": "./dist/src/exports/sabr-stream.d.ts", 43 | "import": "./dist/src/exports/sabr-stream.js", 44 | "default": "./dist/src/exports/sabr-stream.js" 45 | }, 46 | "./protos": { 47 | "types": "./dist/src/exports/protos.d.ts", 48 | "import": "./dist/src/exports/protos.js", 49 | "default": "./dist/src/exports/protos.js" 50 | }, 51 | "./utils": { 52 | "types": "./dist/src/exports/utils.d.ts", 53 | "import": "./dist/src/exports/utils.js", 54 | "default": "./dist/src/exports/utils.js" 55 | }, 56 | "./shared-types": { 57 | "types": "./dist/src/types/shared.d.ts" 58 | } 59 | }, 60 | "devDependencies": { 61 | "@eslint/js": "^9.9.0", 62 | "@stylistic/eslint-plugin": "^2.6.4", 63 | "@types/eslint__js": "^8.42.3", 64 | "eslint": "^9.9.0", 65 | "globals": "^15.9.0", 66 | "ts-patch": "^3.3.0", 67 | "ts-proto": "^2.2.0", 68 | "typedoc": "^0.28.7", 69 | "typedoc-plugin-markdown": "^4.7.1", 70 | "typescript": "^5.5.4", 71 | "typescript-eslint": "^8.2.0", 72 | "vitest": "^3.2.4" 73 | }, 74 | "dependencies": { 75 | "@bufbuild/protobuf": "^2.0.0" 76 | }, 77 | "bugs": { 78 | "url": "https://github.com/LuanRT/GoogleVideo/issues" 79 | }, 80 | "homepage": "https://github.com/LuanRT/GoogleVideo#readme", 81 | "repository": { 82 | "type": "git", 83 | "url": "git+https://github.com/LuanRT/GoogleVideo.git" 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /docs/api/exports/sabr-streaming-adapter/interfaces/SabrOptions.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/sabr-streaming-adapter](../README.md) / SabrOptions 2 | 3 | # Interface: SabrOptions 4 | 5 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:43](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L43) 6 | 7 | ## Properties 8 | 9 | ### clientInfo? 10 | 11 | > `optional` **clientInfo**: [`ClientInfo`](../../protos/interfaces/ClientInfo.md) 12 | 13 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:72](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L72) 14 | 15 | Client information to send with SABR requests. 16 | 17 | *** 18 | 19 | ### enableCaching? 20 | 21 | > `optional` **enableCaching**: `boolean` 22 | 23 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:48](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L48) 24 | 25 | Whether to enable caching of SABR segments. 26 | 27 | #### Default 28 | 29 | ```ts 30 | true 31 | ``` 32 | 33 | *** 34 | 35 | ### enableVerboseRequestLogging? 36 | 37 | > `optional` **enableVerboseRequestLogging**: `boolean` 38 | 39 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:54](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L54) 40 | 41 | Enables verbose logging of all SABR requests made by the player. 42 | @NOTE: `DEBUG` level logging must be enabled for this to take effect. 43 | 44 | #### Default 45 | 46 | ```ts 47 | false 48 | ``` 49 | 50 | *** 51 | 52 | ### maxCacheAgeSeconds? 53 | 54 | > `optional` **maxCacheAgeSeconds**: `number` 55 | 56 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:64](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L64) 57 | 58 | Maximum age of cached segments in seconds. 59 | 60 | #### Default 61 | 62 | ```ts 63 | 300 (5 minutes) 64 | ``` 65 | 66 | *** 67 | 68 | ### maxCacheSizeMB? 69 | 70 | > `optional` **maxCacheSizeMB**: `number` 71 | 72 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:59](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L59) 73 | 74 | Maximum size of the segment cache in megabytes. 75 | 76 | #### Default 77 | 78 | ```ts 79 | 3 80 | ``` 81 | 82 | *** 83 | 84 | ### playerAdapter? 85 | 86 | > `optional` **playerAdapter**: [`SabrPlayerAdapter`](SabrPlayerAdapter.md) 87 | 88 | Defined in: [codeberg/googlevideo/src/types/sabrStreamingAdapterTypes.ts:68](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/src/types/sabrStreamingAdapterTypes.ts#L68) 89 | 90 | Player adapter to use for SABR streaming. 91 | -------------------------------------------------------------------------------- /src/utils/Logger.ts: -------------------------------------------------------------------------------- 1 | export enum LogLevel { 2 | NONE = 0, 3 | ERROR = 1, 4 | WARN = 2, 5 | INFO = 3, 6 | DEBUG = 4, 7 | ALL = 99, 8 | } 9 | 10 | /** 11 | * Singleton logger utility. 12 | * 13 | * Allows enabling or disabling specific log levels (`ERROR`, `WARN`, `INFO`, `DEBUG`) 14 | * at runtime. Supports logging with tags and message arguments. 15 | * 16 | * Usage: 17 | * ```ts 18 | * const logger = Logger.getInstance(); 19 | * logger.setLogLevels(LogLevel.ERROR, LogLevel.INFO); 20 | * logger.error('MyTag', 'An error occurred'); 21 | * ``` 22 | */ 23 | export class Logger { 24 | private static instance: Logger; 25 | private currentLogLevels: Set<LogLevel> = new Set([ LogLevel.INFO, LogLevel.ERROR ]); 26 | 27 | public static getInstance(): Logger { 28 | if (!Logger.instance) { 29 | Logger.instance = new Logger(); 30 | } 31 | return Logger.instance; 32 | } 33 | 34 | /** 35 | * Sets the active log levels. 36 | * Call with LogLevel.NONE or no arguments to turn off all logging. 37 | * Otherwise, specify one or more log levels to be active. 38 | * Use LogLevel.ALL to enable all log levels. 39 | */ 40 | public setLogLevels(...levels: LogLevel[]): void { 41 | if (levels.length === 0 || levels.includes(LogLevel.NONE)) { 42 | this.currentLogLevels = new Set(); // Turn off logging 43 | } else if (levels.includes(LogLevel.ALL)) { 44 | this.currentLogLevels = new Set([ 45 | LogLevel.ERROR, 46 | LogLevel.WARN, 47 | LogLevel.INFO, 48 | LogLevel.DEBUG 49 | ]); 50 | } else { 51 | this.currentLogLevels = new Set(levels.filter((level) => level !== LogLevel.NONE && level !== LogLevel.ALL)); 52 | } 53 | } 54 | 55 | /** 56 | * Gets the current set of active log levels. 57 | * @returns A new Set containing the active LogLevel enums. 58 | */ 59 | public getLogLevels(): Set<LogLevel> { 60 | return new Set(this.currentLogLevels); 61 | } 62 | 63 | private log(level: LogLevel, tag: string, ...messages: any[]): void { 64 | if (level !== LogLevel.NONE && this.currentLogLevels.has(level)) { 65 | const prefix = `[${LogLevel[level]}] [${tag}]`; 66 | switch (level) { 67 | case LogLevel.ERROR: 68 | console.error(prefix, ...messages); 69 | break; 70 | case LogLevel.WARN: 71 | console.warn(prefix, ...messages); 72 | break; 73 | case LogLevel.INFO: 74 | console.info(prefix, ...messages); 75 | break; 76 | case LogLevel.DEBUG: 77 | console.debug(prefix, ...messages); 78 | break; 79 | } 80 | } 81 | } 82 | 83 | public error(tag: string, ...messages: any[]): void { 84 | this.log(LogLevel.ERROR, tag, ...messages); 85 | } 86 | 87 | public warn(tag: string, ...messages: any[]): void { 88 | this.log(LogLevel.WARN, tag, ...messages); 89 | } 90 | 91 | public info(tag: string, ...messages: any[]): void { 92 | this.log(LogLevel.INFO, tag, ...messages); 93 | } 94 | 95 | public debug(tag: string, ...messages: any[]): void { 96 | this.log(LogLevel.DEBUG, tag, ...messages); 97 | } 98 | } -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/StreamerContext.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / StreamerContext 2 | 3 | # Interface: StreamerContext 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/streamer\_context.ts:12](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/streamer_context.ts#L12) 6 | 7 | ## Properties 8 | 9 | ### clientInfo? 10 | 11 | > `optional` **clientInfo**: [`ClientInfo`](ClientInfo.md) 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/streamer\_context.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/streamer_context.ts#L13) 14 | 15 | *** 16 | 17 | ### field4? 18 | 19 | > `optional` **field4**: `Uint8Array`\<`ArrayBufferLike`\> 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/streamer\_context.ts:16](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/streamer_context.ts#L16) 22 | 23 | *** 24 | 25 | ### field7? 26 | 27 | > `optional` **field7**: `string` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/streamer\_context.ts:19](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/streamer_context.ts#L19) 30 | 31 | *** 32 | 33 | ### field8? 34 | 35 | > `optional` **field8**: `StreamerContext_UnknownMessage1` 36 | 37 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/streamer\_context.ts:20](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/streamer_context.ts#L20) 38 | 39 | *** 40 | 41 | ### playbackCookie? 42 | 43 | > `optional` **playbackCookie**: `Uint8Array`\<`ArrayBufferLike`\> 44 | 45 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/streamer\_context.ts:15](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/streamer_context.ts#L15) 46 | 47 | *** 48 | 49 | ### poToken? 50 | 51 | > `optional` **poToken**: `Uint8Array`\<`ArrayBufferLike`\> 52 | 53 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/streamer\_context.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/streamer_context.ts#L14) 54 | 55 | *** 56 | 57 | ### sabrContexts 58 | 59 | > **sabrContexts**: `StreamerContext_SabrContext`[] 60 | 61 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/streamer\_context.ts:17](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/streamer_context.ts#L17) 62 | 63 | *** 64 | 65 | ### unsentSabrContexts 66 | 67 | > **unsentSabrContexts**: `number`[] 68 | 69 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/streamer\_context.ts:18](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/streamer_context.ts#L18) 70 | -------------------------------------------------------------------------------- /protos/generated/video_streaming/playback_cookie.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.7.5 4 | // protoc v5.28.0 5 | // source: video_streaming/playback_cookie.proto 6 | 7 | /* eslint-disable */ 8 | import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; 9 | import { FormatId } from "../misc/common.js"; 10 | 11 | export const protobufPackage = "video_streaming"; 12 | 13 | export interface PlaybackCookie { 14 | /** Always 999999 when resolution is set manually, or if the auto selected one is the max available resolution. */ 15 | resolution?: number | undefined; 16 | field2?: number | undefined; 17 | videoFmt?: FormatId | undefined; 18 | audioFmt?: FormatId | undefined; 19 | } 20 | 21 | function createBasePlaybackCookie(): PlaybackCookie { 22 | return { resolution: 0, field2: 0, videoFmt: undefined, audioFmt: undefined }; 23 | } 24 | 25 | export const PlaybackCookie: MessageFns<PlaybackCookie> = { 26 | encode(message: PlaybackCookie, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { 27 | if (message.resolution !== undefined && message.resolution !== 0) { 28 | writer.uint32(8).int32(message.resolution); 29 | } 30 | if (message.field2 !== undefined && message.field2 !== 0) { 31 | writer.uint32(16).int32(message.field2); 32 | } 33 | if (message.videoFmt !== undefined) { 34 | FormatId.encode(message.videoFmt, writer.uint32(58).fork()).join(); 35 | } 36 | if (message.audioFmt !== undefined) { 37 | FormatId.encode(message.audioFmt, writer.uint32(66).fork()).join(); 38 | } 39 | return writer; 40 | }, 41 | 42 | decode(input: BinaryReader | Uint8Array, length?: number): PlaybackCookie { 43 | const reader = input instanceof BinaryReader ? input : new BinaryReader(input); 44 | const end = length === undefined ? reader.len : reader.pos + length; 45 | const message = createBasePlaybackCookie(); 46 | while (reader.pos < end) { 47 | const tag = reader.uint32(); 48 | switch (tag >>> 3) { 49 | case 1: { 50 | if (tag !== 8) { 51 | break; 52 | } 53 | 54 | message.resolution = reader.int32(); 55 | continue; 56 | } 57 | case 2: { 58 | if (tag !== 16) { 59 | break; 60 | } 61 | 62 | message.field2 = reader.int32(); 63 | continue; 64 | } 65 | case 7: { 66 | if (tag !== 58) { 67 | break; 68 | } 69 | 70 | message.videoFmt = FormatId.decode(reader, reader.uint32()); 71 | continue; 72 | } 73 | case 8: { 74 | if (tag !== 66) { 75 | break; 76 | } 77 | 78 | message.audioFmt = FormatId.decode(reader, reader.uint32()); 79 | continue; 80 | } 81 | } 82 | if ((tag & 7) === 4 || tag === 0) { 83 | break; 84 | } 85 | reader.skip(tag & 7); 86 | } 87 | return message; 88 | }, 89 | }; 90 | 91 | export interface MessageFns<T> { 92 | encode(message: T, writer?: BinaryWriter): BinaryWriter; 93 | decode(input: BinaryReader | Uint8Array, length?: number): T; 94 | } 95 | -------------------------------------------------------------------------------- /docs/api/exports/protos/interfaces/NextRequestPolicy.md: -------------------------------------------------------------------------------- 1 | [googlevideo](../../../README.md) / [exports/protos](../README.md) / NextRequestPolicy 2 | 3 | # Interface: NextRequestPolicy 4 | 5 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/next\_request\_policy.ts:13](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/next_request_policy.ts#L13) 6 | 7 | ## Properties 8 | 9 | ### backoffTimeMs? 10 | 11 | > `optional` **backoffTimeMs**: `number` 12 | 13 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/next\_request\_policy.ts:17](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/next_request_policy.ts#L17) 14 | 15 | *** 16 | 17 | ### maxTimeSinceLastRequestMs? 18 | 19 | > `optional` **maxTimeSinceLastRequestMs**: `number` 20 | 21 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/next\_request\_policy.ts:16](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/next_request_policy.ts#L16) 22 | 23 | *** 24 | 25 | ### minAudioReadaheadMs? 26 | 27 | > `optional` **minAudioReadaheadMs**: `number` 28 | 29 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/next\_request\_policy.ts:18](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/next_request_policy.ts#L18) 30 | 31 | *** 32 | 33 | ### minVideoReadaheadMs? 34 | 35 | > `optional` **minVideoReadaheadMs**: `number` 36 | 37 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/next\_request\_policy.ts:19](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/next_request_policy.ts#L19) 38 | 39 | *** 40 | 41 | ### playbackCookie? 42 | 43 | > `optional` **playbackCookie**: [`PlaybackCookie`](PlaybackCookie.md) 44 | 45 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/next\_request\_policy.ts:20](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/next_request_policy.ts#L20) 46 | 47 | *** 48 | 49 | ### targetAudioReadaheadMs? 50 | 51 | > `optional` **targetAudioReadaheadMs**: `number` 52 | 53 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/next\_request\_policy.ts:14](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/next_request_policy.ts#L14) 54 | 55 | *** 56 | 57 | ### targetVideoReadaheadMs? 58 | 59 | > `optional` **targetVideoReadaheadMs**: `number` 60 | 61 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/next\_request\_policy.ts:15](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/next_request_policy.ts#L15) 62 | 63 | *** 64 | 65 | ### videoId? 66 | 67 | > `optional` **videoId**: `string` 68 | 69 | Defined in: [codeberg/googlevideo/protos/generated/video\_streaming/next\_request\_policy.ts:21](https://github.com/LuanRT/googlevideo/blob/19854137cadaf49fd755394883dfd7fe5fdaba20/protos/generated/video_streaming/next_request_policy.ts#L21) 70 | --------------------------------------------------------------------------------