Help us shape the future of Go! Take the 2026 Go Developer Survey

transcode

package
v0.2.7 Latest Latest
Warning

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

Go to latest
Published: Oct 22, 2026 License: GPL-3.0 Imports: 35 Imported by: 0

Documentation

Overview

Package transcode wraps Ether's bundled ffmpeg: discovery, hardware encoder detection, probing, the direct play / remux / transcode decision and HLS and MPEG-DASH sessions. Manager implements core.Transcoder.

Index

Constants

View Source
const (
	ContainerMPEGTS   = "mpegts"
	ContainerFMP4     = "fmp4"
	ContainerMatroska = "mkv"
)

HLS segment containers reported in core.Decision.Container.

View Source
const (
	AccelNone         = "none"
	AccelVideoToolbox = "videotoolbox"
	AccelNVENC        = "nvenc"
	AccelQSV          = "qsv"
	AccelVAAPI        = "vaapi"
)

Hardware accelerator names, as used in config.Transcode.HWAccel and core.HWAccel.Name.

View Source
const DefaultDASHSegmentDuration = 5 * time.Second

DefaultDASHSegmentDuration is the DASH segment length when a request leaves it unset; PMS uses 5 s.

View Source
const DefaultSegmentDuration = 4 * time.Second

DefaultSegmentDuration is the HLS segment length when a request leaves it unset.

View Source
const DefaultVAAPIDevice = "/dev/dri/renderD128"

DefaultVAAPIDevice is the render node used when none is configured.

View Source
const InitSegment = -1

InitSegment is the segment number ServeSegment uses for the fMP4 initialization segment (init.mp4).

View Source
const InitSegmentName = "init.mp4"

InitSegmentName is the init segment's URI in media playlists.

View Source
const MatroskaHeaderName = "header"

MatroskaHeaderName matches Plex's segmented-Matroska initialization URI.

Variables

View Source
var ErrFFmpegNotFound = errors.New("transcode: ffmpeg not found")

ErrFFmpegNotFound means no usable ffmpeg/ffprobe executable was found in the configured path, the bundled locations or PATH.

View Source
var ErrImageSubtitle = errors.New("transcode: bitmap subtitles cannot be converted to text")

ErrImageSubtitle is returned when a bitmap subtitle is asked for as text.

View Source
var ErrIncompatibleSwap = errors.New("transcode: replacement cannot match the delivered video")

ErrIncompatibleSwap reports a replacement source whose video cannot be delivered in the session's fixed output contract.

View Source
var ErrNoCues = errors.New("transcode: no subtitle cues found")

ErrNoCues means the input held no parsable subtitle cues.

View Source
var ErrPauseUnsupported = errors.New("transcode: pausing processes is not supported on this platform")

ErrPauseUnsupported is returned by Process.Pause on platforms that cannot suspend a process.

View Source
var ErrProbeIncomplete = errors.New("transcode: native probe incomplete")

ErrProbeIncomplete means native probing cannot vouch for the stream parameters; ffprobe must run.

View Source
var ErrTooManyTranscodes = errors.New("transcode: too many concurrent transcodes")

ErrTooManyTranscodes is returned by StartHLS when config MaxTranscodes video transcodes are already running. Remuxes are not counted.

Functions

func Decide

func Decide(info core.MediaInfo, caps core.ClientCaps, opts core.DecideOptions, pol Policy) core.Decision

Decide chooses direct play, remux into HLS, or full transcode, in that order of preference, and explains why in Decision.Reason.

func DownloadCopyable

func DownloadCopyable(info core.MediaInfo, audioStream int) (video, audio *core.StreamInfo, ok bool)

DownloadCopyable reports whether info's video (and chosen audio) can be stream-copied to MP4, returning the streams a remux would keep.

func HLSContainer

func HLSContainer(caps core.ClientCaps, videoCodec, audioCodec string) string

HLSContainer preserves explicit client targets separately from the formats its direct-play decoder accepts. Plex's enhanced player requests segmented Matroska; AVPlayer and browser HLS keep the standard TS/fMP4 path.

func HLSVariantAttributes

func HLSVariantAttributes(info core.MediaInfo, d core.Decision) string

HLSVariantAttributes describes the output selected by the media decision. Apple HLS requires CODECS; HDR and Dolby Vision also need explicit signaling. https://developer.apple.com/streaming/hls-authoring-specification-for-apple-devices.html

