Documentation
¶
Index ¶
- Constants
- Variables
- func DetectFromExtension(u *url.URL) string
- func DetectFromMIME(mime string) string
- func FormatToContentType(format string) (string, error)
- func HeaderArgs(h http.Header) []string
- func NormalizeStreamHeaders(h http.Header) http.Header
- type AudioSupport
- type Codec
- type DeliveryKind
- type FormatInfo
- type ProbeInfo
- type Renderer
- type Stream
- type StreamInfo
- type VideoSupport
Constants ¶
const ( MP4 = "video/mp4" MKV = "video/x-matroska" WebM = "video/webm" AVI = "video/x-msvideo" MOV = "video/quicktime" HLS = "application/x-mpegURL" MPEGTS = "video/mp2t" )
const ( HLSPlaylistName = "stream.m3u8" HLSInitName = "init.mp4" HLSSegmentPattern = "seg_%05d.m4s" )
HLS output filenames, shared by the muxer (ffmpeg's hls muxer writes them into its working directory) and the HLS server (which serves that directory).
Variables ¶
var HLSInputArgs = []string{
"-allowed_extensions", "ALL",
"-allowed_segment_extensions", "ALL",
"-extension_picky", "0",
"-seg_format_options", "extension_picky=0",
}
HLSInputArgs contains ffmpeg/ffprobe flags that relax extension checks for HLS playlists and DASH manifests.
Functions ¶
func DetectFromExtension ¶
DetectFromExtension returns a content type based on the URL's file extension, or empty string if unrecognized.
func DetectFromMIME ¶
DetectFromMIME returns a content type based on a confirmed MIME type, or empty string if unrecognized.
func FormatToContentType ¶
FormatToContentType maps an ffprobe format_name to a content type.
func HeaderArgs ¶ added in v1.7.0
HeaderArgs renders h as the ffmpeg/ffprobe -headers flag pair, or nil when h is empty. ffprobe and ffmpeg both want every request header in one CRLF-joined blob.
func NormalizeStreamHeaders ¶ added in v1.4.3
NormalizeStreamHeaders returns a copy of browser-captured headers ready to replay to the puller. It drops headers that break a re-issued fetch and, when a Referer is present without an Origin, derives the Origin from it: a cross-origin browser GET sends only a Referer, but CDNs commonly gate segment delivery on Origin too, and the derived pair is what a site's own player proxy sends. The input is not mutated.
Types ¶
type AudioSupport ¶ added in v1.8.0
type AudioSupport struct {
Codec Codec
MaxChannels int // highest channel count the renderer decodes; 0 = no ceiling
}
AudioSupport is one audio codec a renderer decodes natively, up to MaxChannels channels. A probed audio track is copy-eligible when its codec matches and its channel count fits, so a 5.1/7.1 track passes through instead of being downmixed to stereo. MaxChannels 0 means "no advertised ceiling": trusted at full channel count, which is right for the inherently-surround Dolby codecs (AC-3/E-AC-3) whose advertised support already implies multichannel decode.
type Codec ¶ added in v1.6.1
type Codec string
Codec is an ffmpeg canonical codec name: the value ffprobe reports for a stream and the vocabulary the planner, renderer capabilities, and encoders all share, so codecs travel as a type instead of bare strings. It names the abstract codec (H.264, AC-3), not a concrete encoder; one codec can have several encoders (libx264, h264_vaapi, h264_videotoolbox). The type spans both video and audio; VideoSupport / AudioSupport disambiguate which side a value belongs to.
Audio codecs. AC-3 and E-AC-3 are the Dolby surround codecs: unlike AAC (which a renderer commonly decodes stereo-only), advertised support for either means the renderer decodes multichannel, so a 5.1 source can reach it intact.
type DeliveryKind ¶ added in v1.8.0
type DeliveryKind int
DeliveryKind is how castor's local HTTP server hands a produced stream to the renderer, and the single fact the delivery driver keys the serving mechanism on. It is carried as data on FormatInfo, so a producible format's delivery is declared alongside it rather than decided by a content-type conditional.
const ( // DeliverStream is one growing output the replay server fronts, handing every // client the stream from byte 0 (MPEG-TS, fragmented mp4). DeliverStream DeliveryKind = iota // DeliverSegmented is a live playlist plus rolling segments in a directory the // HLS server fronts. DeliverSegmented )
type FormatInfo ¶
type FormatInfo struct {
ContentType string
Extension string
Muxer string
Delivery DeliveryKind
}
FormatInfo describes a container castor can produce: the MIME type the device is told it is fetching, the file extension it carries, the ffmpeg muxer (-f) that writes it, and how it is delivered.
func FormatForContentType ¶ added in v1.0.0
func FormatForContentType(ct string) (FormatInfo, bool)
FormatForContentType returns the FormatInfo for a content type, or ok=false if castor cannot produce it. Callers read the muxer, extension, and delivery off the returned FormatInfo.
type ProbeInfo ¶ added in v1.6.1
type ProbeInfo struct {
VideoCodec Codec // e.g. CodecH264, CodecHEVC
VideoProfile string // e.g. "High", "Main", "High 10"
VideoHeight int
VideoBitDepth int // derived from pix_fmt (8, 10, 12)
VideoHDR bool // PQ (smpte2084) or HLG (arib-std-b67) transfer
AudioCodec Codec // e.g. CodecAAC, CodecAC3
AudioChannels int // channel count (2 = stereo, 6 = 5.1, 8 = 7.1), 0 if unknown
}
ProbeInfo is a structured description of a source stream, the subset an ffprobe pass yields that the planner needs to decide whether the source can be stream-copied to a renderer or must be re-encoded. Zero values mean "unknown"; most capability checks treat that as "not safe to copy" (a failed or partial probe falls back to a transcode), except AudioChannels, where an unknown count is trusted rather than force-transcoded (see AudioSupport.accepts) since a matching codec with no probed layout isn't worth the quality loss of an unnecessary re-encode.
It is produced by the ffmpeg adapter (ffmpeg.Probe) and consumed by a Renderer's copy check; the type lives here, in the domain, so neither side depends on the other.
type Renderer ¶ added in v1.6.1
type Renderer struct {
Containers []string
Video []VideoSupport
Audio []AudioSupport
// SelfFetch reports whether the renderer fetches an arbitrary stream URL
// itself once it is handed one, versus needing castor to serve the bytes to
// it. The planner reads this to choose pass-through (hand the renderer the
// source URL and let it pull directly) over a castor-served stream: a
// self-fetching renderer can pass the source through, while a push-only
// renderer only plays what castor serves it and so is always served locally.
SelfFetch bool
// ServedContainer is the content type castor produces on a served cast that
// remuxes: the container the local ffmpeg muxes and the renderer is told it is
// fetching. A renderer that will be served a live remux declares the container
// it wants (a fragmented single-file container for a smart client, or a
// segmented live format for one that cannot play a growing single-file URL);
// the read-once spool path serves its own append-only container. Inert on a
// pass-through cast, which reads the source's own content type.
ServedContainer string
}
Renderer describes what a target device can play without help from us: the containers it accepts as-is over the network (so the source URL can be handed to it directly), and the video envelopes it decodes natively (so a matching source can be stream-copied instead of re-encoded). It is the single capability model every device type describes itself with; each Device resolves its own by whatever means its protocol allows, while this package owns the type and the matching rules. Nothing here names or is specialized for any device family.
func (Renderer) AcceptsContainer ¶ added in v1.6.1
AcceptsContainer reports whether the device plays contentType directly over the network (the pass-through decision).
func (Renderer) CanCopyAudio ¶ added in v1.8.0
CanCopyAudio reports whether a probed source audio track can be stream-copied to this renderer instead of re-encoded.
func (Renderer) CanCopyVideo ¶ added in v1.6.1
CanCopyVideo reports whether a probed source video can be stream-copied to this renderer instead of re-encoded.
func (Renderer) SupportsAudioCodec ¶ added in v1.8.0
SupportsAudioCodec reports whether the renderer decodes audio codec c natively, and so whether the pipeline may re-encode a multichannel source to it rather than downmix to stereo.
func (Renderer) SupportsCodec ¶ added in v1.6.1
SupportsCodec reports whether the renderer decodes video codec c natively, and so whether the pipeline may target it when re-encoding.
type StreamInfo ¶
type StreamInfo struct {
BitRate int64
Duration time.Duration
ContentType string
HasVideo bool
HasAudio bool
// VideoHeight is the display height of the real video track, 0 if unknown.
// For an HLS master this is only whichever variant ffprobe chose, not the
// master's full range, so it is not a reliable ceiling for a master.
VideoHeight int
}
StreamInfo holds metadata returned by ffprobe for a stream.
func (StreamInfo) Live ¶ added in v1.6.1
func (s StreamInfo) Live() bool
Live reports whether ffprobe could determine no duration — genuinely live sources have none (no endlist), and unparseable duration is safest treated the same: pacing such sources at realtime costs nothing on VOD while 2x with a wire-speed burst trips rate limits on proxy CDNs.
func (StreamInfo) Playable ¶ added in v1.4.0
func (s StreamInfo) Playable() bool
Playable reports whether the stream carries castable media — a real video track plus audio. Decoy playlists (an image-only "video" track, or no audio) probe cleanly but cannot be remuxed, so they are not playable.
type VideoSupport ¶ added in v1.6.1
type VideoSupport struct {
Codec Codec
Profiles []string // nil or empty = any profile
BitDepths []int // nil or empty = {8}
}
VideoSupport is one video envelope a renderer decodes natively. A probed source is copy-eligible when it matches at least one on the things that black-screen a TV outright: codec, profile, bit depth, and dynamic range. An HDR source is never copy-eligible: correct HDR playback cannot be assumed to engage on an arbitrary renderer, so it is re-encoded to an SDR-safe output rather than passed through (this is a generic conservative policy, not tied to any device family). Resolution is deliberately absent: it is the user's cast-quality preference (config max_height), applied at source selection and the copy gate, not something guessed from the renderer.