Mosaic is intentionally small. The root package provides orchestration while lower-level packages own focused behavior.
Job
└─ encode.go
├─ prepareInputForEncoding
│ └─ optional orientation normalization
├─ probe.InputWithExecutor
│ └─ ffprobe video stream + audio stream
├─ ladder.Build
│ └─ aspect-preserving base ladder
├─ optimize.Apply
│ └─ bitrate capping and rung trimming
└─ encoder.Encode{HLS|DASH}CMAFWithExecutor
└─ ffmpeg command assembly and execution
Files:
encode.go
job.go
orientation.go
Responsibilities:
mosaic.Profile to internal config.Profile.Files:
config/profiles.go
Responsibilities:
Files:
probe/probe.go
Responsibilities:
DisplayWidthDisplayHeightIsPortraitRotation metadata is read from FFprobe side data first, then tags.rotate.
Files:
ladder/types.go
ladder/ladder.go
Responsibilities:
yuv420p compatibility.Files:
optimize/cost.go
optimize/optimize.go
Responsibilities:
Files:
encoder/common.go
encoder/hls_cmaf.go
encoder/dash_cmaf.go
Responsibilities:
Files:
internal/executor/executor.go
internal/executor/mock.go
Responsibilities:
mosaic
├─ config
├─ encoder
├─ internal/executor
├─ ladder
├─ optimize
└─ probe
Lower-level packages do not import the root package.
This keeps public API orchestration separate from command generation and makes package tests straightforward.
Mosaic depends on external binaries:
ffprobeffmpegAll invocations go through executor.CommandExecutor.
This makes command behavior observable in tests without actually running FFmpeg.
Side effects are intentionally narrow:
Job.OutputDir.Mosaic does not keep global encode state.
Important error boundaries:
ffmpeg HLS failed or ffmpeg DASH failed.executor.CommandError.Most behavior is tested with mocks:
Integration tests and smoke tests can use real FFmpeg and FFprobe where available.