func IsImageSubtitle

func IsImageSubtitle(codec string) bool

IsImageSubtitle reports whether a subtitle codec is bitmap-based and so must be burned in to be shown in HLS.

func IsJPEG

func IsJPEG(b []byte) bool

IsJPEG reports whether b starts with the JPEG SOI marker.

func IsTextSubtitle

func IsTextSubtitle(codec string) bool

IsTextSubtitle reports whether a subtitle codec can be converted to WebVTT.

func MarshalBIF

func MarshalBIF(frames []BIFFrame) ([]byte, error)

MarshalBIF encodes frames as a BIF file. Frames are sorted by time (stable, on a copy) and duplicate timestamps keep the first frame, so the output is deterministic for a given input order. At least one frame with image data is required.

func NormalizeCodec

func NormalizeCodec(c string) string

NormalizeCodec maps ffprobe codec names to Ether/Plex codec names.

func NormalizeContainer

func NormalizeContainer(formatName string) string

NormalizeContainer maps an ffprobe format_name to Ether's container name.

func ParseProbe

func ParseProbe(b []byte) (*core.MediaInfo, error)

ParseProbe maps ffprobe -print_format json -show_format -show_streams output to MediaInfo.

func ParseSegmentName

func ParseSegmentName(name string) (int, bool)

ParseSegmentName parses a segment URI produced by SegmentName (or InitSegmentName) back to its number; init.mp4 yields InitSegment.

func PlexDASHURLs

func PlexDASHURLs(sessionID string) (string, string)

PlexDASHURLs is the URL layout real PMS uses (captured from a PMS start.mpd): segments live next to start.mpd under session/{id}/.

func ProbeSource added in v0.2.4

func ProbeSource(ctx context.Context, src io.ReaderAt, size int64) (*core.MediaInfo, error)

ProbeSource probes a media source natively: Matroska/WebM and MP4/MOV/M4V. Other containers return ErrProbeIncomplete.

func ProbeTrailer added in v0.2.4

func ProbeTrailer(ctx context.Context, src io.ReaderAt, size int64, m *core.MediaInfo) bool

ProbeTrailer reads metadata Matroska keeps after the media (tail Chapters, mkvmerge statistics tags). It fills only facts that are not already known and never changes stream identity or codec parameters, so it can run after playback has started.

func SRTToVTT

func SRTToVTT(dst io.Writer, src io.Reader) error

SRTToVTT converts SubRip to WebVTT (OpenSubtitles sidecars to HLS/Plex web clients).

func SegmentName

func SegmentName(n int, container string) string

SegmentName is the default playlist URI of segment n: "00042.ts" or "00042.m4s" or "00042.mkv" (relative to index.m3u8).

func SupportsDVProfile

func SupportsDVProfile(c core.ClientCaps, profile int) bool

SupportsDVProfile requires both the generic DV flag and a compatible profile. With no model evidence an unspecified profile is accepted only if the client explicitly advertised DV; known unsupported profiles use their base layer.

func VTTToSRT

func VTTToSRT(dst io.Writer, src io.Reader) error

VTTToSRT converts WebVTT to SubRip. Cue settings and WebVTT-only markup (voice, class, timestamp tags) are dropped; <i>, <b>, <u> are kept.

func WriteBIF

func WriteBIF(w io.Writer, frames []BIFFrame) error

WriteBIF is MarshalBIF into w.

func WriteSRT

func WriteSRT(dst io.Writer, cues []Cue) error

WriteSRT writes cues as a SubRip file.

func WriteVTT

func WriteVTT(dst io.Writer, cues []Cue) error

WriteVTT writes cues as a WebVTT file.

Types

type BIF

type BIF struct {
	Version    uint32
	Multiplier uint32 // ms per timestamp unit
	// contains filtered or unexported fields
}

BIF is a parsed BIF file.

func ParseBIF

func ParseBIF(data []byte) (*BIF, error)

ParseBIF parses a whole BIF file held in memory.

func (*BIF) Frame

func (b *BIF) Frame(i int) []byte

Frame returns the JPEG bytes of frame i (a sub-slice of the input).

func (*BIF) FrameAt

func (b *BIF) FrameAt(at time.Duration) ([]byte, bool)

FrameAt returns the latest frame at or before at, if any.

