{"id":37094952,"url":"https://github.com/farshidrezaei/mosaic","last_synced_at":"2026-01-14T11:41:53.951Z","repository":{"id":330476674,"uuid":"1122366298","full_name":"farshidrezaei/mosaic","owner":"farshidrezaei","description":"Adaptive HLS \u0026 DASH (CMAF) encoder for Go","archived":false,"fork":false,"pushed_at":"2025-12-25T18:43:07.000Z","size":63,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-27T05:42:11.335Z","etag":null,"topics":["abr","cmaf","dash","hls-live-streaming","hlsl","m4s","stream","streaming"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/farshidrezaei/mosaic","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/farshidrezaei.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-24T15:22:13.000Z","updated_at":"2025-12-27T00:52:11.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/farshidrezaei/mosaic","commit_stats":null,"previous_names":["farshidrezaei/mosaic"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/farshidrezaei/mosaic","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farshidrezaei%2Fmosaic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farshidrezaei%2Fmosaic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farshidrezaei%2Fmosaic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farshidrezaei%2Fmosaic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/farshidrezaei","download_url":"https://codeload.github.com/farshidrezaei/mosaic/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farshidrezaei%2Fmosaic/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28419249,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["abr","cmaf","dash","hls-live-streaming","hlsl","m4s","stream","streaming"],"created_at":"2026-01-14T11:41:53.357Z","updated_at":"2026-01-14T11:41:53.942Z","avatar_url":"https://github.com/farshidrezaei.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🎬 Mosaic\n\n[![Go Report Card](https://goreportcard.com/badge/github.com/farshidrezaei/mosaic)](https://goreportcard.com/report/github.com/farshidrezaei/mosaic)\n[![Go](https://github.com/farshidrezaei/mosaic/actions/workflows/go.yml/badge.svg)](https://github.com/farshidrezaei/mosaic/actions/workflows/go.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n**Mosaic** is a Go library for adaptive bitrate (ABR) video encoding that generates HLS and DASH streams with CMAF\nsegments. It automatically builds an optimized encoding ladder based on your source video and handles all the complexity\nof FFmpeg command construction.\n\n## ✨ Features\n\n- 🎯 **Automatic Ladder Building** - Generates optimal renditions (1080p, 720p, 360p) based on source resolution\n- 🔧 **Intelligent Optimization** - Bitrate capping and redundant rendition trimming\n- 📦 **CMAF Support** - Industry-standard fMP4 segments compatible with both HLS and DASH\n- ⚡ **Dual Profiles** - VOD (5s segments) and Live (2s low-latency) modes\n- 🎨 **Smart Scaling** - Maintains aspect ratio with letterboxing when needed\n- 🔊 **Audio Detection** - Automatically handles videos with or without audio\n- 📊 **Progress Reporting** - Real-time updates on encoding status\n- ⚙️ **Functional Options** - Flexible configuration for threads, GPU, and logging\n- 🚀 **Hardware Acceleration** - Support for NVIDIA NVENC, Intel/AMD VAAPI, and Apple VideoToolbox\n- 🛡️ **100% Test Coverage** - Comprehensive test suite with mocked dependencies\n\n## 📋 Requirements\n\n- **Go** 1.20 or later\n- **FFmpeg** 4.4+ with libx264 and AAC support\n- **FFprobe** (comes with FFmpeg)\n\n## 📦 Installation\n\n```bash\ngo get github.com/farshidrezaei/mosaic\n```\n\n## 🚀 Quick Start\n\n\u003e 💡 **See full examples in the [`examples/`](./examples) directory.**\n\n### HLS Encoding\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"github.com/farshidrezaei/mosaic\"\n)\n\nfunc main() {\n\tjob := mosaic.Job{\n\t\tInput:     \"/path/to/input.mp4\",\n\t\tOutputDir: \"/output/hls\",\n\t\tProfile:   mosaic.ProfileVOD,\n\t\tProgressHandler: func(info mosaic.ProgressInfo) {\n\t\t\tfmt.Printf(\"Progress: %s, Speed: %s\\n\", info.CurrentTime, info.Speed)\n\t\t},\n\t}\n\n\t// Use functional options for more control\n\t_, err := mosaic.EncodeHls(context.Background(), job, \n\t\tmosaic.WithThreads(4),\n\t\tmosaic.WithGPU(),\n\t)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n```\n\n**Output:**\n\n```\n/output/hls/\n├── master.m3u8           # Master playlist\n├── stream_0.m3u8         # 1080p variant playlist\n├── stream_1.m3u8         # 720p variant playlist\n├── stream_2.m3u8         # 360p variant playlist\n├── seg_0_0.m4s           # 1080p segments\n├── seg_1_0.m4s           # 720p segments\n└── seg_2_0.m4s           # 360p segments\n```\n\n### DASH Encoding\n\n```go\njob := mosaic.Job{\nInput:     \"/path/to/input.mp4\", // or a url\nOutputDir: \"/output/dash\",\nProfile:   mosaic.ProfileLive,\n}\n\n_, err := mosaic.EncodeDash(context.Background(), job);\n\nif err != nil {\nlog.Fatal(err)\n}\n\n```\n\n**Output:**\n\n```\n/output/dash/\n├── manifest.mpd               # DASH manifest\n├── init-stream0.m4s           # Initialization segments\n├── chunk-stream0-00001.m4s    # Media chunks\n└── ...\n```\n\n## 🎚️ Encoding Profiles\n\n| Profile       | Segment Duration | Use Case          | Latency  |\n|---------------|------------------|-------------------|----------|\n| `ProfileVOD`  | 5 seconds        | On-demand content | Standard |\n| `ProfileLive` | 2 seconds        | Live streaming    | Low      |\n\n## 📐 Automatic Ladder\n\nMosaic intelligently builds an encoding ladder based on your source video:\n\n| Source Height | Generated Renditions                      |\n|---------------|-------------------------------------------|\n| ≥ 1080p       | 1080p (5200k), 720p (3000k), 360p (1000k) |\n| ≥ 720p        | 720p (3000k), 360p (1000k)                |\n| ≥ 360p        | 360p (1000k)                              |\n\n### Optimization Features\n\n1. **Bitrate Capping** - Prevents excessive bandwidth:\n    - 1080p max: 5000 kbps\n    - 720p max: 3000 kbps\n    - Others max: 1000 kbps\n\n2. **Rendition Trimming** - Removes redundant rungs when height ratio \u003c 0.7\n    - Example: 1080p + 540p → 720p skipped\n\n## 🏗️ Architecture\n\n```\nInput Video\n    │\n    ├─► Probe (FFprobe)\n    │   └─► Resolution, FPS, Audio Detection\n    │\n    ├─► Ladder Builder\n    │   └─► Generate Renditions (1080p, 720p, 360p)\n    │\n    ├─► Optimizer\n    │   └─► Cap Bitrates \u0026 Trim Redundant Renditions\n    │\n    └─► Encoder (FFmpeg)\n        ├─► HLS CMAF (fMP4 segments + master.m3u8)\n        └─► DASH CMAF (fMP4 segments + manifest.mpd)\n```\n\n## 🔧 Under the Hood\n\n### Video Encoding Settings\n\n- **Codec**: H.264/AVC (libx264)\n- **Pixel Format**: YUV 4:2:0\n- **Preset**: Medium (balanced speed/quality)\n- **Rate Control**: VBR with maxrate and bufsize\n- **GOP Structure**: Aligned to segment boundaries (FPS × segment_duration)\n- **Profiles**: Baseline (360p), Main (720p+)\n\n### Audio Encoding Settings\n\n- **Codec**: AAC\n- **Bitrate**: 96 kbps\n- **Channels**: Stereo (2.0)\n- **Sample Rate**: Automatic\n\n### FFmpeg Optimizations\n\n```bash\n-analyzeduration 100M    // Handle complex inputs\n-probesize 100M          // Thorough stream analysis\n-fflags +genpts          // Fix timestamp issues\n-sc_threshold 0          // Disable scene detection (consistent GOPs)\n```\n\n## 🧪 Testing Architecture\n\nMosaic is built with testability in mind, achieving **100% code coverage** on all production logic.\n\n### Dependency Injection\nThe library uses a `CommandExecutor` interface to abstract FFmpeg and FFprobe interactions. This allows for:\n- **Mocked Testing**: Run tests without installing FFmpeg\n- **Deterministic Results**: Simulate exact command outputs and errors\n- **Safety**: No accidental external command execution during tests\n\n### Running Tests\n```bash\n# Run all tests\ngo test ./...\n\n# Check coverage\ngo test ./... -cover\n\n# Run linter (if installed)\ngolangci-lint run\n```\n\n## 🧩 Package Structure\n\n```\nmosaic/\n├── .golangci.yml            # Linter configuration\n├── job.go                   # Job definition and profiles\n├── encode.go                # Main encoding functions\n├── probe/                   # Input video analysis\n├── ladder/                  # Rendition ladder building\n├── optimize/                # Bitrate optimization\n├── config/                  # Encoding profiles (VOD, LIVE)\n├── internal/                # Internal utilities (executor, mocks)\n└── encoder/\n    ├── common.go            # Shared utilities\n    ├── hls_cmaf.go          # HLS encoder\n    └── dash_cmaf.go         # DASH encoder\n```\n\n### Hardware Acceleration\n\nMosaic supports multiple hardware acceleration backends:\n\n```go\n// NVIDIA NVENC (Default)\nmosaic.EncodeHls(ctx, job, mosaic.WithNVENC())\n\n// Intel/AMD VAAPI\nmosaic.EncodeHls(ctx, job, mosaic.WithVAAPI())\n\n// Apple VideoToolbox\nmosaic.EncodeHls(ctx, job, mosaic.WithVideoToolbox())\n\n// Generic GPU option (defaults to NVENC)\nmosaic.EncodeHls(ctx, job, mosaic.WithGPU())\n```\n\n## 🎯 API Reference\n\n### Types\n\n```go\ntype Job struct {\n\tInput           string          // Path to input video\n\tOutputDir       string          // Output directory for segments/manifests\n\tProfile         Profile         // ProfileVOD or ProfileLive\n\tProgressHandler ProgressHandler // Optional progress callback\n}\n\ntype ProgressInfo struct {\n\tPercentage  float64\n\tCurrentTime string\n\tBitrate     string\n\tSpeed       string\n}\n\ntype ProgressHandler func(ProgressInfo)\n\ntype Profile string\nconst (\nProfileVOD  Profile = \"vod\"  // 5-second segments\nProfileLive Profile = \"live\" // 2-second segments\n)\n```\n\n### Functions\n\n```go\n// Encode to HLS with CMAF segments\nfunc EncodeHls(ctx context.Context, job Job, opts ...Option) error\n\n// Encode to HLS with a custom command executor\nfunc EncodeHlsWithExecutor(ctx context.Context, job Job, exec executor.CommandExecutor, opts ...Option) error\n\n// Encode to DASH with CMAF segments\nfunc EncodeDash(ctx context.Context, job Job, opts ...Option) error\n\n// Encode to DASH with a custom command executor\nfunc EncodeDashWithExecutor(ctx context.Context, job Job, exec executor.CommandExecutor, opts ...Option) error\n\n// Functional Options\nfunc WithThreads(n int) Option\nfunc WithGPU() Option\nfunc WithLogLevel(level string) Option\nfunc WithLogger(logger *slog.Logger) Option\n```\n\n## 🤝 Contributing\n\nContributions are welcome! Areas for improvement:\n\n- [ ] Parallel rendition encoding\n- [ ] HDR/10-bit support\n- [ ] Hardware acceleration (VAAPI, NVENC, QSV)\n- [ ] Custom audio configurations\n- [ ] AV1/VP9 codec support\n\n## 📄 License\n\nMIT License - see [LICENSE](./LICENSE) file for details\n\n## 🙏 Acknowledgments\n\nBuilt with [FFmpeg](https://ffmpeg.org/) - the Swiss Army knife of video processing.\n\n---\n\n**Made with ❤️ by [Farshid Rezaei](https://github.com/farshidrezaei)**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffarshidrezaei%2Fmosaic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffarshidrezaei%2Fmosaic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffarshidrezaei%2Fmosaic/lists"}