Documentation
¶
Overview ¶
Package transcodebench implements a reproducible benchmark harness that drives the real transcode.Manager (probe, decision, HLS sessions and ServeSegment) against a loopback range-capable HTTP source serving a local fixture file. It never builds ad-hoc ffmpeg command lines for the measured work: every measured encode/remux is a Manager session. Direct ffprobe use is limited to verifying the retained output after a run.
Index ¶
- Constants
- func DeliveredMediaSeconds(n int, seg, requested time.Duration) float64
- func ExpectedDimensions(dec core.Decision, cfg Config, srcW, srcH int) (w, h int, ok bool)
- func IsHWEncoder(enc string) bool
- func RedactArgs(args []string) []string
- func SegmentCount(dur, seg time.Duration) int
- func Summarize(res *Result)
- func VideoEncoderFromArgs(args []string) string
- func WriteResult(path string, res *Result) error
- type Config
- type DecisionSummary
- type Launch
- type OutputProbe
- type Recorder
- type Result
- type SessionResult
- type StreamSummary
Constants ¶
const ( ModeTranscode = "transcode" ModeRemux = "remux" )
Modes accepted by Config.Mode.
const SchemaVersion = 1
SchemaVersion is the version of the Result JSON document.
Variables ¶
This section is empty.
Functions ¶
func DeliveredMediaSeconds ¶
DeliveredMediaSeconds is the media time covered by n served segments, capped at the requested duration.
func ExpectedDimensions ¶
ExpectedDimensions returns the exact output size implied by the source dimensions and the decision, mirroring transcode's outputSize scaling (aspect preserved, even sizes) for encodes and the untouched source size for stream copy. ok is false when the source size is unknown.
func IsHWEncoder ¶
IsHWEncoder reports whether an encoder name is a hardware encoder rather than a software libx* encoder or stream copy.
func RedactArgs ¶
RedactArgs returns args with credentials removed: values following -headers/-user_agent/-referer, Authorization/token material anywhere, and sensitive URL query values. The -i input itself is kept (it is a loopback bench URL) except for sensitive query parameters.
func SegmentCount ¶
SegmentCount is the number of whole segments needed to cover dur.
func Summarize ¶
func Summarize(res *Result)
Summarize folds per-session results into totals. Pure; unit-tested.
func VideoEncoderFromArgs ¶
VideoEncoderFromArgs returns the -c:v (or -c:v:0) encoder name, or "".
func WriteResult ¶
WriteResult writes res as indented JSON to path (atomically via rename).
Types ¶
type Config ¶
type Config struct {
Input string // local fixture path (required)
FFmpeg string // ffmpeg path/lookup hint; empty = Manager discovery
FFprobe string // ffprobe path/lookup hint
HWAccel string // none|auto|videotoolbox|nvenc|qsv|vaapi (default none)
Mode string // transcode|remux (default transcode)
Codec string // target video codec for transcode: h264|hevc (default h264)
MaxHeight int // 0 = source height
BitrateKbps int // 0 = Manager decision's bitrate
Concurrency int // simultaneous sessions (default 1)
Duration time.Duration // media seconds to consume per session (required > 0)
SegmentDur time.Duration // HLS segment duration (default 4s)
Paced bool // consume at roughly realtime pace
ResultPath string // JSON result path; empty = stdout only in CLI
OutputDir string // retain init/segments/concatenated output here when set
Timeout time.Duration // overall context timeout (default 10m)
VAAPIDevice string
}
Config is the benchmark configuration. All fields are plain values so the CLI (and tests) can build one without flag parsing.
func (Config) Normalized ¶
Normalized returns cfg with defaults applied.
type DecisionSummary ¶
type DecisionSummary struct {
Kind string `json:"kind"`
VideoCopy bool `json:"videoCopy"`
AudioCopy bool `json:"audioCopy"`
VideoCodec string `json:"videoCodec"`
AudioCodec string `json:"audioCodec,omitempty"`
Container string `json:"container"`
MaxHeight int `json:"maxHeight,omitempty"`
BitrateKbps int `json:"bitrateKbps,omitempty"`
Reason string `json:"reason,omitempty"`
}
DecisionSummary mirrors the explicit decision handed to StartHLS.
type Launch ¶
type Launch struct {
ID int `json:"id"`
Kind string `json:"kind"` // "start" (long-running) or "run" (to completion)
Path string `json:"path"`
Args []string `json:"args"` // redacted
StartedAt time.Time `json:"startedAt"`
DurationMs int64 `json:"durationMs,omitempty"`
ExitError string `json:"exitError,omitempty"`
PID int `json:"pid,omitempty"`
CPUUserMs *int64 `json:"cpuUserMs,omitempty"`
CPUSystemMs *int64 `json:"cpuSystemMs,omitempty"`
PeakRSSBytes *uint64 `json:"peakRssBytes,omitempty"` // individual encoder peak, not aggregate tree RSS
Encoder string `json:"encoder,omitempty"` // -c:v value, when present
HWEncoder bool `json:"hwEncoder,omitempty"`
LogTail string `json:"logTail,omitempty"`
}
Launch is one recorded Runner invocation. PID/CPU are present only when the underlying Process implements the optional interfaces interface{ PID() int } / interface{ CPUTime() (time.Duration, time.Duration) }; they are never invented when the API does not expose them.
type OutputProbe ¶
type OutputProbe struct {
Container string `json:"container,omitempty"`
DurationSec float64 `json:"durationSec,omitempty"`
Streams []StreamSummary `json:"streams,omitempty"`
Error string `json:"error,omitempty"`
Verified bool `json:"verified"`
Detail string `json:"detail,omitempty"`
}
OutputProbe is ffprobe verification of the retained output.
type Recorder ¶
type Recorder struct {
// contains filtered or unexported fields
}
Recorder wraps a transcode.Runner (ExecRunner by default) and records every launch: redacted argv, timing, exit error, captured log tail, and PID/CPU when the process exposes them.
func NewRecorder ¶
func NewRecorder() *Recorder
func NewRecorderWith ¶
NewRecorderWith wraps a specific inner runner (tests).
type Result ¶
type Result struct {
SchemaVersion int `json:"schemaVersion"`
Kind string `json:"kind"`
StartedAt time.Time `json:"startedAt"`
WallMs int64 `json:"wallMs"` // total elapsed (setup+measurement+verification+teardown)
// Timing splits WallMs so Speedup is never computed over setup/probe.
Timing struct {
SetupMs int64 `json:"setupMs"` // hash, Manager start, probe, decision
MeasurementMs int64 `json:"measurementMs"` // barrier release -> last segment delivered (encoders then stopped)
VerificationMs int64 `json:"verificationMs"` // ffprobe of retained output, after encoders stopped
} `json:"timing"`
Success bool `json:"success"`
Error string `json:"error,omitempty"`
Config struct {
Mode string `json:"mode"`
Codec string `json:"codec,omitempty"`
HWAccel string `json:"hwAccel"`
MaxHeight int `json:"maxHeight,omitempty"`
BitrateKbps int `json:"bitrateKbps,omitempty"`
Concurrency int `json:"concurrency"`
DurationSec float64 `json:"durationSec"`
SegmentSec float64 `json:"segmentSec"`
Paced bool `json:"paced"`
} `json:"config"`
Fixture struct {
Path string `json:"path"`
SHA256 string `json:"sha256"`
Size int64 `json:"size"`
} `json:"fixture"`
Runtime struct {
GoVersion string `json:"goVersion"`
GOOS string `json:"goos"`
GOARCH string `json:"goarch"`
NumCPU int `json:"numCPU"`
FFmpegPath string `json:"ffmpegPath,omitempty"`
FFprobePath string `json:"ffprobePath,omitempty"`
FFmpegVer string `json:"ffmpegVersion,omitempty"`
FFprobeVer string `json:"ffprobeVersion,omitempty"`
HWDetected string `json:"hwDetected,omitempty"`
HWEncoders []string `json:"hwEncoders,omitempty"`
HWFallback bool `json:"hwFallback,omitempty"` // requested HW not actually used
} `json:"runtime"`
Probe struct {
Container string `json:"container"`
DurationSec float64 `json:"durationSec"`
BitrateKbps int `json:"bitrateKbps,omitempty"`
Streams []StreamSummary `json:"streams,omitempty"`
} `json:"probe"`
Decision DecisionSummary `json:"decision"`
Sessions []SessionResult `json:"sessions"`
Launches []Launch `json:"launches"`
Totals struct {
SessionsOK int `json:"sessionsOk"`
SessionsFailed int `json:"sessionsFailed"`
Segments int `json:"segments"`
Bytes int64 `json:"bytes"`
MediaSec float64 `json:"mediaSec"`
Speedup float64 `json:"speedup,omitempty"` // mediaSec / wallSec (aggregate)
} `json:"totals"`
}
Result is the versioned JSON document written to -result.
type SessionResult ¶
type SessionResult struct {
ID string `json:"id"`
Success bool `json:"success"`
Error string `json:"error,omitempty"`
StartupMs int64 `json:"startupMs"` // barrier release -> first segment served
WallMs int64 `json:"wallMs"` // barrier release -> last segment served
Segments int `json:"segments"` // segments successfully served
MediaSec float64 `json:"mediaSec"` // delivered media seconds (capped at request)
Bytes int64 `json:"bytes"` // segment bytes (init counted separately)
InitBytes int64 `json:"initBytes,omitempty"`
PlaylistB int `json:"playlistBytes,omitempty"`
OutputPath string `json:"outputPath,omitempty"` // retained concatenated output, when kept
OutputSHA256 string `json:"outputSha256,omitempty"`
OutputProbe *OutputProbe `json:"outputProbe,omitempty"`
HWFallback bool `json:"hwFallback,omitempty"`
// contains filtered or unexported fields
}
SessionResult is one concurrent session's measurements.
type StreamSummary ¶
type StreamSummary struct {
Type string `json:"type"`
Codec string `json:"codec"`
Profile string `json:"profile,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Channels int `json:"channels,omitempty"`
}
StreamSummary is a compact, JSON-friendly stream description.