func (*BIF) Len

func (b *BIF) Len() int

Len is the number of frames.

func (*BIF) Time

func (b *BIF) Time(i int) time.Duration

Time returns the media time of frame i.

type BIFFrame

type BIFFrame struct {
	Time time.Duration
	JPEG []byte
}

BIFFrame is one thumbnail: the media time it shows and its JPEG bytes.

type ClientPolicy

type ClientPolicy struct {
	Family              string   `json:"family"`
	DolbyVisionProfiles []int    `json:"dolbyVisionProfiles"`
	SubtitleCodecs      []string `json:"subtitleCodecs"`
	Notes               string   `json:"notes"`
}

ClientPolicy records conservative product quirks, not device certification. Headers/profile declarations remain authoritative; model/display/audio chain capabilities must not be inferred from a platform name alone.

func ClientPolicies

func ClientPolicies() []ClientPolicy

ClientPolicies is the owner-facing supplemental quirk matrix. It describes defaults only; a real request's profile and hardware declarations refine it.

func ClientPolicyFor

func ClientPolicyFor(c core.ClientCaps) ClientPolicy

type Command

type Command struct {
	Path   string
	Args   []string
	Dir    string
	Stdout io.Writer
	Stderr io.Writer
}

Command describes one ffmpeg/ffprobe invocation.

type Cue

type Cue struct {
	Start, End time.Duration
	// Settings are WebVTT cue settings ("line:0 align:start"); dropped in SRT.
	Settings string
	Text     string // lines joined with \n
}

Cue is one timed subtitle.

type DASHURLs

type DASHURLs func(sessionID string) (initialization, media string)

DASHURLs returns the initialization and media SegmentTemplate URLs of a session, relative to the MPD, with $RepresentationID$ and $Number$.

type DownloadRemuxer

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

DownloadRemuxer remuxes resolved sources to temporary MP4s. It implements core.DownloadRemuxer.

func (*DownloadRemuxer) ReleaseDownload

func (d *DownloadRemuxer) ReleaseDownload(path string)

ReleaseDownload implements core.DownloadRemuxer.

func (*DownloadRemuxer) RemuxDownload

func (d *DownloadRemuxer) RemuxDownload(ctx context.Context, req core.DownloadRemuxRequest, progress func(float64)) (string, int64, error)

RemuxDownload implements core.DownloadRemuxer.

func (*DownloadRemuxer) UsedBytes

func (d *DownloadRemuxer) UsedBytes() int64

UsedBytes is the budget currently held by finished and in-flight downloads (tests and diagnostics).

type ExecRunner

type ExecRunner struct{}

ExecRunner runs real executables with os/exec.

func (ExecRunner) Run

func (ExecRunner) Run(ctx context.Context, c Command) error

Run implements Runner.

func (ExecRunner) Start

func (ExecRunner) Start(c Command) (Process, error)

Start implements Runner.

func (ExecRunner) StartRTX added in v0.2.4

func (ExecRunner) StartRTX(Command) (Process, error)

type Manager

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

Manager runs ffmpeg for Ether. It implements core.Transcoder.

func New

func New(cfg config.Transcode, logger *slog.Logger, opts ...Option) (*Manager, error)

New finds ffmpeg/ffprobe, detects hardware encoders and starts the idle session reaper. It fails with ErrFFmpegNotFound when no ffmpeg exists.

func (*Manager) Close

func (m *Manager) Close() error

Close stops every session and the reaper.

func (*Manager) Decide

func (m *Manager) Decide(info core.MediaInfo, caps core.ClientCaps, opts core.DecideOptions) core.Decision

Decide implements core.Transcoder.

func (*Manager) EnhancementStatus added in v0.2.4

func (m *Manager) EnhancementStatus() core.VideoEnhancementSupport

EnhancementStatus is suitable for an owner status API. Available means detection passed; it deliberately does not mean a VSR run has succeeded.

func (*Manager) ExtractSubtitle

func (m *Manager) ExtractSubtitle(ctx context.Context, inputURL string, streamIndex int, codec string, w io.Writer) error

ExtractSubtitle writes an embedded text subtitle stream as WebVTT. It reads the whole input (subtitle packets are interleaved through it).

func (*Manager) FFmpegPath

func (m *Manager) FFmpegPath() string

FFmpegPath is the ffmpeg executable in use.

