RepoPilotOpen in app →

AlexxIT/go2rtc

Ultimate camera streaming application

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 2w ago
  • 10 active contributors
  • MIT licensed
Show all 6 evidence items →
  • CI configured
  • Tests present
  • Concentrated ownership — top contributor handles 53% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/alexxit/go2rtc)](https://repopilot.app/r/alexxit/go2rtc)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/alexxit/go2rtc on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: AlexxIT/go2rtc

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/AlexxIT/go2rtc shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 2w ago
  • 10 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Concentrated ownership — top contributor handles 53% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live AlexxIT/go2rtc repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/AlexxIT/go2rtc.

What it runs against: a local clone of AlexxIT/go2rtc — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in AlexxIT/go2rtc | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 45 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>AlexxIT/go2rtc</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of AlexxIT/go2rtc. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/AlexxIT/go2rtc.git
#   cd go2rtc
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of AlexxIT/go2rtc and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "AlexxIT/go2rtc(\\.git)?\\b" \\
  && ok "origin remote is AlexxIT/go2rtc" \\
  || miss "origin remote is not AlexxIT/go2rtc (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "internal/app/app.go" \\
  && ok "internal/app/app.go" \\
  || miss "missing critical file: internal/app/app.go"
test -f "internal/api/api.go" \\
  && ok "internal/api/api.go" \\
  || miss "missing critical file: internal/api/api.go"
test -f "internal/ffmpeg/ffmpeg.go" \\
  && ok "internal/ffmpeg/ffmpeg.go" \\
  || miss "missing critical file: internal/ffmpeg/ffmpeg.go"
test -f "go.mod" \\
  && ok "go.mod" \\
  || miss "missing critical file: go.mod"
test -f "internal/app/config.go" \\
  && ok "internal/app/config.go" \\
  || miss "missing critical file: internal/app/config.go"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 45 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~15d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/AlexxIT/go2rtc"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

go2rtc is a zero-dependency streaming application written in Go that converts camera feeds from dozens of input protocols (RTSP, ONVIF, HLS, WebRTC, MJPEG, etc.) into multiple output formats simultaneously. It minimizes streaming latency through direct protocol translation and optional on-demand FFmpeg transcoding, serving as both a standalone binary and an embeddable library for camera streaming infrastructure. Monolithic Go application with internal/ subdirectories organized by function: internal/api/ handles HTTP/WebSocket APIs, internal/app/ manages configuration and logging, internal/alsa/ handles audio capture, internal/ffmpeg/ wraps transcoding, internal/bubble/ and protocol-specific modules handle streaming logic. Examples/ folder contains runnable integration patterns (HASS, HomeKit, ONVIF clients). Docker/ provides multiple deployment targets.

👥Who it's for

HomeKit integrators, IP camera system administrators, home automation developers (especially Home Assistant users), and security system integrators who need a lightweight, zero-dependency streaming bridge to unify camera feeds across multiple protocols without transcoding overhead.

🌱Maturity & risk

Production-ready and actively maintained. The project has substantial GitHub stars, comprehensive CI/CD workflows (.github/workflows/ contains build, test, and gh-pages automation), Docker support across multiple architectures (standard, hardware-accelerated, Rockchip variants), and extensive examples covering HASS, ONVIF, HomeKit, and custom integrations. Recent activity visible in Dockerfile variants and examples folder.

Low risk overall but single-maintainer project (AlexxIT). Dependency surface is intentionally minimal (core Go stdlib focus with optional FFmpeg integration). Go ecosystem dependencies in go.mod/go.sum are well-vetted (crypto, sys libraries). The architecture requires careful protocol handling (RTSP state machines, WebRTC negotiation) which could harbor subtle bugs, but no major breaking changes evident in structure.

Active areas of work

Active development across multiple fronts: hardware acceleration support (hardware.Dockerfile, rockchip.Dockerfile suggest ongoing optimization for edge devices), WebSocket API expansion (internal/api/ws/ module), and ecosystem integrations (examples covering HomeKit, Pinggy tunneling, TUTK decoder). CI workflows are comprehensive and passing.

🚀Get running

git clone https://github.com/AlexxIT/go2rtc.git && cd go2rtc && go build ./cmd/go2rtc (or download pre-built binary from releases). For Docker: docker pull alexxit/go2rtc. Configuration via YAML or environment variables; see docker/README.md and README.md for detailed setup.

Daily commands: go run ./cmd/go2rtc to start with defaults. Place go2rtc.yaml in current directory for configuration (protocol sources, listening ports, transcoding rules). Access web UI typically at http://localhost:1984. Docker: docker run -p 1984:1984 alexxit/go2rtc with volume mount for config file.

🗺️Map of the codebase

  • internal/app/app.go — Main application entry point and lifecycle management—every contributor must understand how go2rtc initializes and runs.
  • internal/api/api.go — HTTP API router and request dispatcher—core for adding any new API endpoints or handlers.
  • internal/ffmpeg/ffmpeg.go — FFmpeg integration and streaming producer—handles the heaviest codec/protocol abstraction in the codebase.
  • go.mod — Module dependency manifest with Go 1.25—required to understand the minimal dependency philosophy and any transitive deps.
  • internal/app/config.go — Configuration schema and parsing—defines how streams, devices, and credentials are loaded from YAML/JSON.
  • internal/api/ws/ws.go — WebSocket handler for real-time streaming updates—core for client-side push notifications and live feed management.

🛠️How to make changes

Add a New Camera Protocol Source

  1. Create a new package under internal/ with a main struct implementing the Source interface (e.g., internal/myprotocol/myprotocol.go). (internal/myprotocol/myprotocol.go)
  2. Implement Producer() and Close() methods to return a streaming producer that yields video/audio frames. (internal/myprotocol/myprotocol.go)
  3. Register your source factory in the stream config parser by adding a case in internal/app/config.go where streams are parsed from YAML. (internal/app/config.go)
  4. Add example config and documentation in the main README.md or examples/ folder. (README.md)

Add a New API Endpoint

  1. Define a new HTTP handler function in internal/api/api.go or a new file in internal/api/ that matches the mux pattern. (internal/api/api.go)
  2. Register the route in the Router setup within api.go using mux.HandleFunc or similar. (internal/api/api.go)
  3. If the endpoint returns JSON, use the existing config or app context to fetch data and marshal responses. (internal/api/api.go)
  4. For WebSocket endpoints, use internal/api/ws/ws.go as a pattern and register the upgrade in api.go. (internal/api/ws/ws.go)

Add Support for a New Output Format (e.g., DASH, WebRTC)

  1. Create a new directory under internal/ (e.g., internal/dash/) with a producer that consumes video/audio frames from FFmpeg. (internal/dash/dash.go)
  2. Implement playlist/manifest generation and segment chunking logic, following the HLS pattern from internal/hls. (internal/hls)
  3. Register the output format in the API config endpoint (internal/api/config.go) so users can select it for a stream. (internal/api/config.go)
  4. Add routes in internal/api/api.go to serve the manifest and segments (e.g., GET /dash/stream/playlist.mpd). (internal/api/api.go)

Enable Hardware Acceleration for a New Platform

  1. Create a platform-specific file (e.g., internal/ffmpeg/hardware/hardware_linux_cuda.go) with codec detection logic. (internal/ffmpeg/hardware/hardware_unix.go)
  2. Add FFmpeg encoder flags (e.g., -c:v h264_nvenc for NVIDIA) to the producer logic in internal/ffmpeg/producer.go. (internal/ffmpeg/producer.go)
  3. Update the hardware detection function in internal/ffmpeg/hardware/hardware.go to list available encoders at startup. (internal/ffmpeg/hardware/hardware.go)
  4. Add a test case in internal/ffmpeg/ffmpeg_test.go to verify the encoder is correctly selected. (internal/ffmpeg/ffmpeg_test.go)

🔧Why these technologies

  • Go 1.25 — Efficient concurrency with goroutines, static binaries, and minimal memory footprint for embedded/edge deployments.
  • FFmpeg (external process) — Decodes 100+ camera codecs and protocols; leverages decades of codec optimization and GPU acceleration without reimplementing.
  • HLS (HTTP Live Streaming) — Universal compatibility across iOS/Android/web clients; works over HTTP without special ports or firewall rules.
  • WebSocket (internal/api/ws) — Bidirectional real-time updates for dashboard and event streaming without polling overhead.
  • YAML Configuration — Human-readable config format; easy to version, template, and integrate with Home Assistant/docker-compose.

⚖️Trade-offs already made

  • External FFmpeg process instead of libav bindings

    • Why: Avoids C bindings complexity and licensing issues; leverages pre-compiled ffmpeg on host system.
    • Consequence: Process spawning overhead (~500ms) and IPC latency; requires FFmpeg binary in PATH; cannot hot-reload codecs.
  • Minimal external Go dependencies (pinggy only for examples)

    • Why: Reduces supply-chain risk and binary size; makes the app lean for embedded systems.
    • Consequence: Reimplements some protocols and utilities (HTTP, muxing); higher maintenance burden for edge cases.
  • Single-process architecture with goroutine-per-stream

    • Why: Simple deployment and low resource overhead; goroutines are cheap and manageable.
    • Consequence: Process crash affects all streams; no stream isolation; harder to enforce per-stream resource limits.
  • File-based config and storage (internal/app/storage.go)

    • Why: Zero external database dependency; works offline and in ephemeral containers.
    • Consequence: No concurrent config writes; not suitable for high-frequency updates; no transactional consistency.

🚫Non-goals (don't propose these)

  • Does not provide authentication/authorization (assumed behind a reverse proxy or local network).
  • Does not record/store video to disk by default (focus is real-time streaming only)

🪤Traps & gotchas

FFmpeg integration is optional but no graceful degradation for advanced codecs—if FFmpeg unavailable and codec requires transcoding, stream fails silently. ALSA audio capture (internal/alsa/alsa_linux.go) is Linux-only; Windows/macOS audio handling delegated to platform specifics. Rockchip and hardware Dockerfiles assume specific H.264/H.265 acceleration; misconfiguration causes performance regression not obvious in logs. WebSocket API (internal/api/ws/) maintains in-memory stream state; no persistence across restarts. Config hot-reload not explicitly documented; changes may require restart.

🏗️Architecture

💡Concepts to learn

  • RTSP State Machine — RTSP protocol requires careful stateful negotiation (DESCRIBE, SETUP, PLAY); go2rtc must implement client/server state machines correctly to avoid stream hangs—study the protocol module structure to debug streaming timeouts
  • GStreamer-style Pipeline Routing — go2rtc routes streams through modular handlers (source → codec parser → output); understanding this pipeline pattern is key to adding new codecs or output formats
  • WebRTC ICE Candidate Gathering — Browser-to-camera WebRTC connections require NAT traversal via ICE agents; the Pion library handles this but misconfiguration causes firewall/connectivity issues
  • H.264/H.265 Codec Negotiation — Cameras often emit H.264/H.265; browsers may not support H.265; go2rtc's transcoding decision logic must correctly identify when FFmpeg is necessary vs. direct passthrough
  • Zero-Copy Stream Buffering — go2rtc minimizes latency by avoiding frame copies; understanding how RTP packets are buffered and forwarded between protocol handlers prevents memory leaks in long-running streams
  • Hardware Video Acceleration (VAAPI/NVENC) — hardware.Dockerfile and rockchip.Dockerfile leverage GPU transcoding; these require careful FFmpeg codec selection and driver availability—critical for performance on edge devices
  • mDNS Service Discovery — examples/mdns/ shows service advertisement; cameras often use mDNS for discovery; understanding Avahi/Bonjour integration helps with zero-config setups
  • aler9/rtsp-simple-server — Direct predecessor and inspiration; pure-Go RTSP server that influenced go2rtc's protocol handling approach
  • pion/webrtc — Dependency library providing WebRTC client/server capability; go2rtc wraps this for browser streaming
  • deepch/RTCPeeringConnection — Related streaming project from @deepch (acknowledged inspiration); provides WebRTC peer patterns
  • home-assistant/core — Primary end-user integration target; go2rtc is often deployed as camera stream provider for Home Assistant
  • brutella/hap — HomeKit Accessory Protocol library; go2rtc examples show HomeKit integration leveraging this pattern

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive test coverage for internal/api/config.go

The internal/api directory has a config.go file but there's no visible test file (config_test.go) in the repository structure. Given that API configuration is critical for the streaming application and affects how cameras are configured and exposed via HTTP/WebSocket, adding unit tests would catch regressions early. This is particularly important since the config module likely parses user input and validates camera stream configurations.

  • [ ] Create internal/api/config_test.go with tests for config parsing
  • [ ] Add test cases for invalid/malformed camera configurations
  • [ ] Test config marshaling/unmarshaling with real-world YAML/JSON examples
  • [ ] Verify error handling for missing required fields in camera definitions
  • [ ] Run tests locally via 'go test ./internal/api/...' and ensure CI includes this via .github/workflows/test.yml

Add unit tests for internal/app/log.go logging infrastructure

The internal/app/log.go module handles application-wide logging but appears to have no corresponding test file. Since logging is a cross-cutting concern used throughout the codebase (as evidenced by log imports across internal packages), adding tests ensures log levels, formatting, and output streams work correctly. This prevents silent failures in production monitoring and helps new contributors understand the logging API.

  • [ ] Create internal/app/log_test.go with tests for different log levels (Debug, Info, Warn, Error)
  • [ ] Test log output formatting and ensure sensitive data isn't exposed
  • [ ] Verify log level filtering works correctly
  • [ ] Test concurrent logging to ensure thread-safety
  • [ ] Add tests to .github/workflows/test.yml if not already running ./internal/app/... tests

Create GitHub Action workflow for testing Docker builds across multiple Dockerfile variants

The repo has 4 Dockerfile variants (docker/Dockerfile, docker/hardware.Dockerfile, docker/rockchip.Dockerfile, and implied base) but there's no visible CI workflow in .github/workflows/ that validates these builds. This is a significant gap since multi-platform Docker support is a key feature (per the Docker Hub badge in README). Adding a workflow prevents broken builds from being merged and reduces maintainer effort.

  • [ ] Create .github/workflows/docker-build.yml that builds all Dockerfile variants on push to main/release branches
  • [ ] Use docker/setup-buildx-action and docker/build-push-action for multi-platform builds
  • [ ] Add build matrix for at least docker/Dockerfile and docker/hardware.Dockerfile
  • [ ] Cache Docker layers using GitHub Actions cache or buildx cache to speed up CI
  • [ ] Set workflow to run on: [push, pull_request] for branches [main, develop] and tag releases

🌿Good first issues

  • Add comprehensive test coverage for internal/app/config.go YAML parsing; no test files visible for configuration validation of stream sources and protocol options
  • Write Go doc comments (godoc) for public functions in internal/api/api.go and internal/api/config.go; current codebase likely lacks inline API documentation for library users
  • Create a Makefile or build script documentation in internal/README.md explaining the module dependencies and build sequence; helps new contributors understand protocol module initialization order

Top contributors

Click to expand

📝Recent commits

Click to expand
  • dc1685e — Merge pull request #2159 from ludufre/fix/mpegts-pcma-pcmu-probe (AlexxIT)
  • 65af579 — fix: remove PCMU, keep only PCMA (always 8000 Hz per G.711 spec) (ludufre)
  • d9af354 — fix: add PCMU to StreamType() mapping (ludufre)
  • 31c19a0 — fix: incoming pcma and pcmu (ludufre)
  • 01c7451 — Restore fix audio sample rate for some xiaomi cameras #2006 (AlexxIT)
  • f68c602 — Add sitemap to website (AlexxIT)
  • 7f36033 — Merge pull request #2080 from skrashevich/260208-fix-grammar (AlexxIT)
  • 6304987 — Review uncommitted changes (skrashevich)
  • 2735baf — Rename mpegts module to mpeg (AlexxIT)
  • 44f6f11 — Move kasa source to separate module (AlexxIT)

🔒Security observations

  • High · Outdated Cryptographic Dependencies — examples/mod_pinggy/go.mod. The pinggy module uses golang.org/x/crypto v0.8.0 (released March 2023) which may contain known vulnerabilities. Current versions are significantly newer. This dependency should be updated to the latest stable version. Fix: Update golang.org/x/crypto to the latest version (v0.17.0 or newer). Run 'go get -u golang.org/x/crypto' and review release notes for any breaking changes.
  • High · Outdated System Dependency — examples/mod_pinggy/go.mod. The golang.org/x/sys v0.7.0 dependency (released March 2023) is outdated and may lack security patches. This low-level package handles system interactions and should be kept current. Fix: Update golang.org/x/sys to the latest version (v0.15.0 or newer). Run 'go get -u golang.org/x/sys' to apply patches.
  • Medium · Indirect Dependency Management — examples/mod_pinggy/go.mod. The pinggy-go module is marked as 'indirect' in go.mod but is being used as a primary dependency. This suggests potential indirect dependency resolution issues that could mask security updates or cause version conflicts. Fix: Review the actual usage of pinggy-go package. If it's directly imported, remove the '// indirect' comment. If truly indirect, ensure it's properly documented in the module hierarchy.
  • Medium · Missing Go Module Integrity Verification — examples/mod_pinggy/go.sum. No go.sum content was provided for examples/mod_pinggy. Without go.sum, module integrity checks cannot be performed, increasing risk of supply chain attacks or dependency tampering. Fix: Ensure go.sum file exists and is committed to version control. Run 'go mod tidy' and 'go mod verify' to generate and validate module checksums. Review go.sum for all dependencies regularly.
  • Medium · Potential Command Injection Risk — internal/exec/. The presence of internal/exec module suggests command execution functionality. Without reviewing the actual implementation, this is a common attack vector in streaming applications that may execute FFmpeg or other tools with user-supplied input. Fix: Review internal/exec/exec.go for proper input sanitization. Ensure all external command invocations use properly escaped arguments, avoid shell=true, and validate all user inputs before passing to exec functions.
  • Medium · Expression Evaluation Module — internal/expr/. The internal/expr module suggests dynamic expression evaluation capability. This could introduce arbitrary code execution risks if expressions are derived from untrusted sources (user input, config files). Fix: Review expr.go implementation to understand evaluation scope. Ensure expressions are not directly evaluated from user input. Implement allowlists for safe operations and disable dangerous functions (exec, system calls).
  • Low · Debug Module Exposed — internal/debug/. The internal/debug module with stack trace functionality could leak sensitive information in error responses if debug output is sent to clients or logged inappropriately. Fix: Ensure debug output is only enabled in development environments. Implement proper log levels that exclude stack traces from production error responses. Review internal/debug/stack.go for information disclosure risks.
  • Low · WebSocket Implementation Present — internal/api/ws/ws.go. WebSocket functionality exists in internal/api/ws/. WebSockets can be vulnerable to CSRF attacks, improper message validation, and privilege escalation if not properly secured. Fix: Verify WebSocket implementation includes: CSRF token validation, message input sanitization, proper authentication/authorization checks, rate limiting, and secure header validation (Origin, Sec-WebSocket headers).
  • Low · Multiple Protocol Support — internal/ (doorbird, dvrip, eseecloud, etc.). The codebase implements many protocols (RTSP, ONVIF, HomeKit, etc.) with varying security maturity. Each integration point is a potential security vector. Fix: Conduct security review of each protocol implementation. Verify TLS/SSL usage for

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · AlexxIT/go2rtc — RepoPilot