Mosaic

August 31, 2026 ยท View on GitHub

Mosaic Logo

Predictable, Production-Ready Adaptive Bitrate (ABR) Video Packaging for Go

Documentation Portal

Go Reference Go Version Build Status Latest Release License: MIT


mosaic is a comprehensive, production-grade Go library for adaptive bitrate (ABR) video packaging. It probes input media, computes an aspect-preserving rendition ladder, applies quality and bitrate optimizations, and generates standardized HLS (fMP4 / TS) and DASH CMAF streams using FFmpeg.

๐Ÿ“– Full Online Documentation & Guides: https://farshidrezaei.github.io/mosaic/

Designed for server-side video infrastructure, background workers, and media pipelines where predictability, performance, clean abstractions, and zero external dependencies are critical.


โšก Highlights

  • Standard CMAF Output: Generates HLS (master.m3u8, variant playlists, fMP4 segments) and DASH (manifest.mpd, init.m4s, chunk.m4s) streams.
  • Next-Gen Codecs: First-class support for AV1 (libsvtav1), HEVC / H.265 (libx265), and H.264 / AVC (libx264) with software and GPU hardware acceleration.
  • Smart Quality & Capped-CRF: Content-Aware Bitrate optimization combining Constant Rate Factor (CRF) with VBV maxrate caps to save 30โ€“50% bandwidth without quality loss.
  • Storyboard Thumbnails (Trick-Play Preview): Automatically generates sprite sheets (thumbnails_0.jpg) and standard WebVTT cue files (thumbnails.vtt) for timeline scrubber previews in modern video players.
  • Built-in Web Preview DevTools Player: Instantly test and inspect streams locally via mosaic preview [dir] featuring a dark-mode web player (Hls.js / Dash.js), audio/rendition switcher, and live diagnostics.
  • Subtitles & Multi-Track Audio: Converts SRT to WebVTT automatically and injects subtitle tracks into HLS master playlists (#EXT-X-MEDIA:TYPE=SUBTITLES) and DASH AdaptationSets.
  • EBU R128 Audio Normalization: Automatic broadcast-standard audio normalization (loudnorm=I=-16:TP=-1.5:LRA=11) ensuring uniform volume levels.
  • Dynamic Watermarking & Branding: Configurable overlay placement (top-right, top-left, bottom-right, bottom-left, center), alpha opacity blending, and auto-scaling relative to rendition widths.
  • HLS AES-128 Segment Encryption: Automated 16-byte key generation and playlist tagging (#EXT-X-KEY:METHOD=AES-128) for content protection.
  • Zero-Dependency Cloud Storage Upload (S3 / MinIO / R2): Concurrent streaming asset upload with pure Go AWS SigV4 signing and automatic Content-Type / Cache-Control: immutable headers.
  • Aspect-Preserving ABR Ladders: Automatically preserves the source display aspect ratio โ€” landscape, square (1:1), portrait (9:16), or ultra-wide inputs never get distorted or letterboxed with black bars.
  • Orientation Normalization: Probes display matrices and rotation tags (90ยฐ, 180ยฐ, 270ยฐ), physically transposes frames when needed, and resets output metadata so mobile videos display correctly everywhere.
  • Real-Time Progress Tracking: Accurately computes encoding percentage (0.0% to 100.0%), encoded time, current bitrate, and speed.
  • Zero Third-Party Dependencies: Built strictly with Go standard library + FFmpeg/FFprobe CLI tooling.
  • Fully Testable Architecture: Interface-driven command executor allows 100% unit testing without calling live FFmpeg.

๐Ÿ“‹ Requirements

  • Go: 1.25+
  • FFmpeg: 4.4+ (with libx264, libx265, libsvtav1, and aac support)
  • FFprobe: Typically installed alongside FFmpeg

๐Ÿ“ฆ Installation

As a Go Library

go get github.com/farshidrezaei/mosaic

As a Standalone CLI Tool

# Install directly via Go
go install github.com/farshidrezaei/mosaic/cmd/mosaic@latest

# Or run via Docker (FFmpeg pre-installed)
docker run --rm -v $(pwd):/workspace ghcr.io/farshidrezaei/mosaic -i input.mp4 -o ./output/hls --thumbnails

๐Ÿ› ๏ธ CLI Quick Start

# 1. Package video into HLS with mobile normalization and thumbnail scrubber:
mosaic -i input.mp4 -o ./output/hls --thumbnails

# 2. Package with Next-Gen AV1 codec, Capped-CRF, Watermark, and Audio Normalization:
mosaic -i input.mp4 -o ./output/hls_av1 \
  --codec av1 \
  --crf 28 \
  --watermark ./logo.png \
  --normalize-audio \
  --thumbnails

# 3. Encrypt HLS segments with AES-128:
mosaic -i input.mp4 -o ./output/hls_secure --encrypt-aes128

# 4. Package and auto-upload directly to S3 / MinIO:
mosaic -i input.mp4 -o ./output/hls_s3 \
  --s3-bucket my-stream-bucket \
  --s3-prefix videos/movie1 \
  --s3-region us-east-1

# 5. Launch local web player to preview generated streams:
mosaic preview ./output/hls

๐Ÿš€ Go Library Usage

1. Complete Production HLS Workflow (Thumbnails, Watermark, Subtitles, AES-128)

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/farshidrezaei/mosaic"
)

func main() {
	job := mosaic.Job{
		Input:     "movie.mp4",
		OutputDir: "./output/hls_stream",
		Profile:   mosaic.ProfileVOD,
		ProgressHandler: func(info mosaic.ProgressInfo) {
			fmt.Printf("\r[%5.1f%%] time=%s bitrate=%s speed=%s",
				info.Percentage, info.CurrentTime, info.Bitrate, info.Speed)
		},
	}

	usage, err := mosaic.EncodeHls(
		context.Background(),
		job,
		mosaic.WithNormalizeOrientation(), // Correct mobile 90ยฐ/270ยฐ orientation
		mosaic.WithNormalizeAudio(),       // EBU R128 broadcast audio leveling
		mosaic.WithThumbnails(),           // Generates thumbnails.vtt & sprite sheet
		mosaic.WithWatermark(mosaic.WatermarkConfig{
			Path:     "./branding/logo.png",
			Position: mosaic.PositionTopRight,
			Opacity:  0.85,
		}),
		mosaic.WithSubtitles(mosaic.SubtitleTrack{
			Path:     "./subtitles/en.srt", // Auto-converted to WebVTT
			Language: "en",
			Label:    "English",
			Default:  true,
		}),
		mosaic.WithAES128Encryption(),     // Generates enc.key and encrypts segments
		mosaic.WithThreads(4),
	)
	if err != nil {
		log.Fatalf("Encoding failed: %v", err)
	}

	fmt.Printf("\nDone! CPU User Time: %.2fs | Peak RSS: %d KB\n", usage.UserTime, usage.MaxMemory)
}

2. Next-Gen AV1 & HEVC Encoding with Capped-CRF

package main

import (
	"context"
	"log"

	"github.com/farshidrezaei/mosaic"
)

func main() {
	job := mosaic.Job{
		Input:     "input.mp4",
		OutputDir: "./output/av1_hls",
		Profile:   mosaic.ProfileVOD,
	}

	// High-efficiency AV1 ABR ladder with Capped-CRF 28
	_, err := mosaic.EncodeHls(
		context.Background(),
		job,
		mosaic.WithAV1(),
		mosaic.WithCRF(28),
		mosaic.WithThumbnails(),
	)
	if err != nil {
		log.Fatalf("AV1 encoding failed: %v", err)
	}
}

3. Direct Cloud Upload to S3 / MinIO / Cloudflare R2

package main

import (
	"context"
	"log"

	"github.com/farshidrezaei/mosaic"
)

func main() {
	job := mosaic.Job{
		Input:     "input.mp4",
		OutputDir: "./output/hls",
		Profile:   mosaic.ProfileVOD,
	}

	_, err := mosaic.EncodeHls(
		context.Background(),
		job,
		mosaic.WithThumbnails(),
		mosaic.WithS3Upload(mosaic.S3Config{
			Endpoint:  "https://s3.us-east-1.amazonaws.com",
			Bucket:    "my-media-bucket",
			Region:    "us-east-1",
			KeyPrefix: "content/video-101",
			AccessKey: "YOUR_ACCESS_KEY",
			SecretKey: "YOUR_SECRET_KEY",
		}),
	)
	if err != nil {
		log.Fatalf("Packaging and upload failed: %v", err)
	}
}

๐Ÿ“š Documentation

For complete architecture details, API references, tutorials, and benchmark results:


๐Ÿค Contributing

Contributions are welcome! Please review CONTRIBUTING.md and AGENTS.md before submitting pull requests.

# Verify code formatting, tests, and linting
gofmt -w .
GOCACHE=/tmp/go-build go test -v -race ./...
golangci-lint run

๐Ÿ“„ License

Mosaic is licensed under the MIT License.