extras

package
v0.3.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 9, 2026 License: GPL-3.0 Imports: 27 Imported by: 0

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

View Source
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.

View Source
const MaxExtras = 10

MaxExtras caps how many extras one title advertises.

View Source
const PinnedYTDLPVersion = "2026.10.26"

PinnedYTDLPVersion is the default official yt-dlp standalone release version installed when the owner clicks Install yt-dlp.

View Source
const SourceCommand = "command"

SourceCommand marks an Extra whose TMDB video is resolved by the owner's command.

Variables

View Source
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 ISO639

func ISO639(lang string) string

ISO639 reduces a BCP-47 tag to its ISO 639-1 language.

func IsExtractorSiteURL

func IsExtractorSiteURL(raw string) bool

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 PageURL

func PageURL(site, key string) (string, bool)

PageURL builds the public watch-page URL for a validated site key.

func ValidateSiteKey

func ValidateSiteKey(site, key string) bool

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

type CommandRunner func(ctx context.Context, name string, args []string) ([]byte, error)

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.

func (Extra) IsTrailer

func (e Extra) IsTrailer() bool

IsTrailer reports whether the extra can serve as a Cinema Trailer.

func (Extra) ThumbURL

func (e Extra) ThumbURL() string

ThumbURL returns a public thumbnail URL for an extra when the site offers one without an API call (YouTube only).

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.

func (Resolved) Input

func (r Resolved) Input() string

Input returns the ffmpeg input.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service lists, registers and resolves extras. Safe for concurrent use.

func New

func New(o Options) *Service

New builds the extras service.

func (*Service) CommandAvailable

func (s *Service) CommandAvailable() bool

CommandAvailable reports whether the resolver command source can run.

func (*Service) DisabledReason

func (s *Service) DisabledReason() string

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) Enabled

func (s *Service) Enabled() bool

Enabled reports whether any playable extras can be advertised.

func (*Service) List

func (s *Service) List(ctx context.Context, parent *core.Title, lang string) ([]Extra, error)

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) Lookup

func (s *Service) Lookup(key core.RatingKey) (Extra, bool)

Lookup returns a registered extra by rating key.

func (*Service) PrewarmBytes

func (s *Service) PrewarmBytes() int64

PrewarmBytes is the configured trailer pre-buffer size (32–64 MiB).

func (*Service) Resolve

func (s *Service) Resolve(ctx context.Context, e Extra) (Resolved, error)

Resolve turns an extra into a playable input, caching command results until the returned URL expires.

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).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL