feat(StreamingInfoOptions)!: Add is_sabr option (#974)

Returns a manifest suitable for use in SABR player implementations.
This commit is contained in:
Luan
2025-06-08 07:02:10 -03:00
committed by GitHub
parent f202bcdeb7
commit 561e60b934
3 changed files with 50 additions and 32 deletions

View File

@@ -315,13 +315,20 @@ function getSegmentInfo(
actions?: Actions,
player?: Player,
cpn?: string,
shared_post_live_dvr_info?: SharedPostLiveDvrInfo
shared_post_live_dvr_info?: SharedPostLiveDvrInfo,
is_sabr?: boolean
) {
const url = new URL(format.decipher(player));
url.searchParams.set('cpn', cpn || '');
const transformed_url = url_transformer(url).toString();
let transformed_url = '';
if (is_sabr) {
const formatKey = `${format.itag || ''}:${format.xtags || ''}`;
transformed_url = `sabr://${format.has_video ? 'video' : 'audio'}?key=${formatKey}`;
} else {
const url = new URL(format.decipher(player));
url.searchParams.set('cpn', cpn || '');
transformed_url = url_transformer(url).toString();
}
if (format.is_type_otf) {
if (!actions)
throw new InnertubeError('Unable to get segment durations for this OTF stream without an Actions instance', { format });
@@ -392,11 +399,9 @@ function getAudioRepresentation(
actions?: Actions,
player?: Player,
cpn?: string,
shared_post_live_dvr_info?: SharedPostLiveDvrInfo
shared_post_live_dvr_info?: SharedPostLiveDvrInfo,
is_sabr?: boolean
) {
const url = new URL(format.decipher(player));
url.searchParams.set('cpn', cpn || '');
const uid_parts = [ format.itag.toString() ];
if (format.audio_track) {
@@ -413,7 +418,7 @@ function getAudioRepresentation(
codecs: !hoisted.includes('codecs') ? getStringBetweenStrings(format.mime_type, 'codecs="', '"') : undefined,
audio_sample_rate: !hoisted.includes('audio_sample_rate') ? format.audio_sample_rate : undefined,
channels: !hoisted.includes('AudioChannelConfiguration') ? format.audio_channels || 2 : undefined,
segment_info: getSegmentInfo(format, url_transformer, actions, player, cpn, shared_post_live_dvr_info)
segment_info: getSegmentInfo(format, url_transformer, actions, player, cpn, shared_post_live_dvr_info, is_sabr)
};
return rep;
@@ -447,7 +452,8 @@ function getAudioSet(
player?: Player,
cpn?: string,
shared_post_live_dvr_info?: SharedPostLiveDvrInfo,
drc_labels?: DrcLabels
drc_labels?: DrcLabels,
is_sabr?: boolean
) {
const first_format = formats[0];
const { audio_track } = first_format;
@@ -475,7 +481,7 @@ function getAudioSet(
track_name,
track_roles: getTrackRoles(first_format, has_drc_streams),
channels: hoistAudioChannelsIfPossible(formats, hoisted),
representations: formats.map((format) => getAudioRepresentation(format, hoisted, url_transformer, actions, player, cpn, shared_post_live_dvr_info))
representations: formats.map((format) => getAudioRepresentation(format, hoisted, url_transformer, actions, player, cpn, shared_post_live_dvr_info, is_sabr))
};
return set;
@@ -556,7 +562,8 @@ function getVideoRepresentation(
player?: Player,
actions?: Actions,
cpn?: string,
shared_post_live_dvr_info?: SharedPostLiveDvrInfo
shared_post_live_dvr_info?: SharedPostLiveDvrInfo,
is_sabr?: boolean
) {
const rep: VideoRepresentation = {
uid: format.itag.toString(),
@@ -565,7 +572,7 @@ function getVideoRepresentation(
height: format.height,
codecs: !hoisted.includes('codecs') ? getStringBetweenStrings(format.mime_type, 'codecs="', '"') : undefined,
fps: !hoisted.includes('fps') ? format.fps : undefined,
segment_info: getSegmentInfo(format, url_transformer, actions, player, cpn, shared_post_live_dvr_info)
segment_info: getSegmentInfo(format, url_transformer, actions, player, cpn, shared_post_live_dvr_info, is_sabr)
};
return rep;
@@ -577,7 +584,8 @@ function getVideoSet(
player?: Player,
actions?: Actions,
cpn?: string,
shared_post_live_dvr_info?: SharedPostLiveDvrInfo
shared_post_live_dvr_info?: SharedPostLiveDvrInfo,
is_sabr?: boolean
) {
const first_format = formats[0];
const color_info = getColorInfo(first_format);
@@ -588,7 +596,7 @@ function getVideoSet(
color_info,
codecs: hoistCodecsIfPossible(formats, hoisted),
fps: hoistNumberAttributeIfPossible(formats, 'fps', hoisted),
representations: formats.map((format) => getVideoRepresentation(format, url_transformer, hoisted, player, actions, cpn, shared_post_live_dvr_info))
representations: formats.map((format) => getVideoRepresentation(format, url_transformer, hoisted, player, actions, cpn, shared_post_live_dvr_info, is_sabr))
};
return set;
@@ -860,9 +868,9 @@ export function getStreamingInfo(
};
}
const audio_sets = audio_groups.map((formats) => getAudioSet(formats, url_transformer, actions, player, cpn, shared_post_live_dvr_info, drc_labels));
const audio_sets = audio_groups.map((formats) => getAudioSet(formats, url_transformer, actions, player, cpn, shared_post_live_dvr_info, drc_labels, options?.is_sabr));
const video_sets = video_groups.map((formats) => getVideoSet(formats, url_transformer, player, actions, cpn, shared_post_live_dvr_info));
const video_sets = video_groups.map((formats) => getVideoSet(formats, url_transformer, player, actions, cpn, shared_post_live_dvr_info, options?.is_sabr));
let image_sets: ImageSet[] = [];