func (*Manager) FFprobePath

func (m *Manager) FFprobePath() string

FFprobePath is the ffprobe executable in use.

func (*Manager) HWAccel

func (m *Manager) HWAccel() core.HWAccel

HWAccel implements core.Transcoder.

func (*Manager) NewDownloadRemuxer

func (m *Manager) NewDownloadRemuxer(cfg config.Downloads) (*DownloadRemuxer, error)

NewDownloadRemuxer prepares the download temp dir under the transcode temp dir and removes files a previous process left behind.

func (*Manager) Policy

func (m *Manager) Policy() Policy

Policy is the server-side decision input derived from config and hardware.

func (*Manager) Probe

func (m *Manager) Probe(ctx context.Context, inputURL string) (*core.MediaInfo, error)

Probe implements core.Transcoder.

func (*Manager) ProbeLive

func (m *Manager) ProbeLive(ctx context.Context, inputURL string) (*core.MediaInfo, error)

ProbeLive accepts complete audio/video parameters without a finite duration. Requiring a duration on an endless feed always forces the expensive retry. This optional capability leaves ordinary file probing unchanged.

func (*Manager) ProbeLiveWithHeaders

func (m *Manager) ProbeLiveWithHeaders(ctx context.Context, input string, headers map[string]string) (*core.MediaInfo, error)

ProbeLiveWithHeaders is the authenticated variant of the optional live probe.

func (*Manager) Session

func (m *Manager) Session(id string) (core.HLSSession, bool)

Session implements core.Transcoder.

func (*Manager) Sessions

func (m *Manager) Sessions() []*Session

Sessions lists the live sessions (admin dashboard).

func (*Manager) StartHLS

func (m *Manager) StartHLS(ctx context.Context, req core.HLSRequest) (core.HLSSession, error)

func (*Manager) Stop

func (m *Manager) Stop(id string)

Stop implements core.Transcoder.

func (*Manager) UpdateConfig

func (m *Manager) UpdateConfig(cfg config.Transcode)

UpdateConfig applies changed limits (MaxTranscodes, RemoteMaxBitrateKbps). Paths and hardware choice need a restart.

func (*Manager) Version

func (m *Manager) Version() string

Version is the ffmpeg version string.

type Option

type Option func(*options)

Option tunes a Manager.

func WithBuffering

func WithBuffering(restartAhead, maxAhead, keepBehind time.Duration) Option

WithBuffering tunes seeking and disk use: a request more than restartAhead past the encoder restarts ffmpeg there (default 24s); ffmpeg is suspended when maxAhead in front of the player (default 2m, 0 = never); segments more than keepBehind behind the player are deleted (default 3m, 0 = never).

func WithDASHURLs

func WithDASHURLs(f DASHURLs) Option

WithDASHURLs sets the segment URL templates written into DASH MPDs. The default is PlexDASHURLs, the layout of real PMS.

func WithFailureHandler

func WithFailureHandler(f func(sessionID string, at time.Duration, err error)) Option

WithFailureHandler is called (in its own goroutine) when ffmpeg fails mid-session, e.g. because the source lost articles; at is the media time playback had reached. Playback typically answers with SwapInput.

func WithIdleTimeout

func WithIdleTimeout(d time.Duration) Option

WithIdleTimeout sets how long an unrequested session lives (default 2m).

func WithInputFailureHandler added in v0.2.4

func WithInputFailureHandler(f func(sessionID, inputURL string, at time.Duration, err error)) Option

WithInputFailureHandler includes the failed input generation, so delayed encoder exits cannot fail over a healthy replacement that is already playing.

func WithManifestWait

func WithManifestWait(d time.Duration) Option

WithManifestWait bounds how long a DASH session's first MPD request waits for ffmpeg's init segments to learn the exact codecs (default 15s); after that the MPD is served with codecs estimated from the probe.

func WithRunStartHandler added in v0.2.4

func WithRunStartHandler(f func(inputURL string, from, to time.Duration)) Option

WithRunStartHandler is told, before ffmpeg is spawned, which part of the input a new run will read first, so the source can fetch it in parallel while the encoder starts and locates it.

func WithRunner

func WithRunner(r Runner) Option

WithRunner replaces the process runner (tests).

func WithSegmentTimeout

func WithSegmentTimeout(d time.Duration) Option

