Documentation
¶
Overview ¶
Package extras lists and resolves trailers and other clips attached to catalogue titles (Plex "Extras" and Cinema Trailers).
TMDB only gives YouTube/Vimeo keys, which official Plex apps cannot play, so an extra is only advertised when a playable source exists: an owner-configured yt-dlp-compatible resolver command that turns a video page into a direct media URL. Ether ships no resolver binary and no content.
Index ¶
- Constants
- Variables
- func ISO639(lang string) string
- func IsExtractorSiteURL(raw string) bool
- func PageURL(site, key string) (string, bool)
- func ValidateSiteKey(site, key string) bool
- type CommandRunner
- type DownloadRequest
- type DownloadResult
- type Downloader
- func (d *Downloader) Download(ctx context.Context, req DownloadRequest) (DownloadResult, error)
- func (d *Downloader) EffectiveCommand() (cmd string, source string, version string, ok bool)
- func (d *Downloader) Install(ctx context.Context, update bool) (DownloaderStatus, error)
- func (d *Downloader) Status() DownloaderStatus
- func (d *Downloader) VerifiedManagedBinary() (string, string, bool)
- type DownloaderOptions
- type DownloaderStatus
- type Extra
- type Options
- type Resolved
- type Service
- func (s *Service) CommandAvailable() bool
- func (s *Service) DisabledReason() string
- func (s *Service) Downloader() *Downloader
- func (s *Service) Enabled() bool
- func (s *Service) List(ctx context.Context, parent *core.Title, lang string) ([]Extra, error)
- func (s *Service) Lookup(key core.RatingKey) (Extra, bool)
- func (s *Service) PrewarmBytes() int64
- func (s *Service) Resolve(ctx context.Context, e Extra) (Resolved, error)
- type VideoProvider
Constants ¶
const DefaultResolverCommand = "yt-dlp"
DefaultResolverCommand is used when the owner enabled trailers but set no resolver command. It is resolved on PATH at use time and never written into the saved config.
const MaxExtras = 10
MaxExtras caps how many extras one title advertises.
const PinnedYTDLPVersion = "2026.10.26"
PinnedYTDLPVersion is the default official yt-dlp standalone release version installed when the owner clicks Install yt-dlp.
const SourceCommand = "command"
SourceCommand marks an Extra whose TMDB video is resolved by the owner's command.
Variables ¶
var DefaultResolverArgs = []string{"-g", "-f", "b[ext=mp4]/b", "--no-playlist", "{url}"}
DefaultResolverArgs is the yt-dlp-compatible template used when the owner configured a command but no arguments: print one single-file media URL for the watch page.
Functions ¶
func IsExtractorSiteURL ¶
IsExtractorSiteURL reports whether raw points to a known video/audio platform watch page that requires a yt-dlp-compatible extractor rather than a direct file GET.
func ValidateSiteKey ¶
ValidateSiteKey reports whether a TMDB site/key pair is a well-formed video id Ether may hand to the resolver. Anything else is rejected before it can reach a command line.
Types ¶
type CommandRunner ¶
CommandRunner runs the resolver command and returns its stdout. Tests substitute a fake; the default is exec without a shell.
type DownloadRequest ¶
type DownloadRequest struct {
URL string
Kind string // "video" or "audio"
Reel bool
MaxBytes int64
MaxDuration time.Duration
OutputDir string
Progress func(float64)
}
DownloadRequest describes a bounded single-video or audio download job.
type DownloadResult ¶
type DownloadResult struct {
Path string
ResolvedURL string
Headers map[string]string
Title string
Attribution string
Duration time.Duration
}
DownloadResult holds either the local file downloaded by yt-dlp or a resolved direct stream URL from a custom resolver command, along with provenance metadata.
type Downloader ¶
type Downloader struct {
// contains filtered or unexported fields
}
Downloader manages the owner-initiated yt-dlp binary in Ether's data dir and runs bounded single-video downloads using the shared Extras resolver config.
func NewDownloader ¶
func NewDownloader(o DownloaderOptions) *Downloader
NewDownloader builds a Downloader sharing the Extras resolver configuration.
func (*Downloader) Download ¶
func (d *Downloader) Download(ctx context.Context, req DownloadRequest) (DownloadResult, error)
Download resolves and downloads a single video or audio clip from a page URL using the configured yt-dlp-compatible command without a shell.
func (*Downloader) EffectiveCommand ¶
func (d *Downloader) EffectiveCommand() (cmd string, source string, version string, ok bool)
EffectiveCommand resolves the command to run: 1. Owner-configured config.Extras.ResolverCommand if non-empty; 2. Verified managed yt-dlp binary in Ether's data dir; 3. Default "yt-dlp" on PATH.
func (*Downloader) Install ¶
func (d *Downloader) Install(ctx context.Context, update bool) (DownloaderStatus, error)
Install downloads or updates the official standalone yt-dlp release binary into Ether's data dir after verifying its SHA-256 against the release's published SHA2-256SUMS (and the pinned digest for PinnedYTDLPVersion).
func (*Downloader) Status ¶
func (d *Downloader) Status() DownloaderStatus
Status reports the current resolver/downloader state for the console.
func (*Downloader) VerifiedManagedBinary ¶
func (d *Downloader) VerifiedManagedBinary() (string, string, bool)
VerifiedManagedBinary returns the path and version of the managed yt-dlp binary only when its metadata and SHA-256 digest are verified. An unverified or modified binary is never returned or executed.
type DownloaderOptions ¶
type DownloaderOptions struct {
ToolsDir string
Config func() config.Extras
Runner CommandRunner
LookPath func(string) (string, error)
FFmpeg func() string
ReleaseURL string
Client *http.Client
GOOS string
GOARCH string
Now func() time.Time
}
DownloaderOptions configures managed yt-dlp discovery, installation and media downloads.
type DownloaderStatus ¶
type DownloaderStatus struct {
Available bool `json:"available"`
Source string `json:"source"` // "managed", "path", "configured", "none"
Version string `json:"version,omitempty"`
PinnedVersion string `json:"pinnedVersion"`
CanInstall bool `json:"canInstall"`
CanUpdate bool `json:"canUpdate"`
}
DownloaderStatus describes the active yt-dlp-compatible command and managed binary installation state for the console.
type Extra ¶
type Extra struct {
Key core.RatingKey // KindExtra
ParentKey core.RatingKey
ParentTitle string
Title string
Subtype string // Plex subtype: trailer, teaser, clip, featurette, behindTheScenes
ExtraType int // Plex numeric extra type (1 = trailer)
Site string // YouTube, Vimeo (command source)
SiteKey string // site-specific video id
Language string // ISO 639-1
Official bool
PublishedAt time.Time
Size int // vertical resolution when known
Duration time.Duration
Source string // SourceCommand
// contains filtered or unexported fields
}
Extra is one playable clip attached to a title.
type Options ¶
type Options struct {
Videos VideoProvider
Config func() config.Extras
Logger *slog.Logger
Now func() time.Time
CacheTTL time.Duration // list cache; default 1h
Runner CommandRunner
LookPath func(string) (string, error)
ToolsDir string
Downloader *Downloader
}
Options are the extras service dependencies.
type Resolved ¶
type Resolved struct {
URL string // direct media URL
Headers map[string]string
Expires time.Time
Container string
}
Resolved is a playable location for an extra.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service lists, registers and resolves extras. Safe for concurrent use.
func (*Service) CommandAvailable ¶
CommandAvailable reports whether the resolver command source can run.
func (*Service) DisabledReason ¶
DisabledReason explains why extras are off, for a startup log line. Empty when enabled.
func (*Service) Downloader ¶
func (s *Service) Downloader() *Downloader
Downloader returns the managed yt-dlp downloader shared with this service.
func (*Service) List ¶
List returns the playable extras of a title, best first: official trailers in the viewer's language ahead of everything else. It returns nothing when extras are disabled or no source can play them.
func (*Service) PrewarmBytes ¶
PrewarmBytes is the configured trailer pre-buffer size (32–64 MiB).
type VideoProvider ¶
type VideoProvider interface {
MovieVideos(ctx context.Context, id int64, lang string) ([]tmdb.Video, error)
TVVideos(ctx context.Context, id int64, lang string) ([]tmdb.Video, error)
SeasonVideos(ctx context.Context, tvID int64, season int, lang string) ([]tmdb.Video, error)
EpisodeVideos(ctx context.Context, tvID int64, season, episode int, lang string) ([]tmdb.Video, error)
}
VideoProvider is the TMDB videos surface the service needs (*tmdb.Client satisfies it).