import { BaseExtractor, ExtractorOptions } from './_base'; import { ExtractorResult } from '../types/extractors'; export declare class YoutubeExtractor extends BaseExtractor { private videoElement; private inlineJsonCache; protected schemaOrgData: any; constructor(document: Document, url: string, schemaOrgData?: any, options?: ExtractorOptions); canExtract(): boolean; canExtractAsync(): boolean; prefersAsync(): boolean; extract(): ExtractorResult; extractAsync(): Promise; private normalizeLanguageCode; private languageCodeMatchesPreference; private shouldUseExistingDomTranscript; private getCaptionTracks; private findPreferredCaptionTrack; private pickCaptionTrack; private getTrackDisplayName; private normalizeLanguageLabel; private getTranscriptLanguageCodeFromDom; private getInlineChapters; private getTranscriptContainer; private getTranscriptSelectors; private buildTranscriptFromContainer; private extractTranscriptFromExistingDom; private canOpenTranscriptPanel; private buildResult; private formatDescription; private getVideoData; private getChannelName; private getChannelNameFromDom; private getChannelNameFromMicrodata; private getChannelNameFromPlayerResponse; /** Returns ytInitialPlayerResponse only if its video ID matches the current URL (stale after SPA navigation). */ private getValidatedPlayerResponse; private parseInlineJson; private fetchTranscript; private getInlineCaptionTrack; private fetchCaptionXml; private pollFor; private waitForTranscriptSegments; private waitForTranscriptContainer; private waitForElement; private isMobileYoutube; /** * Fallback: open YouTube's transcript panel and read segments from the DOM. * Used when fetch-based extraction fails and the transcript is not already rendered. */ private extractTranscriptFromOpenedDom; /** * Mobile YouTube (m.youtube.com) transcript panel opening flow: * 1. Click "...more" to expand description * 2. Click "View all" next to Chapters to open the engagement panel * 3. Click "Timeline" tab to switch to the transcript view * 4. Wait for transcript segments to render */ private openMobileTranscriptPanel; private fetchPlayerData; private fetchChapters; private extractChaptersFromPlayerBar; private extractChaptersFromEngagementPanels; private parseTimestamp; private parseTranscriptXml; private decodeEntities; private _videoId; private getVideoId; /** * Group raw transcript segments into readable blocks. * If speaker markers (>> or -) are present, groups by speaker turn. * Otherwise, groups by sentence boundaries. */ private groupTranscriptSegments; /** * Group segments by speaker turns, then by sentences within each turn. * Each ">>" or "- " marker starts a new speaker turn (with blank line separation). * Within a turn, text is split at sentence boundaries for readability. * Tracks alternating speaker identity (0/1). */ private groupBySpeaker; /** * Split turns that start with a short affirmative response (e.g. "Mhm.", "Yeah.") * followed by longer content. The affirmative belongs to the current speaker, * but the rest is likely the other speaker (missed diarization in auto-captions). */ private splitAffirmativeTurns; private mergeSentenceGroupsWithinTurn; private shouldMergeSentenceGroups; private isShortStandaloneUtterance; /** * Group segments by sentence boundaries for transcripts without speaker markers. * Accumulates text until a segment ends with sentence-ending punctuation (.!?), * or until a very large time gap between segments. */ private groupBySentence; /** * Find the best natural break point in a list of segments. * Prefers mid-text sentence boundaries (". A") over gap-based breaks. * May splice a segment in two when a sentence boundary is found mid-text. * Returns the index to break BEFORE (i.e., flush segments 0..idx-1). */ private findNaturalBreak; }