WithSegmentTimeout bounds how long ServeSegment waits for ffmpeg (default 45s).

func WithSegmentURI

func WithSegmentURI(f func(n int, container string) string) Option

WithSegmentURI sets the segment URIs written into media playlists. The default is SegmentName ("00042.ts", relative to index.m3u8).

func WithoutHWDetection

func WithoutHWDetection() Option

WithoutHWDetection skips the startup hardware probe and encodes on CPU.

type Policy

type Policy struct {
	// RemoteMaxBitrateKbps caps streams to clients outside the LAN; 0 = none.
	RemoteMaxBitrateKbps int
	// HEVCEncoder is true when HEVC can be encoded in real time (Manager
	// sets it only for hardware encoders). It is required to keep HDR in a
	// transcode; without it HDR is tone-mapped to SDR H.264.
	HEVCEncoder bool
	// HEVCHardware is true when HEVC encoding is hardware accelerated, which
	// makes HEVC a good target for 4K transcodes.
	HEVCHardware bool
}

Policy is the server-side input to Decide that is not per request.

type Process

type Process interface {
	// Done is closed when the process has exited.
	Done() <-chan struct{}
	// Err is the exit error; valid once Done is closed.
	Err() error
	// Stop kills the process and blocks until it is gone. It is safe to
	// call more than once and after exit.
	Stop()
	// Pause suspends the process (throttling); ErrPauseUnsupported where
	// the platform cannot.
	Pause() error
	// Resume continues a paused process.
	Resume() error
}

Process is a started long-running command (an ffmpeg HLS run).

type Progress

type Progress struct {
	Frame   int64         `json:"frame"`
	FPS     float64       `json:"fps"`
	Speed   float64       `json:"speed"`   // x realtime
	OutTime time.Duration `json:"outTime"` // media time reached
	Bitrate string        `json:"bitrate,omitempty"`
	Ended   bool          `json:"ended"`
	Updated time.Time     `json:"updated"`
}

Progress is the latest `-progress` report of a session's ffmpeg run.

type RTXRunner added in v0.2.7

type RTXRunner interface {
	StartRTX(Command) (Process, error)
}

RTXRunner is a package-specific optional capability.

type Runner

type Runner interface {
	// Start launches a long-running command.
	Start(cmd Command) (Process, error)
	// Run executes a command to completion, killing it when ctx ends.
	Run(ctx context.Context, cmd Command) error
}

Runner starts processes. The default runs real executables; tests inject fakes.

type SegMode

type SegMode uint8

SegMode is how one segment is produced.

const (
	ModeCopy      SegMode = iota // stream copy (remux)
	ModeTranscode                // steady-state encode
	ModeFastStart                // quick low-latency opening encode (or short copy segment)
	ModeClamp                    // bitrate-clamped encode spliced into a copy stream
)

type SegmentPlan

type SegmentPlan struct {
	Index               int
	Start               time.Duration // playlist-relative
	Duration            time.Duration
	Mode                SegMode
	DiscontinuityBefore bool
}

SegmentPlan is one planned segment, for tests and admin reporting.

type Session

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

Session is one HLS or DASH remux or transcode. It implements core.HLSSession, and core.DASHSession for DASH sessions.

