Fix album header parsing for new musicResponsiveHeaderRenderer structure

This commit is contained in:
Your Name
2026-01-11 11:51:16 +01:00
parent 3da6ce3973
commit 68ce5b4d8e

70
lib.ts
View File

@@ -70,49 +70,65 @@ export class YTMusic {
async getAlbum(browseId: string) { async getAlbum(browseId: string) {
const data = await this.makeRequest("browse", { browseId }); const data = await this.makeRequest("browse", { browseId });
// Handle different header types
const header = data?.header?.musicDetailHeaderRenderer ||
data?.header?.musicImmersiveHeaderRenderer ||
data?.header?.musicVisualHeaderRenderer || {};
// Handle both single and two column layouts // Handle both single and two column layouts
const singleColumn = data?.contents?.singleColumnBrowseResultsRenderer?.tabs?.[0]?.tabRenderer?.content?.sectionListRenderer?.contents; const singleColumn = data?.contents?.singleColumnBrowseResultsRenderer?.tabs?.[0]?.tabRenderer?.content?.sectionListRenderer?.contents;
const twoColumn = data?.contents?.twoColumnBrowseResultsRenderer?.secondaryContents?.sectionListRenderer?.contents; const twoColumnPrimary = data?.contents?.twoColumnBrowseResultsRenderer?.tabs?.[0]?.tabRenderer?.content?.sectionListRenderer?.contents;
const contents = singleColumn || twoColumn || []; const twoColumnSecondary = data?.contents?.twoColumnBrowseResultsRenderer?.secondaryContents?.sectionListRenderer?.contents;
// Extract title and artist from header // Get header from different possible locations
const title = header.title?.runs?.[0]?.text; let title = "";
const subtitleRuns = header.subtitle?.runs || header.straplineTextOne?.runs || []; let artist = "";
const artist = subtitleRuns.find((r: any) => r.navigationEndpoint)?.text || subtitleRuns[0]?.text; let thumbnail = "";
// Get thumbnail
const thumbnail = header.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.slice(-1)[0]?.url ||
header.thumbnail?.croppedSquareThumbnailRenderer?.thumbnail?.thumbnails?.slice(-1)[0]?.url;
// Parse tracks
const tracks = this.parseTracksFromContents(contents);
// Get album metadata from two column layout
const primaryContents = data?.contents?.twoColumnBrowseResultsRenderer?.tabs?.[0]?.tabRenderer?.content?.sectionListRenderer?.contents || [];
let year = ""; let year = "";
let trackCount = tracks.length;
// Check old header location
const oldHeader = data?.header?.musicDetailHeaderRenderer ||
data?.header?.musicImmersiveHeaderRenderer ||
data?.header?.musicVisualHeaderRenderer;
if (oldHeader) {
title = oldHeader.title?.runs?.[0]?.text;
const subtitleRuns = oldHeader.subtitle?.runs || oldHeader.straplineTextOne?.runs || [];
artist = subtitleRuns.find((r: any) => r.navigationEndpoint)?.text || subtitleRuns[0]?.text;
thumbnail = oldHeader.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.slice(-1)[0]?.url ||
oldHeader.thumbnail?.croppedSquareThumbnailRenderer?.thumbnail?.thumbnails?.slice(-1)[0]?.url;
}
// Check new header location (musicResponsiveHeaderRenderer in contents)
const primaryContents = twoColumnPrimary || singleColumn || [];
for (const section of primaryContents) { for (const section of primaryContents) {
const descShelf = section.musicDescriptionShelfRenderer; if (section.musicResponsiveHeaderRenderer) {
if (descShelf) { const h = section.musicResponsiveHeaderRenderer;
const subHeader = descShelf.subheader?.runs?.[0]?.text || ""; title = h.title?.runs?.[0]?.text || title;
const subtitleRuns = h.straplineTextOne?.runs || h.subtitle?.runs || [];
artist = subtitleRuns.find((r: any) => r.navigationEndpoint)?.text || subtitleRuns[0]?.text || artist;
thumbnail = h.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.slice(-1)[0]?.url || thumbnail;
// Get year from subtitle
const secondSubtitle = h.subtitle?.runs || [];
for (const run of secondSubtitle) {
const yearMatch = run.text?.match(/\d{4}/);
if (yearMatch) year = yearMatch[0];
}
}
if (section.musicDescriptionShelfRenderer) {
const subHeader = section.musicDescriptionShelfRenderer.subheader?.runs?.[0]?.text || "";
const yearMatch = subHeader.match(/\d{4}/); const yearMatch = subHeader.match(/\d{4}/);
if (yearMatch) year = yearMatch[0]; if (yearMatch && !year) year = yearMatch[0];
} }
} }
// Parse tracks from secondary contents
const trackContents = twoColumnSecondary || singleColumn || [];
const tracks = this.parseTracksFromContents(trackContents);
return { return {
browseId, browseId,
title, title,
artist, artist,
thumbnail, thumbnail,
year, year,
trackCount, trackCount: tracks.length,
tracks, tracks,
}; };
} }