Documentation
¶
Overview ¶
Package youtube performs YouTube extraction: it turns a URL into video metadata and candidate audio formats, and resolves those formats into playable, signed stream URLs.
Stability: this package and everything beneath it, notably the internal resolver, are YouTube-specific implementation surfaces. They are exported for the facade where needed but may change between releases. External users should prefer the top-level waxtap package.
Concurrency and identity: a ClientProfile is immutable, with headers cloned on read. Mutable per-attempt state lives in an unexported session, so concurrent extractions do not share writable client identity.
Index ¶
- func ExtractPlaylistID(input string) (string, error)
- func ExtractVideoID(input string) (string, error)
- type Chapter
- type Client
- func (c *Client) Enumerate(ctx context.Context, playlistID string, maxItems int) (*Playlist, error)
- func (c *Client) Extract(ctx context.Context, videoID string) (*Extraction, error)
- func (c *Client) Info(ctx context.Context, videoID string) (*Video, error)
- func (c *Client) Resolve(ctx context.Context, ext *Extraction, formatIndex int) (ResolvedStream, error)
- func (c *Client) ResolveWithFailure(ctx context.Context, ext *Extraction, formatIndex int, ...) (ResolvedStream, error)
- type ClientProfile
- type Config
- type Extraction
- type Playlist
- type PlaylistEntry
- type ResolvedStream
- type Thumbnail
- type Video
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExtractPlaylistID ¶
ExtractPlaylistID extracts a playlist ID from a bare ID or a URL carrying a list= parameter.
func ExtractVideoID ¶
ExtractVideoID extracts an 11-character video ID from a bare ID or any common YouTube URL form (watch?v=, youtu.be/, /embed/, /shorts/, /v/, /live/), including scheme-less inputs.
A playlist-only URL (a list= parameter or /playlist path with no video) returns ErrIsPlaylist so the caller can route it to Enumerate. Inputs that carry a candidate of the wrong shape return ErrInvalidVideoID; inputs too short to contain an ID return ErrVideoIDTooShort.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client performs YouTube extraction. It holds configuration and injected dependencies, while mutable per-attempt identity lives in session. It is safe for concurrent use after construction.
func (*Client) Enumerate ¶
Enumerate expands a playlist into lightweight entries without downloading. It pages through continuations until exhausted or maxItems (<= 0 means all) is reached. Per-page failures after the first page are collected in Playlist.Errors rather than discarding the entries already gathered.
func (*Client) Extract ¶
Extract fetches metadata and candidate audio formats for videoID, trying the client strategy chain in order until one succeeds. Each attempt uses an immutable profile and a shared per-extraction session; the winning profile and session are carried in the returned Extraction so stream resolution uses the same identity.
func (*Client) Resolve ¶
func (c *Client) Resolve(ctx context.Context, ext *Extraction, formatIndex int) (ResolvedStream, error)
Resolve turns the candidate at formatIndex, an index into Extraction.Video().Formats, into a playable signed stream. It reuses the client profile and session that won extraction so the media URL is resolved under the same YouTube identity.
Resolution is index-based rather than itag-based because itags can repeat across languages and DRC variants. rawAudio[i] is kept parallel to Video.Formats[i] so the selected public format maps to the right raw format.
func (*Client) ResolveWithFailure ¶
func (c *Client) ResolveWithFailure(ctx context.Context, ext *Extraction, formatIndex int, failure *potoken.HTTPFailure) (ResolvedStream, error)
ResolveWithFailure resolves the selected format like Resolve and passes the HTTP failure that caused a refresh to the PO-token provider. Initial resolution passes nil. When refreshing an expired signed URL, call this with a fresh Extraction; the old player response still contains the old URL.
type ClientProfile ¶
type ClientProfile struct {
Name string // internal name, e.g. "ANDROID_VR"
InnerTubeName string // InnerTube context clientName, e.g. "ANDROID_VR"
InnerTubeID int // drives X-Youtube-Client-Name (never hardcoded)
Version string
APIKey string
UserAgent string
// Device and OS fields sent in the InnerTube client context. Mobile and VR
// clients need these populated; sparse identities are more likely to hit the
// bot-check path. Zero values are omitted from the request.
DeviceMake string
DeviceModel string
OSName string
OSVersion string
AndroidSDKVersion int
// RequiresPOTokens lists the PO-token scopes this client must supply: a
// player-scope token in the /player body, a GVS token on the stream URL,
// or both. Empty means none. NewClientProfile clones and canonicalizes
// the slice.
RequiresPOTokens []potoken.Scope
SupportsCookies bool
SupportsPlaylists bool
// contains filtered or unexported fields
}
ClientProfile identifies an InnerTube client such as ANDROID_VR, iOS, or WEB. The header map is unexported and every accessor returns a clone, so callers cannot mutate a profile after construction.
func BuildProfile ¶
func BuildProfile(base ClientProfile) ClientProfile
BuildProfile derives the static InnerTube request headers from base and returns an isolated profile. Use it for configured profiles so headers such as X-Youtube-Client-Name stay tied to the scalar client identity.
func DefaultProfiles ¶
func DefaultProfiles() []ClientProfile
DefaultProfiles returns the ordered client strategy chain using the default built-in Chrome identity. ANDROID_VR leads because it usually returns direct URLs without a PO token; the embedded and WEB clients cover fallback cases.
func NewClientProfile ¶
func NewClientProfile(base ClientProfile, headers map[string]string) ClientProfile
NewClientProfile returns base with headers deep-copied in, yielding a profile that owns an isolated header map callers cannot mutate.
func (ClientProfile) Header ¶
func (p ClientProfile) Header(key string) string
Header returns a single header value.
func (ClientProfile) Headers ¶
func (p ClientProfile) Headers() map[string]string
Headers returns a copy of the profile's headers; mutating the result does not affect the profile.
func (ClientProfile) WithHeader ¶
func (p ClientProfile) WithHeader(key, value string) ClientProfile
WithHeader returns a copy of the profile with key set to value; the receiver is unchanged.
type Config ¶
type Config struct {
// HTTP is the retrying HTTP client. If nil, a default httpx.Client is used.
HTTP *httpx.Client
// Logger receives debug logs. If nil, logging is discarded.
Logger *slog.Logger
// Profiles overrides the client strategy chain. If empty, DefaultProfiles().
Profiles []ClientProfile
// ChromeMajor overrides the emulated Chrome major for built-in WEB-family
// identities. It applies to the default profile chain and to built-in WEB
// requests used for discovery and fallbacks. Zero selects the built-in
// default. Caller-supplied Profiles are unchanged.
ChromeMajor int
// Resolver resolves candidate formats into playable URLs. If nil, New builds
// a default base.js/goja resolver over the same HTTP client. Metadata
// extraction does not need one; stream resolution (Resolve) does.
Resolver resolver.Resolver
// POTokenProvider supplies PO tokens when a profile requires one. WaxTap may
// call it during extraction for a player-scope token and during resolution for
// a GVS-scope stream token. Nil means no provider is configured.
POTokenProvider potoken.Provider
// ResolveTimeout bounds each cipher JS execution during resolution. Zero
// uses the resolver default.
ResolveTimeout time.Duration
// CacheDir is the base directory for on-disk caches. When set, and when
// DisableDiskCache is false, the default resolver stores base.js source under
// CacheDir/players. Empty leaves the resolver memory-only. Ignored when a
// Resolver is injected.
CacheDir string
// DisableDiskCache turns off the on-disk base.js source cache even when
// CacheDir is set.
DisableDiskCache bool
// HL (host language, e.g. "en") and GL (content region, e.g. "US") set the
// InnerTube locale. Empty defaults to en / US. These are localization hints:
// geo-restricted availability is still governed by the request IP.
HL string
GL string
}
Config configures a Client.
type Extraction ¶
type Extraction struct {
// contains filtered or unexported fields
}
Extraction is the result of a successful extract: the video plus the opaque context (which client profile and session won) needed to resolve and download in the same identity. Its internals are unexported, so the facade holds it as an opaque handle and passes it back into resolve/download without reaching in.
func (*Extraction) Video ¶
func (e *Extraction) Video() *Video
Video returns the extracted metadata and candidate formats.
type Playlist ¶
type Playlist struct {
ID string
Title string
Author string
Entries []PlaylistEntry
Errors []error // per-entry failures (partial enumeration is not fatal)
Continuation string // opaque token for the next page; "" when exhausted
}
Playlist is the result of enumerating a playlist URL. Enumeration is tolerant: one bad entry is collected in Errors rather than failing the list.
type PlaylistEntry ¶
type PlaylistEntry struct {
VideoID string
Title string
Author string
Duration time.Duration
Index int // 0-based position within the playlist
}
PlaylistEntry is a lightweight playlist item. Enumeration does not download media, and full per-video metadata enrichment is opt-in.
type ResolvedStream ¶
type ResolvedStream struct {
URL string
ExpiresAt time.Time
ContentLength int64
Headers http.Header
}
ResolvedStream is a resolved, playable stream URL with the metadata needed to fetch it. youtube owns this type: resolver.Stream is mapped into it by the youtube package, and download.Source is mapped from it by the facade.
type Video ¶
type Video struct {
ID string
Title string
Author string // channel / uploader name
ChannelID string
Duration time.Duration
PublishDate time.Time
Description string
Thumbnails []Thumbnail // candidates for cover art
Chapters []Chapter
Formats []format.Format // candidate audio (and incidental video) formats
IsLive bool // currently live
IsUpcoming bool // scheduled premiere / upcoming
}
Video is the extracted metadata model. YouTube exposes channel metadata rather than authoritative artist tags, so WaxTap returns the raw fields and leaves tagging policy to the caller.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
internal
|
|
|
resolver
Package resolver isolates YouTube's most volatile surface: discovering the player JS (base.js), solving the signature and n-parameter transforms, and building a playable, signed stream URL.
|
Package resolver isolates YouTube's most volatile surface: discovering the player JS (base.js), solving the signature and n-parameter transforms, and building a playable, signed stream URL. |