Segment n always covers media time base+n*segDur (base is the request's StartOffset for HLS and 0 for DASH, whose MPD always spans the whole title). ffmpeg runs are started at a segment boundary with -ss and -copyts, so restarting at any segment (a seek far ahead or behind, a failover to another release) keeps numbering and timestamps continuous.

An HLS session has one track of muxed segments. A DASH session has one track per representation (video, audio); ffmpeg's dash muxer writes short chunks that the session regroups into numbered segments by timestamp.

func (*Session) CheckSwap added in v0.2.4

func (s *Session) CheckSwap(info core.MediaInfo) error

CheckSwap reports whether SwapInput can deliver info's video in the format the client already opened. Playback calls it before committing a replacement so an incompatible candidate is skipped, not spliced.

func (*Session) Close

func (s *Session) Close() error

Close implements core.HLSSession: kill ffmpeg and delete the segments.

func (*Session) Container

func (s *Session) Container() string

Container is "mpegts", "fmp4", or explicitly negotiated "mkv".

func (*Session) Decision

func (s *Session) Decision() core.Decision

Decision is the session's current decision (it can change on SwapInput).

func (*Session) GoodputKbps

func (s *Session) GoodputKbps() int

GoodputKbps is the session's measured client delivery goodput.

func (*Session) HWAccelerated

func (s *Session) HWAccelerated() bool

HWAccelerated reports whether the current run encodes on hardware.

func (*Session) ID

func (s *Session) ID() string

ID implements core.HLSSession.

func (*Session) Info

func (s *Session) Info() core.MediaInfo

Info is the media info of the current input.

func (*Session) LastAccess

func (s *Session) LastAccess() time.Time

LastAccess implements core.HLSSession.

func (*Session) Progress

func (s *Session) Progress() Progress

Progress is the current ffmpeg run's latest progress report.

func (*Session) Protocol

func (s *Session) Protocol() string

Protocol is core.ProtocolHLS or core.ProtocolDASH.

func (*Session) RequestedPosition added in v0.2.4

func (s *Session) RequestedPosition() time.Duration

RequestedPosition is the title position of the player's latest segment request. Source reads can be far ahead or at the container's tail index.

func (*Session) Rungs

func (s *Session) Rungs() []core.HLSRung

Rungs implements core.HLSLadderSession.

func (*Session) SegmentDuration

func (s *Session) SegmentDuration() time.Duration

SegmentDuration is the session's segment length.

func (*Session) ServeInit

func (s *Session) ServeInit(w http.ResponseWriter, r *http.Request, rep int)

ServeInit implements core.DASHSession: representation rep's initialization segment.

func (*Session) ServeManifest

func (s *Session) ServeManifest(w http.ResponseWriter, r *http.Request)

ServeManifest implements core.DASHSession: the static, full-length MPD. The first request waits (bounded) for ffmpeg's init segments so the MPD carries exact codecs strings; until then they are estimated.

func (*Session) ServeMedia

func (s *Session) ServeMedia(w http.ResponseWriter, r *http.Request, rep, n int)

ServeMedia implements core.DASHSession: media segment n of representation rep. Each segment starts with its run's init segment, so segments from different ffmpeg runs (seeks, failovers) play back to back.

func (*Session) ServePlaylist

func (s *Session) ServePlaylist(w http.ResponseWriter, r *http.Request)

ServePlaylist implements core.HLSSession: the full-length VOD playlist (the MPD for DASH sessions).

func (*Session) ServeRungPlaylist

func (s *Session) ServeRungPlaylist(w http.ResponseWriter, r *http.Request, rungID string)

ServeRungPlaylist implements core.HLSLadderSession.

func (*Session) ServeRungSegment

func (s *Session) ServeRungSegment(w http.ResponseWriter, r *http.Request, rungID string, n int)

ServeRungSegment implements core.HLSLadderSession.

func (*Session) ServeSegment

func (s *Session) ServeSegment(w http.ResponseWriter, r *http.Request, n int)

ServeSegment implements core.HLSSession. n == InitSegment serves the fMP4 init segment. For DASH sessions it serves the first representation.

func (*Session) SwapInput

func (s *Session) SwapInput(ctx context.Context, inputURL string, info core.MediaInfo, at time.Duration) error

SwapInput implements core.HLSSession: restart on a new input at `at` (mid-stream failover). Segments from `at` on are discarded and produced again from the new input; numbering stays continuous.

func (*Session) Touch

func (s *Session) Touch()

Touch marks the session as in use (e.g. on a Plex timeline ping while the client is paused) so the idle reaper keeps it.

type ThumbOptions

type ThumbOptions struct {
	Runner Runner
	FFmpeg string
	Logger *slog.Logger

	Interval      time.Duration // frame spacing (default 10s)
	Width         int           // thumbnail width px (default 320, Plex "sd")
	Quality       int           // ffmpeg -q:v (default 7)
	FrameTimeout  time.Duration // per-frame extraction cap (default 25s)
	BatchFrames   int           // frames per batch before a pause (default 12)
	BatchPause    time.Duration // pause between batches (default 4s)
	MaxConcurrent int           // global extraction jobs (default 2)
	MaxBytes      int64         // total stored JPEG bytes, LRU-evicted (default 256MiB)
	MaxReleases   int           // releases kept, LRU-evicted (default 32)
	RetryBackoff  time.Duration // pause before retrying a failed release (default 2m)
}

ThumbOptions tunes a Thumbnails store. Runner and FFmpeg are required; zero limits take the defaults documented on each field.

type Thumbnails

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

Thumbnails builds sparse BIF preview indexes for releases while they stream. Extraction only ever reads a source handed to EnsureTrickplay (the loopback input of an active playback or warmup session): one fast-seek ffmpeg run per frame decodes a single (key)frame, so bytes are read around the requested frame only — never the whole file ahead of playback. Jobs run at most one per release under a small global cap, fill in bounded batches with pauses, and stop when the source stops answering (the session ended) or Close is called.

It implements core.TrickplayProvider.

func NewThumbnails

func NewThumbnails(o ThumbOptions) *Thumbnails

NewThumbnails builds an empty thumbnail store. Call Close on shutdown.

func (*Thumbnails) CancelTrickplay

func (t *Thumbnails) CancelTrickplay(releaseID string)

CancelTrickplay stops the active extraction for a release. Playback calls this after the last viewer session for that release ends.

func (*Thumbnails) Close

func (t *Thumbnails) Close() error

Close stops all generation and waits for jobs to finish.

func (*Thumbnails) EnsureTrickplay

func (t *Thumbnails) EnsureTrickplay(_ context.Context, src core.TrickplaySource)

EnsureTrickplay implements core.TrickplayProvider.

func (*Thumbnails) SetTrickplayFallback

func (t *Thumbnails) SetTrickplayFallback(releaseID string, jpeg []byte)

SetTrickplayFallback implements core.TrickplayProvider.

func (*Thumbnails) TrickplayAvailable

func (t *Thumbnails) TrickplayAvailable(releaseID string) bool

TrickplayAvailable implements core.TrickplayProvider.

func (*Thumbnails) TrickplayBIF

func (t *Thumbnails) TrickplayBIF(releaseID string) ([]byte, bool)

TrickplayBIF implements core.TrickplayProvider.

func (*Thumbnails) TrickplayFrame

func (t *Thumbnails) TrickplayFrame(releaseID string, at time.Duration) ([]byte, bool)

TrickplayFrame implements core.TrickplayProvider.

type Timeline

type Timeline struct {

	// SwitchSeg is the first steady segment after the fast-start ramp
	// (== len(durs) when the whole title is ramp, 0 when there is none).
	SwitchSeg int
	// contains filtered or unexported fields
}

Timeline is a session's segment plan. Starts are relative to the session's playlist position zero (the HLS StartOffset); callers add base for absolute media time.

func (*Timeline) ClampKbps

func (tl *Timeline) ClampKbps(n int) int

ClampKbps is the governor's bitrate ceiling for segment n (0 = none).

func (*Timeline) Dur

func (tl *Timeline) Dur(n int) time.Duration

Dur is segment n's playlist duration.

func (*Timeline) IndexAt

func (tl *Timeline) IndexAt(rel time.Duration) int

IndexAt is the segment covering playlist-relative time rel.

func (*Timeline) Keyframed added in v0.2.4

func (tl *Timeline) Keyframed() bool

Keyframed reports whether the boundaries come from a keyframe index.

func (*Timeline) ModeAt

func (tl *Timeline) ModeAt(n int) SegMode

ModeAt is how segment n must be produced.

func (*Timeline) NextChange

func (tl *Timeline) NextChange(n int) int

NextChange is the first segment after n produced in a different mode than n (the exclusive end of a run starting at n), or -1 when the mode runs to the end of what is known.

func (*Timeline) Plan

func (tl *Timeline) Plan(n int) SegmentPlan

Plan returns segment n's plan. discont reports discontinuities for the primary encode; rung playlists pass their own via playlist rendering.

func (*Timeline) SetClamp

func (tl *Timeline) SetClamp(n, kbps int)

SetClamp plans segment n as a clamped transcode (governor).

func (*Timeline) Start

func (tl *Timeline) Start(n int) time.Duration

Start is segment n's offset from playlist zero.

func (*Timeline) TargetDuration

func (tl *Timeline) TargetDuration() time.Duration

TargetDuration is the HLS #EXT-X-TARGETDURATION: the ceiling of the longest segment duration.

func (*Timeline) Total

func (tl *Timeline) Total() int

Total is the number of segments; 0 when the duration is unknown.

Jump to

Keyboard shortcuts

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