# Technical Documentation: AlexxIT/go2rtc

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/AlexxIT/go2rtc)

### Overview (`README.md`)

<h1 align="center">
  <a href="https://github.com/AlexxIT/go2rtc">
    <img src="./website/images/logo.gif" alt="go2rtc - GitHub">
  </a>
</h1>
<p align="center">
  <a href="https://github.com/AlexxIT/go2rtc/stargazers" target="_blank">
    <img style="display: inline" src="https://img.shields.io/github/stars/AlexxIT/go2rtc?style=flat-square&logo=github" alt="go2rtc - GitHub Stars">
  </a>
  <a href="https://hub.docker.com/r/alexxit/go2rtc" target="_blank">
    <img style="display: inline" src="https://img.shields.io/docker/pulls/alexxit/go2rtc?style=flat-square&logo=docker&logoColor=white&label=pulls" alt="go2rtc - Docker Pulls">
  </a>
  <a href="https://github.com/AlexxIT/go2rtc/releases" target="_blank">
    <img style="display: inline" src="https://img.shields.io/github/downloads/AlexxIT/go2rtc/total?color=blue&style=flat-square&logo=github" alt="go2rtc - GitHub Downloads">
  </a>
</p>
<p align="center">
  <a href="https://trendshift.io/repositories/4628" target="_blank">
    <img src="https://trendshift.io/api/badge/repositories/4628" alt="go2rtc - Trendshift"/>
  </a>
</p>

Ultimate camera streaming application with support for dozens formats and protocols.

- zero-dependency [small app](#go2rtc-binary) for all OS (Windows, macOS, Linux, FreeBSD)
- zero-delay for many [supported protocols](#codecs-madness) (lowest possible streaming latency)
- [streaming input](#streaming-input) from dozens formats and protocols
- [streaming output](#streaming-output) in all popular formats
- [streaming ingest](#streaming-ingest) in a number of popular formats
- [publish](#publish-stream) any source to popular streaming services (YouTube, Telegram)
- on-the-fly transcoding only if necessary via [FFmpeg](internal/ffmpeg/README.md)
- [two-way audio](#two-way-audio) support for many formats
- [streaming audio](#stream-to-camera) to all cameras with [two-way audio](#two-way-audio) support
- mixing tracks from different sources to single stream
- [auto-match](www/README.md#javascript-api) client-supported streaming formats and codecs
- [streaming stats](#streaming-stats) for all active connections
- can be [integrated to any project](#projects-using-go2rtc) or be used as [standalone app](#go2rtc-binary)

#### Inspired by

- series of streaming projects from [@deepch](https://github.com/deepch)
- [webrtc](https://github.com/pion/webrtc) go library and whole [@pion](https://github.com/pion) team
- [rtsp-simple-server](https://github.com/aler9/rtsp-simple-server) idea from [@aler9](https://github.com/aler9)
- [GStreamer](https://gstreamer.freedesktop.org/) framework pipeline idea
- [MediaSoup](https://mediasoup.org/) framework routing idea
- HomeKit Accessory Protocol from [@brutella](https://github.com/brutella/hap)
- creator of the project's logo [@v_novoseltsev](https://www.instagram.com/v_novoseltsev)

<br>
<details>
<summary><b>Table of Contents</b></summary>

- [Installation](#installation)
  - [go2rtc: Binary](#go2rtc-binary)
  - [go2rtc: Docker](#go2rtc-docker)
  - [go2rtc: Home Assistant add-on](#go2rtc-home-assistant-add-on)
  - [go2rtc: Home Assistant Integration](#go2rtc-home-assistant-integration)
  - [go2rtc: Master version](#go2rtc-master-version)
- [Configuration](#configuration)
- [Features](#features)
  - [Streaming input](#streaming-input)
  - [Streaming output](#streaming-output)
  - [Streaming ingest](#streaming-ingest)
  - [Two-way audio](#two-way-audio)
  - [Stream to camera](#stream-to-camera)
  - [Publish stream](#publish-stream)
  - [Preload stream](#preload-stream)
  - [Streaming stats](#streaming-stats)
- [Codecs](#codecs)
  - [Codecs filters](#codecs-filters)
  - [Codecs madness](#codecs-madness)
  - [Built-in transcoding](#built-in-transcoding)
  - [Codecs negotiation](#codecs-negotiation)
- [Security](#security)
- [Projects using go2rtc](#projects-using-go2rtc)
- [Camera experience](#camera-experience)
- [Tips](#tips)

</details>

## Installation

1. Download [binary](#go2rtc-binary) or use [Docker](#go2rtc-docker) or Home Assistant [add-on](#go2rtc-home-assistant-add-on) or [integration](#go2rtc-home-assistant-integration)
2. Open web interface: `http://localhost:1984/`
3. Add [streams](#streaming-input) to [config](#configuration)

**Developers:** integrate [HTTP API](internal/api/README.md) into your smart home platform.

### go2rtc: Binary

Download binary for your OS from [latest release](https://github.com/AlexxIT/go2rtc/releases/):

| name                                                                                                            | description                                                                                                                               |
|-----------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|
| [go2rtc_win64.zip](https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_win64.zip)                 | Windows 10+ 64-bit                                                                                                                        |
| [go2rtc_win32.zip](https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_win32.zip)                 | Windows 10+ 32-bit                                                                                                                        |
| [go2rtc_win_arm64.zip](https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_win_arm64.zip)         | Windows ARM 64-bit                                                                                                                        |
| [go2rtc_linux_amd64](https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_linux_amd64)             | Linux 64-bit                                                                                                                              |
| [go2rtc_linux_i386](https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_linux_i386)               | Linux 32-bit                                                                                                                              |
| [go2rtc_linux_arm64](https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_linux_arm64)             | Linux ARM 64-bit (ex. Raspberry 64-bit OS)                                                                                                |
| [go2rtc_linux_arm](https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_linux_arm)                 | Linux ARM 32-bit (ex. Raspberry 32-bit OS)                                                                                                |
| [go2rtc_linux_armv6](https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_linux_armv6)             | Linux ARMv6 (for old Raspberry 1 and Zero)                                                                                                |
| [go2rtc_linux_mipsel](https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_linux_mipsel)           | Linux MIPS (ex. [Xiaomi Gateway 3](https://github.com/AlexxIT/XiaomiGateway3), [Wyze cameras](https://github.com/gtxaspec/wz_mini_hacks)) |
| [go2rtc_mac_amd64.zip](https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_mac_amd64.zip)         | macOS 11+ Intel 64-bit                                                                                                                    |
| [go2rtc_mac_arm64.zip](https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_mac_arm64.zip)         | macOS ARM 64-bit                                                                                                                          |
| [go2rtc_freebsd_amd64.zip](https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_freebsd_amd64.zip) | FreeBSD 64-bit                                                                                                                            |
| [go2rtc_freebsd_arm64.zip](https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_freebsd_arm64.zip) | FreeBSD ARM 64-bit                                                                                                                        |

Don't forget to fix the rights `chmod +x go2rtc_xxx_xxx` on Linux and Mac.

PS. The application is compiled with the latest versions of the Go language for maximum speed and security. Therefore, the [minimum OS versions](https://go.dev/wiki/MinimumRequirements) depend on the Go language.

### go2rtc: Docker

The Docker containers [`alexxit/go2rtc`](https://hub.docker.com/r/alexxit/go2rtc) and [`ghcr.io/alexxit/go2rtc`](https://github.com/AlexxIT/go2rtc/pkgs/container/go2rtc) support multiple architectures including `386`, `amd64`, `arm/v6`, `arm/v7` and `arm64`.
These containers offer the same functionality as the Home Assistant [add-on](#go2rtc-home-assistant-add-on) but are designed to operate independently of Home Assistant.
It comes preinstalled with [FFmpeg](internal/ffmpeg/README.md) and [Python](internal/echo/README.md).

### go2rtc: Home Assistant add-on

[](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2FAlexxIT%2Fhassio-addons)

1. Settings > Add-ons > Plus > Repositories > Add
   ```
   https://github.com/AlexxIT/hassio-addons
   ```
2. go2rtc > Install > Start

### go2rtc: Home Assistant Integration

[WebRTC Camera](https://github.com/AlexxIT/WebRTC) custom component can be used on any Home Assistant [installation](https://www.home-assistant.io/installation/), including [HassWP](https://github.com/AlexxIT/HassWP) on Windows. It can automatically download and use the latest version of go2rtc. Or it can connect to an existing version of go2rtc. Addon installation in this case is optional.

### go2rtc: Master version

Latest, but maybe unstable version:

- Binary: [latest master build](https://nightly.link/AlexxIT/go2rtc/workflows/build/master)
- Docker: `alexxit/go2rtc:master` or `alexxit/go2rtc:master-hardware` versions
- Home Assistant add-on: `go2rtc master` or `go2rtc master hardware` versions

## Configuration

This is the `go2rtc.yaml` file in [YAML-format](https://en.wikipedia.org/wiki/YAML).
The configuration can be changed in the [WebUI](www/README.md) at `http://localhost:1984`.
The editor provides syntax highlighting and checking.



The simplest config looks like this:

```yaml
streams:
  hall-camera: rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=0
```

- by default go2rtc will search `go2rtc.yaml` in the current work directory
- `api` server will start on default **1984 port** (TCP)
- `rtsp` server will start on default **8554 port** (TCP)
- `webrtc` will use port **8555** (TCP/UDP) for connections

More information can be [found here](internal/app/README.md).

## Features

A summary table of all modules and features can be found [here](internal/README.md).

**Core modules**

- [`app`](internal/app/README.md) - Reading [configs](internal/app/README.md) and setting up [logs](internal/app/README.md#log).
- [`api`](internal/api/README.md) - Handle [HTTP](internal/api/README.md) and [WebSocket](internal/api/ws/README.md) API.
- [`streams`](internal/streams/README.md) - Handle a list of streams.

### Streaming input

#### public protocols

- [`mpjpeg`](internal/mjpeg/README.md#mjpeg-client) - The legacy but still used [MJPEG](https://en.wikipedia.org/wiki/Motion_JPEG) protocol for real-time media transmission.
- [`onvif`](internal/onvif/README.md#onvif-client) - A popular [ONVIF](https://en.wikipedia.org/wiki/ONVIF) protocol for receiving media in RTSP format.
- [`rtmp`](internal/rtmp/README.md#rtmp-client) - The legacy but still used [RTMP](https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol) protocol for real-time media transmission.
- [`rtsp`](internal/rtsp/README.md#rtsp-client) - The most common [RTSP](https://en.wikipedia.org/wiki/Real-Time_Streaming_Protocol) protocol for real-time media transmission.
- [`webrtc`](internal/webrtc/README.md#webrtc-client) - [WebRTC](https://en.wikipedia.org/wiki/WebRTC) web-compatible protocol for real-time media transmission.
- [`yuv4mpegpipe`](internal/http/README.md#tcp) - Raw [YUV](https://en.wikipedia.org/wiki/Y%E2%80%B2UV) frame stream with [YUV4MPEG](https://manned.org/yuv4mpeg) header.

#### private protocols

- [`bubble`](internal/bubble/README.md) - Some NVR from [dvr163.com](http://help.dvr163.com/) and [eseecloud.com](http://www.eseecloud.com/).
- [`doorbird`](internal/doorbird/README.md) - [Doorbird](https://www.doorbird.com/) devices with two-way audio.
- [`dvrip`](internal/dvrip/README.md) - DVR-IP NVR, NetSurveillance, Sofia protocol (XMeye SDK).
- [`eseecloud`](internal/eseecloud/README.md) - Some NVR from [dvr163.com](http://help.dvr163.com/) and [eseecloud.com](http://www.eseecloud.com/).
- [`gopro`](internal/gopro/README.md) - [GoPro](https://gopro.com/) cameras, connected via USB or Wi-Fi.
- [`hass`](internal/hass/README.md) - Import cameras from [Home Assistant](https://www.home-assistant.io/) config files.
- [`homekit`](internal/homekit/README.md) - Cameras with [Apple HomeKit](https://www.apple.com/home-app/accessories/) protocol.
- [`isapi`](internal/isapi/README.md) - Two-way audio for [Hikvision ISAPI](https://tpp.hikvision.com/download/ISAPI_OTAP) protocol.
- [`kasa`](internal/kasa/README.md) - [TP-Link Kasa](https://www.kasasmart.com/) cameras.
- [`multitrans`](internal/multitrans/README.md) - Two-way audio for Chinese version of [TP-Link](https://www.tp-link.com.cn/) cameras.
- [`nest`](internal/nest/README.md) - [Google Nest](https://developers.google.com/nest/device-access/supported-devices) cameras through user-unfriendly and paid APIs.
- [`ring`](internal/ring/README.md) - Ring cameras with two-way audio support.
- [`roborock`](internal/roborock/README.md) - [Roborock](https://roborock.com/) vacuums with cameras with two-way audio support. 
- [`tapo`](internal/tapo/README.md) - [TP-Link Tapo](https://www.tapo.com/) cameras with two-way audio support.
- [`vigi`](internal/tapo/README.md#tp-link-vigi) - TP-Link Vigi cameras.
- [`tuya`](internal/tuya/README.md) - [Tuya](https://www.tuya.com/) ecosystem cameras with two-way audio support.
- [`webtorrent`](internal/webtorrent/README.md) - Stream from another go2rtc via [WebTorrent](https://en.wikipedia.org/wiki/WebTorrent) protocol.
- [`wyze`](internal/wyze/README.md) - [Wyze](https://wyze.com/) cameras using native P2P protocol
- [`xiaomi`](internal/xiaomi/README.md) - [Xiaomi Mi Home](https://home.mi.com/) ecosystem cameras with two-way audio support.

#### devices

- [`alsa`](internal/alsa/README.md) - A [framework](https://en.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture) for receiving audio from devices on Linux OS.
- [`v4l2`](internal/v4l2/README.md) - A [framework](https://en.wikipedia.org/wiki/Video4Linux) for receiving video from devices on Linux OS.

#### files

- [`adts`](internal/http/README.md#tcp) - Audio stream in [AAC](https://en.wikipedia.org/wiki/Advanced_Audio_Coding) codec with Audio Data Transport Stream headers.
- [`flv`](internal/http/README.md#tcp) - The legacy but still used [Flash Video](https://en.wikipedia.org/wiki/Flash_Video) format.
- [`h264`](internal/http/README.md#tcp) - AVC/H.264 bitstream.
- [`hevc`](internal/http/README.md#tcp) - HEVC/H.265 bitstream.
- [`hls`](internal/http/README.md) - A popular [HTTP Live Streaming](https://en.wikipedia.org/wiki/HTTP_Live_Streaming) format.
- [`mjpeg`](internal/http/README.md#tcp) - A continuous sequence of JPEG frames (without HTTP headers).
- [`mpegts`](internal/http/README.md#tcp) - The legacy [MPEG transport stream](https://en.wikipedia.org/wiki/MPEG_transport_stream) format.
- [`wav`](internal/http/README.md#tcp) - Audio stream in [Waveform Audio File](https://en.wikipedia.org/wiki/WAV) format.

#### scripts

- [`echo`](internal/echo/README.md) - If the source has a dynamic link, you can use a bash or python script to get it.
- [`exec`](internal/exec/README.md) - You can run an external application (`ffmpeg`, `gstreamer`, `rpicam`, etc.) and receive a media stream from it.
- [`expr`](internal/expr/README.md) - If the source has a dynamic link, you can use [Expr](https://github.com/expr-lang/expr) language to get it.
- [`ffmpeg`](internal/ffmpeg/README.md) - Use [FFmpeg](https://ffmpeg.org/) as a stream source. Hardware-accelerated transcoding and streaming from USB devices are supported.

#### webrtc

- [`creality`](internal/webrtc/README.md#creality) - [Creality](https://www.creality.com/) 3D printer cameras.
- [`kinesis`](internal/webrtc/README.md#kinesis) - [Amazon Kinesis](https://aws.amazon.com/kinesis/video-streams/) video streams.
- [`openipc`](internal/webrtc/README.md#openipc) - Cameras on open-source [OpenIPC](https://openipc.org/) firmware.
- [`switchbot`](internal/webrtc/README.md#switchbot) - [SwitchBot](https://us.switch-bot.com/) cameras.
- [`whep`](internal/webrtc/README.md#whep) - [WebRTC/WHEP](https://datatracker.ietf.org/doc/draft-murillo-whep/) is replaced by [WebRTC/WISH](https://datatracker.ietf.org/doc/charter-ietf-wish/02/) standard for WebRTC video/audio viewers.
- [`wyze`](internal/webrtc/README.md#wyze) - Legacy method to connect to [Wyze](https://www.wyze.com/) cameras via [docker-wyze-bridge](https://github.com/mrlt8/docker-wyze-bridge).

### Streaming output

- [`adts`](internal/mpeg/README.md) - Output stream in ADTS format with [AAC](https://en.wikipedia.org/wiki/Advanced_Audio_Coding) audio.
- [`ascii`](internal/mjpeg/README.md#ascii) - Just for fun stream as [ASCII to Terminal](https://www.youtube.com/watch?v=sHj_3h_sX7M).
- [`flv`](internal/rtmp/README.md) - Output stream in [Flash Video](https://en.wikipedia.org/wiki/Flash_Video) format.
- [`hls`](internal/hls/README.md) - Output stream in [HTTP Live Streaming](https://en.wikipedia.org/wiki/HTTP_Live_Streaming) format.
- [`homekit`](internal/homekit/README.md#homekit-server) - Output stream to [Apple Home](https://www.apple.com/home-app/) using [HomeKit](https://en.wikipedia.org/wiki/Apple_Home) protocol.
- [`jpeg`](internal/mjpeg/README.md#jpeg) - Output snapshots in [JPEG](https://en.wikipedia.org/wiki/JPEG) format.
- [`mpjpeg`](internal/mjpeg/README.md#mpjpeg) - Output a stream in [MJPEG](https://en.wikipedia.org/wiki/Motion_JPEG) format.
- [`mp4`](internal/mp4/README.md) - Output as [MP4 stream](https://en.wikipedia.org/wiki/Progressive_download) or [Media Source Extensions](https://developer.mozilla.org/en-US/docs/Web/API/Media_Source_Extensions_API) (MSE) compatible format.
- [`mpegts`](internal/mpeg/README.md) - Output stream in [MPEG transport stream](https://en.wikipedia.org/wiki/MPEG_transport_stream) format.
- [`onvif`](internal/onvif/README.md#onvif-server) - Output stream using [ONVIF](https://en.wikipedia.org/wiki/ONVIF) protocol.
- [`rtmp`](internal/rtmp/README.md#rtmp-server) - Output stream using [Real-Time Messaging](https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol) protocol.
- [`rtsp`](internal/rtsp/README.md#rtsp-server) - Output stream using [Real-Time Streaming](https://en.wikipedia.org/wiki/Real-Time_Streaming_Protocol) protocol.
- [`webrtc`](internal/webrtc/README.md#webrtc-server) - Output stream using [Web Real-Time Communication](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API) API.
- [`webtorrent`](internal/webtorrent/README.md#webtorrent-server) - Output stream using [WebTorrent](https://en.wikipedia.org/wiki/WebTorrent) protocol.
- [`yuv4mpegpipe`](internal/mjpeg/README.md#yuv4mpegpipe) - Output in raw [YUV](https://en.wikipedia.org/wiki/Y%E2%80%B2UV) frame stream with [YUV4MPEG](https://manned.org/yuv4mpeg) header.

### Streaming ingest

Supported for: 
[`flv`](internal/rtmp/README.md#flv-server), 
[`mjpeg`](internal/mjpeg/README.md#streaming-ingest), 
[`mpegts`](internal/mpeg/README.md#streaming-ingest), 
[`rtmp`](internal/rtmp/README.md#rtmp-server), 
[`rtsp`](internal/rtsp/README.md#streaming-ingest), 
[`webrtc`](internal/webrtc/README.md#streaming-ingest).

This is a feature when go2rtc expects to receive an incoming stream from an external application. The stream transmission is started and stopped by an external application.

- You can push data only to an existing stream (create a stream with empty source in config).
- You can push multiple incoming sources to the same stream.
- You can push data to a non-empty stream, so it will have additional codecs inside.

### Two-way audio

Supported for:
[`doorbird`](internal/doorbird/README.md), 
[`dvrip`](internal/dvrip/README.md), 
[`exec`](internal/exec/README.md), 
[`isapi`](internal/isapi/README.md), 
[`multitrans`](internal/multitrans/README.md), 
[`ring`](internal/ring/README.md), 
[`roborock`](internal/roborock/README.md), 
[`rtsp`](internal/rtsp/README.md#two-way-audio), 
[`tapo`](internal/tapo/README.md), 
[`tuya`](internal/tuya/README.md), 
[`webrtc`](internal/webrtc/README.md), 
[`wyze`](internal/wyze/README.md), 
[`xiaomi`](internal/xiaomi/README.md).

Two-way audio can be used in browser with [WebRTC](internal/webrtc/README.md) technology. The browser will give access to the microphone only for HTTPS sites ([read more](https://stackoverflow.com/questions/52759992/how-to-access-camera-and-microphone-in-chrome-without-https)).

### Stream to camera

You can play audio files or live streams on any camera with [two-way audio](#two-way-audio) support.

[read more](internal/streams/README.md#stream-to-camera)

### Publish stream

You can publish any stream to streaming services (YouTube, Telegram, etc.) via RTMP/RTMPS.

[read more](internal/streams/README.md#publish-stream)

### Preload stream

You can preload any stream on go2rtc start. This is useful for cameras that take a long time to start up.

[read more](internal/streams/README.md#preload-stream)

### Streaming stats

[WebUI](www/README.md) provides detailed information about all active connections, including IP-addresses, formats, protocols, number of packets and bytes transferred. 
Via the [HTTP API](internal/api/README.md) in [`json`](https://en.wikipedia.org/wiki/JSON) or [`dot`](https://en.wikipedia.org/wiki/DOT_(graph_description_language)) format on an interactive connection map.



## Codecs

If you have questions about why video or audio is not displayed, you need to read the following sections.

| Name                         | FFmpeg   | RTSP          | Aliases     |
|------------------------------|----------|---------------|-------------|
| Advanced Audio Coding        | `aac`    | MPEG4-GENERIC |             |
| Advanced Video Coding        | `h264`   | H264          | AVC, H.264  |
| G.711 PCM (A-law)            | `alaw`   | PCMA          | G711A       |
| G.711 PCM (µ-law)            | `mulaw`  | PCMU          | G711u       |
| High Efficiency Video Coding | `hevc`   | H265          | HEVC, H.265 |
| Motion JPEG                  | `mpjpeg` | JPEG          |             |
| MPEG-1 Audio Layer III       | `mp3`    | MPA           |             |
| Opus Codec                   | `opus`   | OPUS          |             |
| PCM signed 16-bit big-endian | `s16be`  | L16           |             |

### Codecs filters

go2rtc can automatically detect which codecs your device supports for [WebRTC](internal/webrtc/README.md) and [MSE](internal/mp4/README.md) technologies.

But it cannot be done for [RTSP](internal/rtsp/README.md), [HTTP progressive streaming](internal/mp4/README.md), [HLS](internal/hls/README.md) technologies. 
You can manually add a codec filter when you create a link to a stream. 
The filters work the same for all three technologies. 
Filters do not create a new codec, they only select the suitable codec from existing sources. 
You can add new codecs to the stream using the [FFmpeg transcoding](internal/ffmpeg/README.md).

Without filters:

- RTSP will provide only the first video and only the first audio (any codec)
- MP4 will include only compatible codecs (H264, H265, AAC)
- HLS will output in the legacy TS format (H264 without audio)

Some examples:

- `rtsp://192.168.1.123:8554/camera1?mp4` - useful for recording as MP4 files (e.g. Home Assistant or Frigate)
- `rtsp://192.168.1.123:8554/camera1?video=h264,h265&audio=aac` - full version of the filter above
- `rtsp://192.168.1.123:8554/camera1?video=h264&audio=aac&audio=opus` - H264 video codec and two separate audio tracks
- `rtsp://192.168.1.123:8554/camera1?video&audio=all` - any video codec and all audio codecs as separate tracks
- `http://192.168.1.123:1984/api/stream.m3u8?src=camera1&mp4` - HLS stream with MP4 compatible codecs (HLS/fMP4)
- `http://192.168.1.123:1984/api/stream.m3u8?src=camera1&mp4=flac` - HLS stream with PCMA/PCMU/PCM audio support (HLS/fMP4), won't work on old devices
- `http://192.168.1.123:1984/api/stream.mp4?src=camera1&mp4=flac` - MP4 file with PCMA/PCMU/PCM audio support, won't work on old devices (ex. iOS 12)
- `http://192.168.1.123:1984/api/stream.mp4?src=camera1&mp4=all` - MP4 file with non-standard audio codecs, won't work on some players

### Codecs madness

`AVC/H.264` video can be played almost anywhere. But `HEVC/H.265` has many limitations in supporting different devices and browsers.

| Device                                                             | WebRTC                                  | MSE                                     | HTTP*                                        | HLS                         |
|--------------------------------------------------------------------|-----------------------------------------|-----------------------------------------|----------------------------------------------|-----------------------------|
| *latency*                                                          | best                                    | medium                                  | bad                                          | bad                         |
| Desktop Chrome 136+ <br/> Desktop Edge <br/> Android Chrome 136+   | H264, H265* <br/> PCMU, PCMA <br/> OPUS | H264, H265* <br/> AAC, FLAC* <br/> OPUS | H264, H265* <br/> AAC, FLAC* <br/> OPUS, MP3 | no                          |
| Desktop Firefox                                                    | H264 <br/> PCMU, PCMA <br/> OPUS        | H264 <br/> AAC, FLAC* <br/> OPUS        | H264 <br/> AAC, FLAC* <br/> OPUS             | no                          |
| Desktop Safari 14+ <br/> iPad Safari 14+ <br/> iPhone Safari 17.1+ | H264, H265* <br/> PCMU, PCMA <br/> OPUS | H264, H265 <br/> AAC, FLAC*             | **no!**                                      | H264, H265 <br/> AAC, FLAC* |
| iPhone Safari 14+                                                  | H264, H265* <br/> PCMU, PCMA <br/> OPUS | **no!**                                 | **no!**                                      | H264, H265 <br/> AAC, FLAC* |
| macOS [Hass App][1]                                                | no                                      | no                                      | no                                           | H264, H265 <br/> AAC, FLAC* |

[1]: https://apps.apple.com/app/home-assistant/id1099568401

- `HTTP*` - HTTP Progressive Streaming, not related to [progressive download](https://en.wikipedia.org/wiki/Progressive_download), because the file has no size and no end
- `WebRTC H265` - supported in [Chrome 136+](https://developer.chrome.com/release-notes/136), supported in [Safari 18+](https://developer.apple.com/documentation/safari-release-notes/safari-18-release-notes)
- `MSE iPhone` - supported in [iOS 17.1+](https://webkit.org/blog/14735/webkit-features-in-safari-17-1/)

**Audio**

- go2rtc supports [automatic repackaging](#built-in-transcoding) of `PCMA/PCMU/PCM` codecs into `FLAC` for MSE/MP4/HLS so they'll work almost anywhere
- **WebRTC** audio codecs: `PCMU/8000`, `PCMA/8000`, `OPUS/48000/2`
- `OPUS` and `MP3` inside **MP4** are part of the standard, but some players do not support them anyway (especially Apple)

**Apple devices**

- all Apple devices don't support HTTP progressive streaming
- old iPhone firmwares don't support MSE technology because it competes with the HTTP Live Streaming (HLS) technology, invented by Apple
- HLS is the worst technology for **live** streaming, it still exists only because of iPhones

### Built-in transcoding

There are no plans to embed complex transcoding algorithms inside go2rtc. 
[FFmpeg source](internal/ffmpeg/README.md) does a great job with this. 
Including [hardware acceleration](https://github.com/AlexxIT/go2rtc/wiki/Hardware-acceleration) support.

But go2rtc has some simple algorithms. They are turned on automatically; you do not need to set them up additionally.

**PCM for MSE/MP4/HLS**

Go2rtc can pack `PCMA`, `PCMU` and `PCM` codecs into an MP4 container so that they work in all browsers and all built-in players on modern devices. Including Apple QuickTime:

```text
PCMA/PCMU => PCM => FLAC => MSE/MP4/HLS
```

**Resample PCMA/PCMU for WebRTC**

By default WebRTC supports only `PCMA/8000` and `PCMU/8000`. But go2rtc can automatically resample PCMA and PCMU codecs with a different sample rate. Also, go2rtc can transcode `PCM` codec to `PCMA/8000`, so WebRTC can play it:

```text
PCM/xxx => PCMA/8000 => WebRTC
PCMA/xxx => PCMA/8000 => WebRTC
PCMU/xxx => PCMU/8000 => WebRTC
```

**Important**

- FLAC codec not supported in an RTSP stream. If you are using Frigate or Home Assistant for recording MP4 files with PCMA/PCMU/PCM audio, you should set up transcoding to the AAC codec.
- PCMA and PCMU are VERY low-quality codecs. They support only 256! different sounds. Use them only when you have no other options.

### Codecs negotiation

For example, you want to watch an RTSP stream from a [Dahua IPC-K42](https://www.dahuasecurity.com/fr/products/All-Products/Network-Cameras/Wireless-Series/Wi-Fi-Series/4MP/IPC-K42) camera in your Chrome browser.

- this camera supports two-way audio standard **ONVIF Profile T**
- this camera supports codecs **H264, H265** for sending video, and you select `H264` in camera settings
- this camera supports codecs **AAC, PCMU, PCMA** for sending audio (from mic), and you select `AAC/16000` in camera settings
- this camera supports codecs **AAC, PCMU, PCMA** for receiving audio (to speaker), you don't need to select them
- your browser supports codecs **H264, VP8, VP9, AV1** for receiving video, you don't need to select them
- your browser supports codecs **OPUS, PCMU, PCMA** for sending and receiving audio, you don't need to select them
- you can't get the camera audio directly because its audio codecs don't match your browser's codecs
    - so you decide to use transcoding via FFmpeg and add this setting to the config YAML file
    - you have chosen `OPUS/48000/2` codec, because it is higher quality than the `PCMU/8000` or `PCMA/8000`

Now you have a stream with two sources - **RTSP and FFmpeg**:

```yaml
streams:
  dahua:
    - rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    - ffmpeg:rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=0#audio=opus
```

**go2rtc** automatically matches codecs for your browser across all of your stream sources. This is called **multi-source two-way codec negotiation**, and it's one of the main features of this app.

**PS.** You can select `PCMU` or `PCMA` codec in camera settings and not use transcoding at all. Or you can select `AAC` codec for main stream and `PCMU` codec for second stream and add both RTSP to YAML config, this also will work fine.

## Security

> [!IMPORTANT]
> If an attacker gains access to the API, you are in danger. Through the API, an attacker can use insecure sources such as echo and exec. And get full access to your server.

For maximum (paranoid) security, go2rtc has special settings:

```yaml
app:
  # use only allowed modules
  modules: [api, rtsp, webrtc, exec, ffmpeg, mjpeg]

api:
  # use only allowed API paths
  allow_paths: [/api, /api/streams, /api/webrtc, /api/frame.jpeg]
  # enable auth for localhost (used together with username and password)
  local_auth: true

exec:
  # use only allowed exec paths
  allow_paths: [ffmpeg]
```

By default, `go2rtc` starts the Web interface on port `1984` and RTSP on port `8554`, as well as uses port `8555` for WebRTC connections. The three ports are accessible from your local network. So anyone on your local network can watch video from your cameras without authorization. The same rule applies to the Home Assistant add-on.

This is not a problem if you trust your local network as much as I do. But you can change this behaviour with a `go2rtc.yaml` config:

```yaml
api:
  listen: "127.0.0.1:1984" # localhost

rtsp:
  listen: "127.0.0.1:8554" # localhost

webrtc:
  listen: ":8555" # external TCP/UDP port
```

- local access to RTSP is not a problem for [FFmpeg](internal/ffmpeg/README.md) integration, because it runs locally on your server
- local access to API is not a problem for the [Home Assistant add-on](#go2rtc-home-assistant-add-on), because Home Assistant runs locally on the same server, and the add-on web UI is protected with Home Assistant authorization ([Ingress feature](https://www.home-assistant.io/blog/2019/04/15/hassio-ingress/))
- external access to WebRTC TCP port is not a problem, because it is used only for transmitting encrypted media data
    - anyway you need to open this port to your local network and to the Internet for WebRTC to work

If you need web interface protection without the Home Assistant add-on, you need to use a reverse proxy, like [Nginx](https://nginx.org/), [Caddy](https://caddyserver.com/), etc.

PS. Additionally, WebRTC will try to use the 8555 UDP port to transmit encrypted media. It works without problems on the local network, and sometimes also works for external access, even if you haven't opened this port on your router ([read more](https://en.wikipedia.org/wiki/UDP_hole_punching)). But for stable external WebRTC access, you need to open the 8555 port on your router for both TCP and UDP.

## Projects using go2rtc

- [Home Assistant](https://www.home-assistant.io/) [2024.11+](https://www.home-assistant.io/integrations/go2rtc/) - top open-source smart home project
- [Frigate](https://frigate.video/) [0.12+](https://docs.frigate.video/guides/configuring_go2rtc/) - open-source NVR built around real-time AI object detection
- [camera.ui](https://www.cameraui.com/) - The modern, local-first platform for professional video surveillance.
- [Advanced Camera Card](https://github.com/dermotduffy/advanced-camera-card) - custom card for Home Assistant
- [OpenIPC](https://github.com/OpenIPC/firmware/tree/master/general/package/go2rtc) - alternative IP camera firmware from an open community
- [wz_mini_hacks](https://github.com/gtxaspec/wz_mini_hacks) - custom firmware for Wyze cameras
- [EufyP2PStream](https://github.com/oischinger/eufyp2pstream) - a small project that provides a video/audio stream from Eufy cameras that don't directly support RTSP
- [ioBroker.euSec](https://github.com/bropat/ioBroker.eusec) - [ioBroker](https://www.iobroker.net/) adapter for controlling Eufy security devices
- [MMM-go2rtc](https://github.com/Anonym-tsk/MMM-go2rtc) - MagicMirror² module
- [ring-mqtt](https://github.com/tsightler/ring-mqtt) - Ring-to-MQTT bridge
- [lightNVR](https://github.com/opensensor/lightNVR)

**Distributions**

- [Alpine Linux](https://pkgs.alpinelinux.org/packages?name=go2rtc)
- [Arch User Repository](https://linux-packages.com/aur/package/go2rtc)
- [Gentoo](https://github.com/inode64/inode64-overlay/tree/main/media-video/go2rtc)
- [NixOS](https://search.nixos.org/packages?query=go2rtc)
- [Proxmox Helper Scripts](https://github.com/community-scripts/ProxmoxVE/)
- [QNAP](https://www.myqnap.org/product/go2rtc/)
- [Synology NAS](https://synocommunity.com/package/go2rtc)
- [Unraid](https://unraid.net/community/apps?q=go2rtc)

## Camera experience

- [Dahua](https://www.dahuasecurity.com/) - reference implementation streaming protocols, a lot of settings, high stream quality, multiple streaming clients
- [EZVIZ](https://www.ezviz.com/) - awful RTSP protocol implementation, many bugs in SDP
- [Hikvision](https://www.hikvision.com/) - a lot of proprietary streaming technologies
- [Reolink](https://reolink.com/) - some models have an awful, unusable RTSP implementation and not the best RTMP alternative (I recommend that you contact Reolink support for new firmware), few settings
- [Sonoff](https://sonoff.tech/) - very low stream quality, no settings, not the best protocol implementation
- [TP-Link](https://www.tp-link.com/) - few streaming clients, packet loss?
- Cheap noname cameras, Wyze Cams, Xiaomi cameras with hacks (usually have `/live/ch00_1` in RTSP URL) - awful but usable RTSP protocol implementation, low stream quality, few settings, packet loss?

## Tips

**Using apps for low RTSP delay**

- `ffplay -fflags nobuffer -flags low_delay "rtsp://192.168.1.123:8554/camera1"`
- VLC > Preferences > Input / Codecs > Default Caching Level: Lowest Latency

**Snapshots to Telegram**

[read more](https://github.com/AlexxIT/go2rtc/wiki/Snapshot-to-Telegram)

---

### Overview (`docker/README.md`)

# Docker

Images are built automatically via [GitHub actions](https://github.com/AlexxIT/go2rtc/actions) and published on [Docker Hub](https://hub.docker.com/r/alexxit/go2rtc) and [GitHub](https://github.com/AlexxIT/go2rtc/pkgs/container/go2rtc).

## Versions

- `alexxit/go2rtc:latest` - latest release based on `alpine` (`amd64`, `386`, `arm/v6`, `arm/v7`, `arm64`) with support for hardware transcoding for Intel iGPU and Raspberry
- `alexxit/go2rtc:latest-hardware` - latest release based on `debian 13` (`amd64`) with support for hardware transcoding for Intel iGPU, AMD GPU and NVidia GPU
- `alexxit/go2rtc:latest-rockchip` - latest release based on `debian 12` (`arm64`) with support for hardware transcoding for Rockchip RK35xx
- `alexxit/go2rtc:master` - latest unstable version based on `alpine`
- `alexxit/go2rtc:master-hardware` - latest unstable version based on `debian 13` (`amd64`)
- `alexxit/go2rtc:master-rockchip` - latest unstable version based on `debian 12` (`arm64`)

## Docker compose

```yaml
services:
  go2rtc:
    image: alexxit/go2rtc
    network_mode: host       # important for WebRTC, HomeKit, UDP cameras
    privileged: true         # only for FFmpeg hardware transcoding
    restart: unless-stopped  # autorestart on fail or config change from WebUI
    environment:
      - TZ=Atlantic/Bermuda  # timezone in logs
    volumes:
      - "~/go2rtc:/config"   # folder for go2rtc.yaml file (edit from WebUI)
```

## Basic Deployment

```bash
docker run -d \
  --name go2rtc \
  --network host \
  --privileged \
  --restart unless-stopped \
  -e TZ=Atlantic/Bermuda \
  -v ~/go2rtc:/config \
  alexxit/go2rtc
```

## Deployment with GPU Acceleration

```bash
docker run -d \
  --name go2rtc \
  --network host \
  --privileged \
  --restart unless-stopped \
  -e TZ=Atlantic/Bermuda \
  --gpus all \
  -v ~/go2rtc:/config \
  alexxit/go2rtc:latest-hardware
```

---

### Overview (`internal/README.md`)

# Modules

go2rtc tries to name formats, protocols and codecs the same way they are named in FFmpeg.
Some formats and protocols go2rtc supports exclusively. They have no equivalent in FFmpeg.

- The [`echo`], [`expr`], [`hass`] and [`onvif`] modules receive a link to a stream. They don't know the protocol in advance.
- The [`exec`] and [`ffmpeg`] modules support many formats. They are identical to the [`http`] module.
- The [`api`], [`app`], [`debug`], [`ngrok`], [`pinggy`], [`srtp`], [`streams`] are supporting modules.

**Modules** implement communication APIs: authorization, encryption, command set, structure of media packets.

**Formats** describe the structure of the data being transmitted.

**Protocols** implement transport for data transmission.

| module         | formats         | protocols        | input | output | ingest | two-way |
|----------------|-----------------|------------------|-------|--------|--------|---------|
| [`alsa`]       | `pcm`           | `ioctl`          | yes   |        |        |         |
| [`bubble`]     | -               | `http`           | yes   |        |        |         |
| [`doorbird`]   | `mulaw`         | `http`           | yes   |        |        | yes     |
| [`dvrip`]      | -               | `tcp`            | yes   |        |        | yes     |
| [`echo`]       | *               | *                | yes   |        |        |         |
| [`eseecloud`]  | `rtp`           | `http`           | yes   |        |        |         |
| [`exec`]       | *               | `pipe`, `rtsp`   | yes   |        |        | yes     |
| [`expr`]       | *               | *                | yes   |        |        |         |
| [`ffmpeg`]     | *               | `pipe`, `rtsp`   | yes   |        |        |         |
| [`flussonic`]  | `mp4`           | `ws`             | yes   |        |        |         |
| [`gopro`]      | `mpegts`        | `udp`            | yes   |        |        |         |
| [`hass`]       | *               | *                | yes   |        |        |         |
| [`hls`]        | `mpegts`, `mp4` | `http`           |       | yes    |        |         |
| [`homekit`]    | `srtp`          | `hap`            | yes   | yes    |        | no      |
| [`http`]       | `adts`          | `http`, `tcp`    | yes   |        |        |         |
| [`http`]       | `flv`           | `http`, `tcp`    | yes   |        |        |         |
| [`http`]       | `h264`          | `http`, `tcp`    | yes   |        |        |         |
| [`http`]       | `hevc`          | `http`, `tcp`    | yes   |        |        |         |
| [`http`]       | `hls`           | `http`, `tcp`    | yes   |        |        |         |
| [`http`]       | `mjpeg`         | `http`, `tcp`    | yes   |        |        |         |
| [`http`]       | `mpjpeg`        | `http`           | yes   |        |        |         |
| [`http`]       | `mpegts`        | `http`, `tcp`    | yes   |        |        |         |
| [`http`]       | `wav`           | `http`, `tcp`    | yes   |        |        |         |
| [`http`]       | `yuv4mpegpipe`  | `http`, `tcp`    | yes   |        |        |         |
| [`isapi`]      | `alaw`, `mulaw` | `http`           |       |        |        | yes     |
| [`ivideon`]    | `mp4`           | `ws`             | yes   |        |        |         |
| [`kasa`]       | `h264`, `mulaw` | `http`           | yes   |        |        |         |
| [`mjpeg`]      | `ascii`         | `http`           |       | yes    |        |         |
| [`mjpeg`]      | `jpeg`          | `http`           |       | yes    |        |         |
| [`mjpeg`]      | `mpjpeg`        | `http`           |       | yes    | yes    |         |
| [`mjpeg`]      | `yuv4mpegpipe`  | `http`           |       | yes    |        |         |
| [`mp4`]        | `mp4`           | `http`, `ws`     |       | yes    |        |         |
| [`mpeg`]       | `adts`          | `http`           |       | yes    |        |         |
| [`mpeg`]       | `mpegts`        | `http`           |       | yes    | yes    |         |
| [`multitrans`] | `rtp`           | `tcp`            |       |        |        | yes     |
| [`nest`]       | `srtp`          | `rtsp`, `webrtc` | yes   |        |        | no      |
| [`onvif`]      | `rtp`           | *                | yes   | yes    |        |         |
| [`ring`]       | `srtp`          | `webrtc`         | yes   |        |        | yes     |
| [`roborock`]   | `srtp`          | `webrtc`         | yes   |        |        | yes     |
| [`rtmp`]       | `flv`           | `rtmp`           | yes   | yes    | yes    |         |
| [`rtmp`]       | `flv`           | `http`           |       | yes    | yes    |         |
| [`rtsp`]       | `rtsp`          | `rtsp`           | yes   | yes    | yes    | yes     |
| [`tapo`]       | `mpegts`        | `http`           | yes   |        |        | yes     |
| [`tuya`]       | `srtp`          | `webrtc`         | yes   |        |        | yes     |
| [`v4l2`]       | `rawvideo`      | `ioctl`          | yes   |        |        |         |
| [`webrtc`]     | `srtp`          | `webrtc`         | yes   | yes    | yes    | yes     |
| [`webtorrent`] | `srtp`          | `webrtc`         | yes   | yes    |        |         |
| [`wyoming`]    | `pcm`           | `tcp`            |       | yes    |        |         |
| [`wyze`]       | -               | `tutk`           | yes   |        |        | yes     |
| [`xiaomi`]     | -               | `cs2`, `tutk`    | yes   |        |        | yes     |
| [`yandex`]     | `srtp`          | `webrtc`         | yes   |        |        |         |

[`alsa`]: alsa/README.md
[`api`]: api/README.md
[`app`]: app/README.md
[`bubble`]: bubble/README.md
[`debug`]: debug/README.md
[`doorbird`]: doorbird/README.md
[`dvrip`]: dvrip/README.md
[`echo`]: echo/README.md
[`eseecloud`]: eseecloud/README.md
[`exec`]: exec/README.md
[`expr`]: expr/README.md
[`ffmpeg`]: ffmpeg/README.md
[`flussonic`]: flussonic/README.md
[`gopro`]: gopro/README.md
[`hass`]: hass/README.md
[`hls`]: hls/README.md
[`homekit`]: homekit/README.md
[`http`]: http/README.md
[`isapi`]: isapi/README.md
[`ivideon`]: ivideon/README.md
[`kasa`]: kasa/README.md
[`mjpeg`]: mjpeg/README.md
[`mp4`]: mp4/README.md
[`mpeg`]: mpeg/README.md
[`multitrans`]: multitrans/README.md
[`nest`]: nest/README.md
[`ngrok`]: ngrok/README.md
[`onvif`]: onvif/README.md
[`pinggy`]: pinggy/README.md
[`ring`]: ring/README.md
[`roborock`]: roborock/README.md
[`rtmp`]: rtmp/README.md
[`rtsp`]: rtsp/README.md
[`srtp`]: srtp/README.md
[`streams`]: streams/README.md
[`tapo`]: tapo/README.md
[`tuya`]: tuya/README.md
[`v4l2`]: v4l2/README.md
[`webrtc`]: webrtc/README.md
[`webtorrent`]: webtorrent/README.md
[`wyoming`]: wyze/README.md
[`wyze`]: wyze/README.md
[`xiaomi`]: xiaomi/README.md
[`yandex`]: yandex/README.md

---

### Overview (`pkg/README.md`)

# Notes

go2rtc tries to name formats, protocols and codecs the same way they are named in FFmpeg.
Some formats and protocols go2rtc supports exclusively. They have no equivalent in FFmpeg.

## Producers (input)

- The initiator of the connection can be go2rtc - **Source protocols**
- The initiator of the connection can be an external program - **Ingress protocols**
- Codecs can be incoming - **Receiver codecs**
- Codecs can be outgoing (two way audio) - **Sender codecs**

| Group      | Format       | Protocols       | Ingress | Receiver codecs                 | Sender codecs      | Example       |
|------------|--------------|-----------------|---------|---------------------------------|---------------------|---------------|
| Devices    | alsa         | pipe            |         |                                 | pcm                 | `alsa:`       |
| Devices    | v4l2         | pipe            |         |                                 |                     | `v4l2:`       |
| Files      | adts         | http, tcp, pipe | http    | aac                             |                     | `http:`       |
| Files      | flv          | http, tcp, pipe | http    | h264, aac                       |                     | `http:`       |
| Files      | h264         | http, tcp, pipe | http    | h264                            |                     | `http:`       |
| Files      | hevc         | http, tcp, pipe | http    | hevc                            |                     | `http:`       |
| Files      | hls          | http            |         | h264, h265, aac, opus           |                     | `http:`       |
| Files      | mjpeg        | http, tcp, pipe | http    | mjpeg                           |                     | `http:`       |
| Files      | mpegts       | http, tcp, pipe | http    | h264, hevc, aac, opus           |                     | `http:`       |
| Files      | wav          | http, tcp, pipe | http    | pcm_alaw, pcm_mulaw             |                     | `http:`       |
| Net (pub)  | mpjpeg       | http, tcp, pipe | http    | mjpeg                           |                     | `http:`       |
| Net (pub)  | onvif        | rtsp            |         |                                 |                     | `onvif:`      |
| Net (pub)  | rtmp         | rtmp            | rtmp    | h264, aac                       |                     | `rtmp:`       |
| Net (pub)  | rtsp         | rtsp, ws        | rtsp    | h264, hevc, aac, pcm*, opus     | pcm*, opus          | `rtsp:`       |
| Net (pub)  | webrtc*      | webrtc          | webrtc  | h264, pcm_alaw, pcm_mulaw, opus | pcm_alaw, pcm_mulaw | `webrtc:`     |
| Net (pub)  | yuv4mpegpipe | http, tcp, pipe | http    | rawvideo                        |                     | `http:`       |
| Net (priv) | bubble       | http            |         | h264, hevc, pcm_alaw            |                     | `bubble:`     |
| Net (priv) | doorbird     | http            |         |                                 |                     | `doorbird:`   |
| Net (priv) | dvrip        | tcp             |         | h264, hevc, pcm_alaw, pcm_mulaw | pcm_alaw            | `dvrip:`      |
| Net (priv) | eseecloud    | http            |         |                                 |                     | `eseecloud:`  |
| Net (priv) | gopro        | udp             |         | TODO                            |                     | `gopro:`      |
| Net (priv) | hass         | webrtc          |         | TODO                            |                     | `hass:`       |
| Net (priv) | homekit      | hap             |         | h264, eld*                      |                     | `homekit:`    |
| Net (priv) | isapi        | http            |         |                                 | pcm_alaw, pcm_mulaw | `isapi:`      |
| Net (priv) | kasa         | http            |         | h264, pcm_mulaw                 |                     | `kasa:`       |
| Net (priv) | nest         | rtsp, webrtc    |         | TODO                            |                     | `nest:`       |
| Net (priv) | ring         | webrtc          |         |                                 |                     | `ring:`       |
| Net (priv) | roborock     | webrtc          |         | h264, opus                      | opus                | `roborock:`   |
| Net (priv) | tapo         | http            |         | h264, pcma                      | pcm_alaw            | `tapo:`       |
| Net (priv) | tuya         | webrtc          |         |                                 |                     | `tuya:`       |
| Net (priv) | vigi         | http            |         |                                 |                     | `vigi:`       |
| Net (priv) | webtorrent   | webrtc          | TODO    | TODO                            | TODO                | `webtorrent:` |
| Net (priv) | xiaomi*      | cs2, tutk       |         |                                 |                     | `xiaomi:`     |
| Services   | flussonic    | ws              |         |                                 |                     | `flussonic:`  |
| Services   | ivideon      | ws              |         | h264                            |                     | `ivideon:`    |
| Services   | yandex       | webrtc          |         |                                 |                     | `yandex:`     |
| Other      | echo         | *               |         |                                 |                     | `echo:`       |
| Other      | exec         | pipe, rtsp      |         |                                 |                     | `exec:`       |
| Other      | expr         | *               |         |                                 |                     | `expr:`       |
| Other      | ffmpeg       | pipe, rtsp      |         |                                 |                     | `ffmpeg:`     |
| Other      | stdin        | pipe            |         |                                 | pcm_alaw, pcm_mulaw | `stdin:`      |

- **eld** - rare variant of aac codec
- **pcm** - pcm_alaw pcm_mulaw pcm_s16be pcm_s16le
- **webrtc** - webrtc/kinesis, webrtc/openipc, webrtc/milestone, webrtc/wyze, webrtc/whep

## Consumers (output)

| Format       | Protocol | Send codecs                     | Recv codecs               | Example                               |
|--------------|----------|---------------------------------|---------------------------|---------------------------------------|
| adts         | http     | aac                             |                           | `GET /api/stream.adts`                |
| ascii        | http     | mjpeg                           |                           | `GET /api/stream.ascii`               |
| flv          | http     | h264, aac                       |                           | `GET /api/stream.flv`                 |
| hls/mpegts   | http     | h264, hevc, aac                 |                           | `GET /api/stream.m3u8`                |
| hls/fmp4     | http     | h264, hevc, aac, pcm*, opus     |                           | `GET /api/stream.m3u8?mp4`            |
| homekit      | hap      | h264, opus                      |                           | Apple HomeKit app                     |
| mjpeg        | ws       | mjpeg                           |                           | `{"type":"mjpeg"}` -> `/api/ws`       |
| mpjpeg       | http     | mjpeg                           |                           | `GET /api/stream.mjpeg`               |
| mp4          | http     | h264, hevc, aac, pcm*, opus     |                           | `GET /api/stream.mp4`                 |
| mse/fmp4     | ws       | h264, hevc, aac, pcm*, opus     |                           | `{"type":"mse"}` -> `/api/ws`         |
| mpegts       | http     | h264, hevc, aac                 |                           | `GET /api/stream.ts`                  |
| rtmp         | rtmp     | h264, aac                       |                           | `rtmp://localhost:1935/{stream_name}` |
| rtsp         | rtsp     | h264, hevc, aac, pcm*, opus     |                           | `rtsp://localhost:8554/{stream_name}` |
| webrtc       | webrtc   | h264, pcm_alaw, pcm_mulaw, opus | pcm_alaw, pcm_mulaw, opus | `{"type":"webrtc"}` -> `/api/ws`      |
| yuv4mpegpipe | http     | rawvideo                        |                           | `GET /api/stream.y4m`                 |

- **pcm** - pcm_alaw pcm_mulaw pcm_s16be pcm_s16le

## Snapshots

| Format | Protocol | Send codecs | Example               |
|--------|----------|-------------|-----------------------|
| jpeg   | http     | mjpeg       | `GET /api/frame.jpeg` |
| mp4    | http     | h264,hevc   | `GET /api/frame.mp4`  |

## Developers

**File naming:**

- `pkg/{format}/producer.go` - producer for this format (also if support backchannel)
- `pkg/{format}/consumer.go` - consumer for this format
- `pkg/{format}/backchannel.go` - producer with only backchannel func

**Mentioning modules:**

- [`main.go`](../main.go)
- [`README.md`](../README.md)
- [`internal/README.md`](../internal/README.md)
- [`website/.vitepress/config.js`](../website/.vitepress/config.js)
- [`website/api/openapi.yaml`](../website/api/openapi.yaml)
- [`www/schema.json`](../www/schema.json)

## Useful links

- https://www.wowza.com/blog/streaming-protocols
- https://vimeo.com/blog/post/rtmp-stream/
- https://sanjeev-pandey.medium.com/understanding-the-mpeg-4-moov-atom-pseudo-streaming-in-mp4-93935e1b9e9a
- [Android Supported media formats](https://developer.android.com/guide/topics/media/media-formats)
- [THEOplayer](https://www.theoplayer.com/test-your-stream-hls-dash-hesp)
- [How Generate DTS/PTS](https://www.ramugedia.com/how-generate-dts-pts-from-elementary-stream)

---

### Overview (`scripts/README.md`)

# Scripts

This folder contains a script for building binaries for all platforms.

The project has no `CGO` dependencies, so building is as simple as possible using the `go build` command.

The project has to use the latest versions of go due to dependencies on third-party go libraries. Such as `pion/webrtc` or `golang.org/x`. Unfortunately, this breaks compatibility with older versions of operating systems.

The project uses [UPX](https://github.com/upx/upx) to compress binaries for Linux. The project does not use compression for Windows due to false antivirus alarms. The project does not use compression for macOS due to broken result.

## Useful commands

```
go get -u
go mod tidy
go mod why github.com/pion/rtcp
go list -deps .\cmd\go2rtc_rtsp\
./goweight
```

## Dependencies

```
- gopkg.in/yaml.v3
  - github.com/kr/pretty
- github.com/AlexxIT/go2rtc/pkg/hap
  - github.com/tadglines/go-pkgs
  - golang.org/x/crypto
- github.com/AlexxIT/go2rtc/pkg/mdns
  - github.com/miekg/dns
- github.com/AlexxIT/go2rtc/pkg/pcm
  - github.com/sigurn/crc16
  - github.com/sigurn/crc8
- github.com/pion/ice/v2
  - github.com/google/uuid
  - github.com/wlynxg/anet
- github.com/rs/zerolog
  - github.com/mattn/go-colorable
  - github.com/mattn/go-isatty
- github.com/stretchr/testify
  - github.com/davecgh/go-spew
  - github.com/pmezard/go-difflib
- ???
  - golang.org/x/mod
  - golang.org/x/net
  - golang.org/x/sys
  - golang.org/x/tools
```

## Licenses

- github.com/asticode/go-astits - MIT
- github.com/eclipse/paho.mqtt.golang - EPL-2.0
- github.com/expr-lang/expr - MIT
- github.com/gorilla/websocket - BSD-2
- github.com/mattn/go-isatty - MIT
- github.com/miekg/dns - BSD-3
- github.com/pion/dtls - MIT
- github.com/pion/ice - MIT
- github.com/pion/interceptor - MIT
- github.com/pion/rtcp - MIT
- github.com/pion/rtp - MIT
- github.com/pion/sdp - MIT
- github.com/pion/srtp - MIT
- github.com/pion/stun - MIT
- github.com/pion/webrtc - MIT
- github.com/rs/zerolog - MIT
- github.com/sigurn/crc16 - MIT
- github.com/sigurn/crc8 - MIT
- github.com/stretchr/testify - MIT
- github.com/tadglines/go-pkgs - Apache
- golang.org/x/crypto - BSD-3
- gopkg.in/yaml.v3 - MIT and Apache
- github.com/asticode/go-astikit - MIT
- github.com/davecgh/go-spew - ISC (BSD/MIT like)
- github.com/google/uuid - BSD-3
- github.com/kr/pretty - MIT
- github.com/mattn/go-colorable - MIT
- github.com/pion/datachannel - MIT
- github.com/pion/logging - MIT
- github.com/pion/mdns - MIT
- github.com/pion/randutil - MIT
- github.com/pion/sctp - MIT
- github.com/pmezard/go-difflib - ???
- github.com/wlynxg/anet - BSD-3
- golang.org/x/mod - BSD-3
- golang.org/x/net - BSD-3
- golang.org/x/sync - BSD-3
- golang.org/x/sys - BSD-3
- golang.org/x/tools - BSD-3

## Virus

- https://go.dev/doc/faq#virus
- https://groups.google.com/g/golang-nuts/c/lPwiWYaApSU

## Useful links

- https://github.com/golang-standards/project-layout
- https://github.com/micro/micro
- https://github.com/golang/go/wiki/GoArm
- https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63
- https://en.wikipedia.org/wiki/AArch64
- https://stackoverflow.com/questions/22267189/what-does-the-w-flag-mean-when-passed-in-via-the-ldflags-option-to-the-go-comman

---

### Overview (`website/README.md`)

# WebSite

These are the sources of the [go2rtc.org](https://go2rtc.org/) website. It's content published on GitHub Pages and is a mirror of [alexxit.github.io/go2rtc/](http://alexxit.github.io/go2rtc/).

The site contains:

- Project's documentation, which is compiled via [vitepress](https://github.com/vuejs/vitepress) from `README.md` files located in the root of the repository, as well as in the `internal` folder.
- Project's API in OpenAPI format, and the [Redoc](https://github.com/Redocly/redoc) viewer
- Project's assets (logo).

---

### Overview (`www/README.md`)

# www

This folder contains static HTTP and JS content that is embedded into the application during build. An external developer can use it as a basis for integrating go2rtc into their project or for developing a custom web interface for go2rtc.

## HTTP API

`www/stream.html` - universal viewer with support params in URL:

- multiple streams on page `src=camera1&src=camera2...`
- stream technology autoselection `mode=webrtc,webrtc/tcp,mse,hls,mp4,mjpeg`
- stream technology comparison `src=camera1&mode=webrtc&mode=mse&mode=mp4`
- player width setting in pixels `width=320px` or percents `width=50%`

`www/webrtc.html` - WebRTC viewer with support two way audio and params in URL:

- `media=video+audio` - simple viewer
- `media=video+audio+microphone` - two way audio from camera
- `media=camera+microphone` - stream from browser
- `media=display+speaker` - stream from desktop

## JavaScript API

- You can write your viewer from the scratch
- You can extend the built-in viewer - `www/video-rtc.js`
- Check example - `www/video-stream.js`
- Check example - https://github.com/AlexxIT/WebRTC

`video-rtc.js` features:

- support technologies:
    - WebRTC over UDP or TCP
    - MSE or HLS or MP4 or MJPEG over WebSocket
- automatic selection best technology according on:
    - codecs inside your stream
    - current browser capabilities
    - current network configuration
- automatic stop stream while browser or page not active
- automatic stop stream while player not inside page viewport
- automatic reconnection

Technology selection based on priorities:

1. Video and Audio better than just Video
2. H265 better than H264
3. WebRTC better than MSE, than HLS, than MJPEG

## Browser support

[ECMAScript 2019 (ES10)](https://caniuse.com/?search=es10) supported by [iOS 12](https://en.wikipedia.org/wiki/IOS_12) (iPhone 5S, iPad Air, iPad Mini 2, etc.).

But [ECMAScript 2017 (ES8)](https://caniuse.com/?search=es8) almost fine (`es6 + async`) and recommended for [React+TypeScript](https://github.com/typescript-cheatsheets/react).

## Known problems

- Autoplay doesn't work for WebRTC in Safari [read more](https://developer.apple.com/documentation/webkit/delivering_video_content_for_safari/).

## Useful links

- https://www.webrtc-experiment.com/DetectRTC/
- https://divtable.com/table-styler/
- https://www.chromium.org/audio-video/
- https://web.dev/i18n/en/fast-playback-with-preload/#manual_buffering
- https://developer.mozilla.org/en-US/docs/Web/API/Media_Source_Extensions_API
- https://chromium.googlesource.com/external/w3c/web-platform-tests/+/refs/heads/master/media-source/mediasource-is-type-supported.html
- https://googlechrome.github.io/samples/media/sourcebuffer-changetype.html
- https://chromestatus.com/feature/5100845653819392
- https://developer.apple.com/documentation/webkit/delivering_video_content_for_safari
- https://dirask.com/posts/JavaScript-supported-Audio-Video-MIME-Types-by-MediaRecorder-Chrome-and-Firefox-jERn81
- https://privacycheck.sec.lrz.de/active/fp_cpt/fp_can_play_type.html

---

### Overview (`examples/onvif_client/README.md`)

## ONVIF Client

```shell
go run examples/onvif_client/main.go http://admin:password@192.168.10.90 GetAudioEncoderConfigurations
```

---

### Overview (`examples/tutk_decoder/README.md`)

# tutk_decoder

1. Wireshark > Select any packet > Follow > UDP Stream
2. Wireshark > File > Export Packet Dissections > As JSON > Displayed, Values
3. `tutk_decoder wireshark.json decoded.txt`

---

### Overview (`internal/alsa/README.md`)

# ALSA

[`new in v1.9.10`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.9.10)

> [!WARNING]
> This source is under development and does not always work well.

[Advanced Linux Sound Architecture](https://en.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture) - a framework for receiving audio from devices on Linux OS.

Easy to add via **WebUI > add > ALSA**.

Alternatively, you can use FFmpeg source.

---

### Overview (`internal/api/README.md`)

# HTTP API

The HTTP API is the main part for interacting with the application. Default address: `http://localhost:1984/`.

The HTTP API is described in [OpenAPI](../../website/api/openapi.yaml) format. It can be explored in [interactive viewer](https://go2rtc.org/api/). WebSocket API described [here](ws/README.md).

The project's static HTML and JS files are located in the [www](../../www/README.md) folder. An external developer can use them as a basis for integrating go2rtc into their project or for developing a custom web interface for go2rtc.

The contents of `www` folder are built into go2rtc when building, but you can use configuration to specify an external folder as the source of static files.

## Configuration

**Important!** go2rtc passes requests from localhost and Unix sockets without HTTP authorization, even if you have it configured. It is your responsibility to set up secure external access to the API. If not properly configured, an attacker can gain access to your cameras and even your server.

- you can disable HTTP API with `listen: ""` and use, for example, only RTSP client/server protocol
- you can enable HTTP API only on localhost with `listen: "127.0.0.1:1984"` setting
- you can change the API `base_path` and host go2rtc on your main app webserver suburl
- all files from `static_dir` hosted on root path: `/`
- you can use raw TLS cert/key content or path to files

```yaml
api:
  listen: ":1984"    # default ":1984", HTTP API port ("" - disabled)
  username: "admin"  # default "", Basic auth for WebUI
  password: "pass"   # default "", Basic auth for WebUI
  local_auth: true   # default false, Enable auth check for localhost requests
  base_path: "/rtc"  # default "", API prefix for serving on suburl (/api => /rtc/api)
  static_dir: "www"  # default "", folder for static files (custom web interface)
  origin: "*"        # default "", allow CORS requests (only * supported)
  tls_listen: ":443" # default "", enable HTTPS server
  tls_cert: |        # default "", PEM-encoded fullchain certificate for HTTPS
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
  tls_key: |         # default "", PEM-encoded private key for HTTPS
    -----BEGIN PRIVATE KEY-----
    ...
    -----END PRIVATE KEY-----
  unix_listen: "/tmp/go2rtc.sock"  # default "", unix socket listener for API
```

**PS:**

- MJPEG over WebSocket plays better than native MJPEG because Chrome [bug](https://bugs.chromium.org/p/chromium/issues/detail?id=527446)
- MP4 over WebSocket was created only for Apple iOS because it doesn't support file streaming

---

### Overview (`internal/app/README.md`)

# App

The application module is responsible for reading configuration files, running other modules and setting up [logs](#log).

The configuration can be edited through the application's WebUI with code highlighting, syntax and specification checking.

- By default, go2rtc will search for the `go2rtc.yaml` config file in the current working directory
- go2rtc supports multiple config files:
  - `go2rtc -c config1.yaml -c config2.yaml -c config3.yaml`
- go2rtc supports inline config in multiple formats from the command line:
  - **YAML**: `go2rtc -c '{log: {format: text}}'`
  - **JSON**: `go2rtc -c '{"log":{"format":"text"}}'`
  - **key=value**: `go2rtc -c log.format=text`
- Each subsequent config will overwrite the previous one (but only for defined params)

```
go2rtc -config "{log: {format: text}}" -config /config/go2rtc.yaml -config "{rtsp: {listen: ''}}" -config /usr/local/go2rtc/go2rtc.yaml
```

or a simpler version

```
go2rtc -c log.format=text -c /config/go2rtc.yaml -c rtsp.listen='' -c /usr/local/go2rtc/go2rtc.yaml
```

## Environment variables

There is support for loading external variables into the config. First, they will be loaded from [credential files](https://systemd.io/CREDENTIALS). If `CREDENTIALS_DIRECTORY` is not set, then the key will be loaded from an environment variable. If no environment variable is set, then the string will be left as-is.

```yaml
streams:
  camera1: rtsp://rtsp:${CAMERA_PASSWORD}@192.168.1.123/av_stream/ch0

rtsp:
  username: ${RTSP_USER:admin}   # "admin" if "RTSP_USER" not set
  password: ${RTSP_PASS:secret}  # "secret" if "RTSP_PASS" not set
```

## JSON Schema

Editors like [GoLand](https://www.jetbrains.com/go/) and [VS Code](https://code.visualstudio.com/) support autocomplete and syntax validation.

```yaml
# yaml-language-server: $schema=https://raw.githubusercontent.com/AlexxIT/go2rtc/master/www/schema.json
```

or from a running go2rtc:

```yaml
# yaml-language-server: $schema=http://localhost:1984/schema.json
```

## Defaults

- Default values may change in updates
- FFmpeg module has many presets, they are not listed here because they may also change in updates

```yaml
api:
  listen: ":1984"  # default public port for WebUI and HTTP API

ffmpeg:
  bin: "ffmpeg"    # default binary path for FFmpeg

log:
  level: "info"    # default log level
  output: "stdout"
  time: "UNIXMS"

rtsp:
  listen: ":8554"  # default public port for RTSP server
  default_query: "video&audio"

srtp:
  listen: ":8443"  # default public port for SRTP server (used for HomeKit)

webrtc:
  listen: ":8555"  # default public port for WebRTC server (TCP and UDP)
  ice_servers:
    - urls: [ "stun:stun.cloudflare.com:3478", "stun:stun.l.google.com:19302" ]
```

## Log

You can set different log levels for different modules.

```yaml
log:
  format: ""        # empty (default, autodetect color support), color, json, text 
  level: "info"     # disabled, trace, debug, info (default), warn, error
  output: "stdout"  # empty (only to memory), stderr, stdout (default)
  time: "UNIXMS"    # empty (disable timestamp), UNIXMS (default), UNIXMICRO, UNIXNANO
  
  api: trace   # module name: log level
```

Modules: `api`, `streams`, `rtsp`, `webrtc`, `mp4`, `hls`, `mjpeg`, `hass`, `homekit`, `onvif`, `rtmp`, `webtorrent`, `wyoming`, `echo`, `exec`, `expr`, `ffmpeg`, `wyze`, `xiaomi`.

---

### Overview (`internal/bubble/README.md`)

# Bubble

[`new in v1.6.1`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.1)

Private format in some cameras from [dvr163.com](http://help.dvr163.com/) and [eseecloud.com](http://www.eseecloud.com/).

## Configuration

- you can skip `username`, `password`, `port`, `ch` and `stream` if they are default
- set up separate streams for different channels and streams

```yaml
streams:
  camera1: bubble://username:password@192.168.1.123:34567/bubble/live?ch=0&stream=0
```

---

### Overview (`internal/debug/README.md`)

# Debug

This module provides `GET /api/stack`, with which you can find hanging goroutines

---

### Overview (`internal/doorbird/README.md`)

# Doorbird

[`new in v1.9.8`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.9.8)

This source type supports [Doorbird](https://www.doorbird.com/) devices including MJPEG stream, audio stream as well as two-way audio.

It is recommended to create a separate user within your doorbird setup for go2rtc. Minimum permissions for the user are:

- Watch always
- API operator

## Configuration

```yaml
streams:
  doorbird1:
    - rtsp://admin:password@192.168.1.123:8557/mpeg/720p/media.amp  # RTSP stream
    - doorbird://admin:password@192.168.1.123?media=video           # MJPEG stream
    - doorbird://admin:password@192.168.1.123?media=audio           # audio stream
    - doorbird://admin:password@192.168.1.123                       # two-way audio
```

---

### Overview (`internal/dvrip/README.md`)

# DVR-IP

[`new in v1.2.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.2.0)

Private format from DVR-IP NVR, NetSurveillance, Sofia protocol (NETsurveillance ActiveX plugin XMeye SDK).

## Configuration

- you can skip `username`, `password`, `port`, `channel` and `subtype` if they are default
- set up separate streams for different channels
- use `subtype=0` for Main stream, and `subtype=1` for Extra1 stream
- only the TCP protocol is supported

```yaml
streams:
  only_stream: dvrip://username:password@192.168.1.123:34567?channel=0&subtype=0
  only_tts: dvrip://username:password@192.168.1.123:34567?backchannel=1
  two_way_audio:
    - dvrip://username:password@192.168.1.123:34567?channel=0&subtype=0
    - dvrip://username:password@192.168.1.123:34567?backchannel=1
```

---

### Overview (`internal/echo/README.md`)

# Echo

Some sources may have a dynamic link. And you will need to get it using a Bash or Python script. Your script should echo a link to the source. RTSP, FFmpeg or any of the supported sources.

**Docker** and **Home Assistant add-on** users have preinstalled `python3`, `curl`, `jq`.

## Configuration

```yaml
streams:
  apple_hls: echo:python3 hls.py https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.html
```

## Install python libraries

**Docker** and **Hass Add-on** users have preinstalled `python3` without any additional libraries, like [requests](https://requests.readthedocs.io/) or others. If you need some additional libraries - you need to install them to folder with your script:

1. Install [SSH & Web Terminal](https://github.com/hassio-addons/addon-ssh)
2. Goto Add-on Web UI
3. Install library: `pip install requests -t /config/echo`
4. Add your script to `/config/echo/myscript.py`
5. Use your script as source `echo:python3 /config/echo/myscript.py`

## Example: Apple HLS

```yaml
streams:
  apple_hls: echo:python3 hls.py https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.html
```

**hls.py**

```python
import re
import sys
from urllib.parse import urljoin
from urllib.request import urlopen

html = urlopen(sys.argv[1]).read().decode("utf-8")
url = re.search(r"https.+?m3u8", html)[0]

html = urlopen(url).read().decode("utf-8")
m = re.search(r"^[a-z0-1/_]+\.m3u8$", html, flags=re.MULTILINE)
url = urljoin(url, m[0])

# ffmpeg:https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/gear1/prog_index.m3u8#video=copy
print("ffmpeg:" + url + "#video=copy")
```

---

### Overview (`internal/eseecloud/README.md`)

# EseeCloud

[`new in v1.9.10`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.9.10)

This source is for cameras with a link like this `http://admin:@192.168.1.123:80/livestream/12`. Related [issue](https://github.com/AlexxIT/go2rtc/issues/1690).

## Configuration

```yaml
streams:
  camera1: eseecloud://user:pass@192.168.1.123:80/livestream/12
```

---

### Overview (`internal/exec/README.md`)

# Exec

Exec source can run any external application and expect data from it. Two transports are supported - **pipe** ([`new in v1.5.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.5.0)) and **RTSP**.

If you want to use **RTSP** transport, the command must contain the `{output}` argument in any place. On launch, it will be replaced by the local address of the RTSP server.

**pipe** reads data from app stdout in different formats: **MJPEG**, **H.264/H.265 bitstream**, **MPEG-TS**. Also pipe can write data to app stdin in two formats: **PCMA** and **PCM/48000**.

The source can be used with:

- [FFmpeg](https://ffmpeg.org/) - go2rtc ffmpeg source is just a shortcut to exec source
- [FFplay](https://ffmpeg.org/ffplay.html) - play audio on your server
- [GStreamer](https://gstreamer.freedesktop.org/)
- [Raspberry Pi Cameras](https://www.raspberrypi.com/documentation/computers/camera_software.html)
- any of your own software

## Configuration

Pipe commands support parameters (format: `exec:{command}#{param1}#{param2}`):

- `killsignal` - signal which will be sent to stop the process (numeric form)
- `killtimeout` - time in seconds for forced termination with sigkill
- `backchannel` - enable backchannel for two-way audio
- `starttimeout` - time in seconds for waiting first byte from RTSP

```yaml
streams:
  stream: exec:ffmpeg -re -i /media/BigBuckBunny.mp4 -c copy -rtsp_transport tcp -f rtsp {output}
  picam_h264: exec:libcamera-vid -t 0 --inline -o -
  picam_mjpeg: exec:libcamera-vid -t 0 --codec mjpeg -o -
  pi5cam_h264: exec:libcamera-vid -t 0 --libav-format h264 -o -
  canon: exec:gphoto2 --capture-movie --stdout#killsignal=2#killtimeout=5
  play_pcma: exec:ffplay -fflags nobuffer -f alaw -ar 8000 -i -#backchannel=1
  play_pcm48k: exec:ffplay -fflags nobuffer -f s16be -ar 48000 -i -#backchannel=1
```

## Backchannel

- You can check audio card names in the **Go2rtc > WebUI > Add**
- You can specify multiple backchannel lines with different codecs

```yaml
sources:
  two_way_audio_win:
    - exec:ffmpeg -hide_banner -f dshow -i "audio=Microphone (High Definition Audio Device)" -c pcm_s16le -ar 16000 -ac 1 -f wav -
    - exec:ffplay -nodisp -probesize 32 -f s16le -ar 16000 -#backchannel=1#audio=s16le/16000
    - exec:ffplay -nodisp -probesize 32 -f alaw -ar 8000 -#backchannel=1#audio=alaw/8000
```

---

### Overview (`internal/expr/README.md`)

# Expr

[`new in v1.8.2`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.8.2)

[Expr](https://github.com/antonmedv/expr) - expression language and expression evaluation for Go.

- [language definition](https://expr.medv.io/docs/Language-Definition) - takes best from JS, Python, Jinja2 syntax
- your expression should return a link of any supported source
- expression supports multiple operation, but:
  - all operations must be separated by a semicolon
  - all operations, except the last one, must declare a new variable (`let s = "abc";`)
  - the last operation should return a string
- go2rtc supports additional functions:
  - `fetch` - JS-like HTTP requests
  - `match` - JS-like RegExp queries

## Fetch examples

Multiple fetch requests are executed within a single session. They share the same cookie.

**HTTP GET**

```js
var r = fetch('https://example.org/products.json');
```

**HTTP POST JSON**

```js
var r = fetch('https://example.org/post', {
    method: 'POST',
    // Content-Type: application/json will be set automatically
    json: {username: 'example'}
});
```

**HTTP POST Form**

```js
var r = fetch('https://example.org/post', {
    method: 'POST',
    // Content-Type: application/x-www-form-urlencoded will be set automatically
    data: {username: 'example', password: 'password'}
});
```

## Script examples

**Two way audio for Dahua VTO**

```yaml
streams:
  dahua_vto: |
    expr:
    let host = 'admin:password@192.168.1.123';

    var r = fetch('http://' + host + '/cgi-bin/configManager.cgi?action=setConfig&Encode[0].MainFormat[0].Audio.Compression=G.711A&Encode[0].MainFormat[0].Audio.Frequency=8000');

    'rtsp://' + host + '/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif'
```

**dom.ru**

You can get credentials from https://github.com/ad/domru

```yaml
streams:
  dom_ru: |
    expr:
    let camera   = '***';
    let token    = '***';
    let operator = '***';

    fetch('https://myhome.proptech.ru/rest/v1/forpost/cameras/' + camera + '/video', {
      headers: {
        'Authorization': 'Bearer ' + token,
        'User-Agent': 'Google sdkgphone64x8664 | Android 14 | erth | 8.26.0 (82600010) | 0 | 0 | 0',
        'Operator': operator
      }
    }).json().data.URL
```

**dom.ufanet.ru**

```yaml
streams:
  ufanet_ru: |
    expr:
    let username = '***';
    let password = '***';
    let cameraid = '***';

    let r1 = fetch('https://ucams.ufanet.ru/api/internal/login/', {
      method: 'POST',
      data: {username: username, password: password}
    });
    let r2 = fetch('https://ucams.ufanet.ru/api/v0/cameras/this/?lang=ru', {
      method: 'POST',
      json: {'fields': ['token_l', 'server'], 'token_l_ttl': 3600, 'numbers': [cameraid]},
    }).json().results[0];

    'rtsp://' + r2.server.domain + '/' + r2.number + '?token=' + r2.token_l
```

**Parse HLS files from Apple**

Same example in two languages - python and expr.

```yaml
streams:
  example_python: |
    echo:python -c 'from urllib.request import urlopen; import re

    # url1 = "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/bipbop_16x9_variant.m3u8"
    html1 = urlopen("https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.html").read().decode("utf-8")
    url1 = re.search(r"https.+?m3u8", html1)[0]

    # url2 = "gear1/prog_index.m3u8"
    html2 = urlopen(url1).read().decode("utf-8")
    url2 = re.search(r"^[a-z0-1/_]+\.m3u8$", html2, flags=re.MULTILINE)[0]

    # url3 = "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/gear1/prog_index.m3u8"
    url3 = url1[:url1.rindex("/")+1] + url2

    print("ffmpeg:" + url3 + "#video=copy")'

  example_expr: |
    expr:

    let html1 = fetch("https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.html").text;
    let url1 = match(html1, "https.+?m3u8")[0];

    let html2 = fetch(url1).text;
    let url2 = match(html2, "^[a-z0-1/_]+\\.m3u8$", "m")[0];

    let url3 = url1[:lastIndexOf(url1, "/")+1] + url2;

    "ffmpeg:" + url3 + "#video=copy"
```

## Comparison

| expr                         | python                     | js                             |
|------------------------------|----------------------------|--------------------------------|
| let x = 1;                   | x = 1                      | let x = 1                      |
| {a: 1, b: 2}                 | {"a": 1, "b": 2}           | {a: 1, b: 2}                   |
| let r = fetch(url, {method}) | r = request(method, url)   | r = await fetch(url, {method}) |
| r.ok                         | r.ok                       | r.ok                           |
| r.status                     | r.status_code              | r.status                       |
| r.text                       | r.text                     | await r.text()                 |
| r.json()                     | r.json()                   | await r.json()                 |
| r.headers                    | r.headers                  | r.headers                      |
| let m = match(text, "abc")   | m = re.search("abc", text) | let m = text.match(/abc/)      |

---

### Overview (`internal/ffmpeg/README.md`)

# FFmpeg

You can get any stream, file or device via FFmpeg and push it to go2rtc. The app will automatically start FFmpeg with the proper arguments when someone starts watching the stream.

- FFmpeg preinstalled for **Docker** and **Home Assistant add-on** users
- **Home Assistant add-on** users can target files from [/media](https://www.home-assistant.io/more-info/local-media/setup-media/) folder

## Configuration

Format: `ffmpeg:{input}#{param1}#{param2}#{param3}`. Examples:

```yaml
streams:
  # [FILE] all tracks will be copied without transcoding codecs
  file1: ffmpeg:/media/BigBuckBunny.mp4

  # [FILE] video will be transcoded to H264, audio will be skipped
  file2: ffmpeg:/media/BigBuckBunny.mp4#video=h264

  # [FILE] video will be copied, audio will be transcoded to PCMU
  file3: ffmpeg:/media/BigBuckBunny.mp4#video=copy#audio=pcmu

  # [HLS] video will be copied, audio will be skipped
  hls: ffmpeg:https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/gear5/prog_index.m3u8#video=copy

  # [MJPEG] video will be transcoded to H264
  mjpeg: ffmpeg:http://185.97.122.128/cgi-bin/faststream.jpg#video=h264

  # [RTSP] video with rotation, should be transcoded, so select H264
  rotate: ffmpeg:rtsp://12345678@192.168.1.123/av_stream/ch0#video=h264#rotate=90
```

All transcoding formats have [built-in templates](ffmpeg.go): `h264`, `h265`, `opus`, `pcmu`, `pcmu/16000`, `pcmu/48000`, `pcma`, `pcma/16000`, `pcma/48000`, `aac`, `aac/16000`.

But you can override them via YAML config. You can also add your own formats to the config and use them with source params.

```yaml
ffmpeg:
  bin: ffmpeg  # path to ffmpeg binary
  global: "-hide_banner"
  timeout: 5  # default timeout in seconds for rtsp inputs
  h264: "-codec:v libx264 -g:v 30 -preset:v superfast -tune:v zerolatency -profile:v main -level:v 4.1"
  mycodec: "-any args that supported by ffmpeg..."
  myinput: "-fflags nobuffer -flags low_delay -timeout {timeout} -i {input}"
  myraw: "-ss 00:00:20"
```

- You can use go2rtc stream name as ffmpeg input (ex. `ffmpeg:camera1#video=h264`)
- You can use `video` and `audio` params multiple times (ex. `#video=copy#audio=copy#audio=pcmu`)
- You can use `rotate` param with `90`, `180`, `270` or `-90` values, important with transcoding (ex. `#video=h264#rotate=90`)
- You can use `width` and/or `height` params, important with transcoding (ex. `#video=h264#width=1280`)
- You can use `drawtext` to add a timestamp (ex. `drawtext=x=2:y=2:fontsize=12:fontcolor=white:box=1:boxcolor=black`)
    - This will greatly increase the CPU of the server, even with hardware acceleration
- You can use `timeout` param to set RTSP input timeout in seconds (ex. `#timeout=10`)
- You can use `raw` param for any additional FFmpeg arguments (ex. `#raw=-vf transpose=1`)
- You can use `input` param to override default input template (ex. `#input=rtsp/udp` will change RTSP transport from TCP to UDP+TCP)
    - You can use raw input value (ex. `#input=-timeout {timeout} -i {input}`)
    - You can add your own input templates

Read more about [hardware acceleration](hardware/README.md).

**PS.** It is recommended to check the available hardware in the WebUI add page.

---

### Overview (`internal/flussonic/README.md`)

# Flussonic

[`new in v1.9.10`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.9.10)

Support streams from [Flussonic](https://flussonic.com/) server. Related [issue](https://github.com/AlexxIT/go2rtc/issues/1678).

---

### Overview (`internal/gopro/README.md`)

# GoPro

[`new in v1.8.3`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.8.3)

Support streaming from [GoPro](https://gopro.com/) cameras, connected via USB or Wi-Fi to Linux, Mac, Windows.

Supported models: HERO9, HERO10, HERO11, HERO12.  
Supported OS: Linux, Mac, Windows, [HassOS](https://www.home-assistant.io/installation/)

Other camera models have different APIs. I will try to add them in future versions.

## Configuration

- USB-connected cameras create a new network interface in the system
- Linux users do not need to install anything
- Windows users should install the [network driver](https://community.gopro.com/s/article/GoPro-Webcam)
- if the camera is detected but the stream does not start, you need to disable the firewall

1. Discover camera address: WebUI > Add > GoPro
2. Add camera to config

```yaml
streams:
  hero12: gopro://172.20.100.51
```

## Useful links

- https://gopro.github.io/OpenGoPro/

---

### Overview (`internal/hass/README.md`)

# Hass

Support import camera links from [Home Assistant](https://www.home-assistant.io/) config files:

- [Generic Camera](https://www.home-assistant.io/integrations/generic/), setup via GUI
- [HomeKit Camera](https://www.home-assistant.io/integrations/homekit_controller/)
- [ONVIF](https://www.home-assistant.io/integrations/onvif/)
- [Roborock](https://github.com/humbertogontijo/homeassistant-roborock) vacuums with camera

## Configuration

```yaml
hass:
  config: "/config"  # skip this setting if you are a Home Assistant add-on user

streams:
  generic_camera: hass:Camera1  # Settings > Integrations > Integration Name
  aqara_g3: hass:Camera-Hub-G3-AB12
```

### WebRTC Cameras

[`new in v1.6.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.0)

Any cameras in WebRTC format are supported. But at the moment Home Assistant only supports some [Nest](https://www.home-assistant.io/integrations/nest/) cameras in this format.

**Important.** The Nest API only allows you to get a link to a stream for 5 minutes.
Do not use this with Frigate! If the stream expires, Frigate will consume all available RAM on your machine within seconds.
It's recommended to use [Nest source](../nest/README.md) - it supports extending the stream.

```yaml
streams:
  # link to Home Assistant Supervised
  hass-webrtc1: hass://supervisor?entity_id=camera.nest_doorbell
  # link to external Home Assistant with Long-Lived Access Tokens
  hass-webrtc2: hass://192.168.1.123:8123?entity_id=camera.nest_doorbell&token=eyXYZ...
```

### RTSP Cameras

By default, the Home Assistant API does not allow you to get a dynamic RTSP link to a camera stream. [This method](https://github.com/felipecrs/hass-expose-camera-stream-source#importing-cameras-from-home-assistant-to-go2rtc-or-frigate) can work around it.

---

### Overview (`internal/hls/README.md`)

# HLS

[`new in v1.1.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.1.0)

[HLS](https://en.wikipedia.org/wiki/HTTP_Live_Streaming) is the worst technology for real-time streaming. 
It can only be useful on devices that do not support more modern technology, like [WebRTC](../webrtc/README.md), [MP4](../mp4/README.md).

The go2rtc implementation differs from the standards and may not work with all players.

API examples:

- HLS/TS stream: `http://192.168.1.123:1984/api/stream.m3u8?src=camera1` (H264)
- HLS/fMP4 stream: `http://192.168.1.123:1984/api/stream.m3u8?src=camera1&mp4` (H264, H265, AAC)

Read more about [codecs filters](../../README.md#codecs-filters).

## Useful links

- https://walterebert.com/playground/video/hls/

---

### Overview (`internal/homekit/README.md`)

# Apple HomeKit

This module supports both client and server for the [Apple HomeKit](https://www.apple.com/home-app/accessories/) protocol.

## HomeKit Client

**Important:**

- You can use HomeKit Cameras **without Apple devices** (iPhone, iPad, etc.), it's just a yet another protocol
- HomeKit device can be paired with only one ecosystem. So, if you have paired it to an iPhone (Apple Home), you can't pair it with Home Assistant or go2rtc. Or if you have paired it to go2rtc, you can't pair it with an iPhone
- HomeKit device should be on the same network with working [mDNS](https://en.wikipedia.org/wiki/Multicast_DNS) between the device and go2rtc

go2rtc supports importing paired HomeKit devices from [Home Assistant](../hass/README.md). 
So you can use HomeKit camera with Home Assistant and go2rtc simultaneously. 
If you are using Home Assistant, I recommend pairing devices with it; it will give you more options.

You can pair device with go2rtc on the HomeKit page. If you can't see your devices, reload the page. 
Also, try rebooting your HomeKit device (power off). If you still can't see it, you have a problem with mDNS.

If you see a device but it does not have a pairing button, it is paired to some ecosystem (Apple Home, Home Assistant, HomeBridge, etc.). You need to delete the device from that ecosystem, and it will be available for pairing. If you cannot unpair the device, you will have to reset it.

**Important:**

- HomeKit audio uses very non-standard **AAC-ELD** codec with very non-standard params and specification violations
- Audio can't be played in `VLC` and probably any other player
- Audio should be transcoded for use with MSE, WebRTC, etc.

### Client Configuration

Recommended settings for using HomeKit Camera with WebRTC, MSE, MP4, RTSP:

```yaml
streams:
  aqara_g3:
    - hass:Camera-Hub-G3-AB12
    - ffmpeg:aqara_g3#audio=aac#audio=opus
```

RTSP link with "normal" audio for any player: `rtsp://192.168.1.123:8554/aqara_g3?video&audio=aac`

**This source is in active development!** Tested only with [Aqara Camera Hub G3](https://www.aqara.com/eu/product/camera-hub-g3) (both EU and CN versions).

## HomeKit Server

[`new in v1.7.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.7.0)

HomeKit module can work in two modes:

- export any H264 camera to Apple HomeKit
- transparent proxy any Apple HomeKit camera (Aqara, Eve, Eufy, etc.) back to Apple HomeKit, so you will have all camera features in Apple Home and also will have RTSP/WebRTC/MP4/etc. from your HomeKit camera

**Important**

- HomeKit cameras support only H264 video and OPUS audio

### Server Configuration

**Minimal config**

```yaml
streams:
  dahua1: rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=0
homekit:
  dahua1:  # same stream ID from streams list, default PIN - 19550224
```

**Full config**

```yaml
streams:
  dahua1:
    - rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=0
    - ffmpeg:dahua1#video=h264#hardware  # if your camera doesn't support H264, important for HomeKit
    - ffmpeg:dahua1#audio=opus           # only OPUS audio supported by HomeKit

homekit:
  dahua1:                   # same stream ID from streams list
    pin: 12345678           # custom PIN, default: 19550224
    name: Dahua camera      # custom camera name, default: generated from stream ID
    device_id: dahua1       # custom ID, default: generated from stream ID
    device_private: dahua1  # custom key, default: generated from stream ID
```

**Proxy HomeKit camera**

- Video stream from HomeKit camera to Apple device (iPhone, Apple TV) will be transmitted directly
- Video stream from HomeKit camera to RTSP/WebRTC/MP4/etc. will be transmitted via go2rtc

```yaml
streams:
  aqara1:
    - homekit://...
    - ffmpeg:aqara1#audio=aac#audio=opus  # optional audio transcoding

homekit:
  aqara1:  # same stream ID from streams list
```

---

### Overview (`internal/http/README.md`)

# HTTP

This source supports receiving a stream via an HTTP link.

It can determine the source format from the`Content-Type` HTTP header:

- **HTTP-JPEG** (`image/jpeg`) - camera snapshot link, can be converted by go2rtc to MJPEG stream
- **HTTP-MJPEG** (`multipart/x-mixed-replace`) - A continuous sequence of JPEG frames (with HTTP headers).
- **HLS** (`application/vnd.apple.mpegurl`) - A popular [HTTP Live Streaming](https://en.wikipedia.org/wiki/HTTP_Live_Streaming) (HLS) format, which is not designed for real-time media transmission.

> [!WARNING]
> The HLS format is not designed for real time and is supported quite poorly. It is recommended to use it via ffmpeg source with buffering enabled (disabled by default).

## TCP

Source also supports HTTP and TCP streams with autodetection for different formats:

- `adts` - Audio stream in [AAC](https://en.wikipedia.org/wiki/Advanced_Audio_Coding) codec with Audio Data Transport Stream (ADTS) headers.
- `flv` - The legacy but still used [Flash Video](https://en.wikipedia.org/wiki/Flash_Video) format.
- `h264` - AVC/H.264 bitstream.
- `hevc` - HEVC/H.265 bitstream.
- `mjpeg` - A continuous sequence of JPEG frames (without HTTP headers).
- `mpegts` - The legacy [MPEG transport stream](https://en.wikipedia.org/wiki/MPEG_transport_stream) format.
- `wav` - Audio stream in [WAV](https://en.wikipedia.org/wiki/WAV) format.
- `yuv4mpegpipe` - Raw YUV frame stream with YUV4MPEG header.

## Configuration

```yaml
streams:
  # [HTTP-FLV] stream in video/x-flv format
  http_flv: http://192.168.1.123:20880/api/camera/stream/780900131155/657617
  
  # [JPEG] snapshots from Dahua camera, will be converted to MJPEG stream
  dahua_snap: http://admin:password@192.168.1.123/cgi-bin/snapshot.cgi?channel=1

  # [MJPEG] stream will be proxied without modification
  http_mjpeg: https://mjpeg.sanford.io/count.mjpeg

  # [MJPEG or H.264/H.265 bitstream or MPEG-TS]
  tcp_magic: tcp://192.168.1.123:12345

  # Add custom header
  custom_header: "https://mjpeg.sanford.io/count.mjpeg#header=Authorization: Bearer XXX"
```

**PS.** Dahua camera has a bug: if you select MJPEG codec for RTSP second stream, snapshot won't work.

---

### Overview (`internal/isapi/README.md`)

# Hikvision ISAPI

[`new in v1.3.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)

This source type supports only backchannel audio for the [Hikvision ISAPI](https://tpp.hikvision.com/download/ISAPI_OTAP) protocol. So it should be used as a second source in addition to the RTSP protocol.

## Configuration

```yaml
streams:
  hikvision1:
    - rtsp://admin:password@192.168.1.123:554/Streaming/Channels/101
    - isapi://admin:password@192.168.1.123:80/
```

---

### Overview (`internal/ivideon/README.md`)

# Ivideon

Support public cameras from the service [Ivideon](https://tv.ivideon.com/).

## Configuration

```yaml
streams:
  quailcam: ivideon:100-tu5dkUPct39cTp9oNEN2B6/0
```

---

### Overview (`internal/kasa/README.md`)

# TP-Link Kasa

[`new in v1.7.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.7.0)

[TP-Link Kasa](https://www.kasasmart.com/) non-standard protocol [more info](https://medium.com/@hu3vjeen/reverse-engineering-tp-link-kc100-bac4641bf1cd).

- `username` - urlsafe email, `alex@gmail.com` -> `alex%40gmail.com`
- `password` - base64password, `secret1` -> `c2VjcmV0MQ==`

```yaml
streams:
  kc401: kasa://username:password@192.168.1.123:19443/https/stream/mixed
```

Tested: KD110, KC200, KC401, KC420WS, EC71.

---

### Overview (`internal/mjpeg/README.md`)

# Motion JPEG

- This module can provide and receive streams in MJPEG format.
- This module is also responsible for receiving snapshots in JPEG format.
- This module also supports streaming to the server console (terminal) in the **animated ASCII art** format.

## MJPEG Client

**Important.** For a stream in MJPEG format, your source MUST contain the MJPEG codec. If your stream has the MJPEG codec, you can receive an **MJPEG stream** or **JPEG snapshots** via the API.

You can receive an MJPEG stream in several ways:

- some cameras support MJPEG codec inside [RTSP stream](../rtsp/README.md) (ex. second stream for Dahua cameras)
- some cameras have an HTTP link with [MJPEG stream](../http/README.md)
- some cameras have an HTTP link with snapshots - go2rtc can convert them to [MJPEG stream](../http/README.md)
- you can convert an H264/H265 stream from your camera via [FFmpeg integration](../ffmpeg/README.md)

With this example, your stream will have both H264 and MJPEG codecs:

```yaml
streams:
  camera1:
    - rtsp://rtsp:12345678@192.168.1.123/av_stream/ch0
    - ffmpeg:camera1#video=mjpeg
```

## MJPEG Server

### mpjpeg

Output a stream in [MJPEG](https://en.wikipedia.org/wiki/Motion_JPEG) format. In [FFmpeg](https://ffmpeg.org/), this format is called `mpjpeg` because it contains HTTP headers.

```
ffplay http://192.168.1.123:1984/api/stream.mjpeg?src=camera1
```

### jpeg

Receiving a JPEG snapshot.

```
curl http://192.168.1.123:1984/api/frame.jpeg?src=camera1
```

- You can use `width`/`w` and/or `height`/`h` parameters.
- You can use `rotate` param with `90`, `180`, `270` or `-90` values.
- You can use `hardware`/`hw` param [read more](https://github.com/AlexxIT/go2rtc/wiki/Hardware-acceleration).
- You can use `cache` param (`1m`, `10s`, etc.) to get a cached snapshot.
  - The snapshot is cached only when requested with the `cache` parameter.
  - A cached snapshot will be used if its time is not older than the time specified in the `cache` parameter.
  - The `cache` parameter does not check the image dimensions from the cache and those specified in the query.

### ascii

Stream as ASCII to Terminal. This format is just for fun. You can boast to your friends that you can stream cameras even to the server console without a GUI.

[](https://www.youtube.com/watch?v=sHj_3h_sX7M)

> The demo video features a combination of several settings for this format with added audio. Of course, the format doesn't support audio out of the box.

**Tips**

- this feature works only with MJPEG codec (use transcoding)
- choose a low frame rate (FPS)
- choose the width and height to fit in your terminal
- different terminals support different numbers of colors (8, 256, rgb)
- URL-encode the `text` parameter
- you can stream any camera or file from disk

**go2rtc.yaml** - transcoding to MJPEG, terminal size - 210x59 (16/9), fps - 10

```yaml
streams:
  gamazda: ffmpeg:gamazda.mp4#video=mjpeg#hardware#width=210#height=59#raw=-r 10
```

**API params**

- `color` - foreground color, values: empty, `8`, `256`, `rgb`, [SGR](https://en.wikipedia.org/wiki/ANSI_escape_code)
  - example: `30` (black), `37` (white), `38;5;226` (yellow)
- `back` - background color, values: empty, `8`, `256`, `rgb`, [SGR](https://en.wikipedia.org/wiki/ANSI_escape_code)
  - example: `40` (black), `47` (white), `48;5;226` (yellow)
- `text` - character set, values: empty, one character, `block`, list of chars (in order of brightness)
  - example: `%20` (space), `block` (keyword for block elements), `ox` (two chars)

**Examples**

```bash
% curl "http://192.168.1.123:1984/api/stream.ascii?src=gamazda"
% curl "http://192.168.1.123:1984/api/stream.ascii?src=gamazda&color=256"
% curl "http://192.168.1.123:1984/api/stream.ascii?src=gamazda&back=256&text=%20"
% curl "http://192.168.1.123:1984/api/stream.ascii?src=gamazda&back=8&text=%20%20"
% curl "http://192.168.1.123:1984/api/stream.ascii?src=gamazda&text=helloworld"
```

### yuv4mpegpipe

Raw [YUV](https://en.wikipedia.org/wiki/Y%E2%80%B2UV) frame stream with [YUV4MPEG](https://manned.org/yuv4mpeg) header.

```
ffplay http://192.168.1.123:1984/api/stream.y4m?src=camera1
```

## Streaming ingest

```shell
ffmpeg -re -i BigBuckBunny.mp4 -c mjpeg -f mpjpeg http://localhost:1984/api/stream.mjpeg?dst=camera1
```

---

### Overview (`internal/mp4/README.md`)

# MP4

This module provides several features:

1. MSE stream (fMP4 over WebSocket)
2. Camera snapshots in MP4 format (single frame), can be sent to [Telegram](#snapshot-to-telegram)
3. HTTP progressive streaming (MP4 file stream) - bad format for streaming because of high start delay. This format doesn't work in all Safari browsers, but go2rtc will automatically redirect it to HLS/fMP4 in this case.

## API examples

- MP4 snapshot: `http://192.168.1.123:1984/api/frame.mp4?src=camera1` (H264, H265)
- MP4 stream: `http://192.168.1.123:1984/api/stream.mp4?src=camera1` (H264, H265, AAC)
- MP4 file: `http://192.168.1.123:1984/api/stream.mp4?src=camera1` (H264, H265*, AAC, OPUS, MP3, PCMA, PCMU, PCM)
    - You can use `mp4`, `mp4=flac` and `mp4=all` param for codec filters
    - You can use `duration` param in seconds (ex. `duration=15`)
    - You can use `filename` param (ex. `filename=record.mp4`)
    - You can use `rotate` param with `90`, `180` or `270` values
    - You can use `scale` param with positive integer values (ex. `scale=4:3`)

Read more about [codecs filters](../../README.md#codecs-filters).

**PS.** Rotate and scale params don't use transcoding and change video using metadata.

## Snapshot to Telegram

This examples for Home Assistant [Telegram Bot](https://www.home-assistant.io/integrations/telegram_bot/) integration.

- change `url` to your go2rtc web API (`http://localhost:1984/` for most users)
- change `target` to your Telegram chat ID (support list)
- change `src=camera1` to your stream name from go2rtc config

**Important.** Snapshot will be near instant for most cameras and many sources, except `ffmpeg` source. Because it takes a long time for ffmpeg to start streaming with video, even when you use `#video=copy`. Also the delay can be with cameras that do not start the stream with a keyframe.

### Snapshot from H264 or H265 camera

```yaml
service: telegram_bot.send_video
data:
  url: http://localhost:1984/api/frame.mp4?src=camera1
  target: 123456789
```

### Record from H264 or H265 camera

Record from service call to the future. Doesn't support loopback.

- `mp4=flac` - adds support PCM audio family
- `filename=record.mp4` - set name for downloaded file

```yaml
service: telegram_bot.send_video
data:
  url: http://localhost:1984/api/stream.mp4?src=camera1&mp4=flac&duration=5&filename=record.mp4  # duration in seconds
  target: 123456789
```

### Snapshot from JPEG or MJPEG camera

This example works via the [mjpeg](../mjpeg/README.md) module.

```yaml
service: telegram_bot.send_photo
data:
  url: http://localhost:1984/api/frame.jpeg?src=camera1
  target: 123456789
```

---

### Overview (`internal/mpeg/README.md`)

# MPEG

This module provides an [HTTP API](../api/README.md) for:
 
- Streaming output in `mpegts` format.
- Streaming output in `adts` format.
- Streaming ingest in `mpegts` format.

## MPEG-TS Server

```shell
ffplay http://localhost:1984/api/stream.ts?src=camera1
```

## ADTS Server

```shell
ffplay http://localhost:1984/api/stream.aac?src=camera1
```

## Streaming ingest

```shell
ffmpeg -re -i BigBuckBunny.mp4 -c copy -f mpegts http://localhost:1984/api/stream.ts?dst=camera1
```

---

### Overview (`internal/multitrans/README.md`)

# TP-Link MULTITRANS

[`new in v1.9.14`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.9.14) by [@forrestsocool](https://github.com/forrestsocool)

Two-way audio support for Chinese version of [TP-Link](https://www.tp-link.com.cn/) cameras.

## Configuration

```yaml
streams:
  tplink_cam:
    # video uses standard RTSP
    - rtsp://admin:admin@192.168.1.202:554/stream1
    # two-way audio uses MULTITRANS schema
    - multitrans://admin:admin@192.168.1.202:554
```

## Useful links

- https://www.tp-link.com.cn/list_2549.html
- https://github.com/AlexxIT/go2rtc/issues/1724
- https://github.com/bingooo/hass-tplink-ipc/

---

### Overview (`internal/nest/README.md`)

# Google Nest

[`new in v1.6.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.0)

For simplicity, it is recommended to connect the Nest/WebRTC camera to the [Home Assistant](../hass/README.md). 
But if you can somehow get the below parameters, Nest/WebRTC source will work without Home Assistant.

```yaml
streams:
  nest-doorbell: nest:?client_id=***&client_secret=***&refresh_token=***&project_id=***&device_id=***
```

---

### Overview (`internal/ngrok/README.md`)

# ngrok

With the ngrok integration, you can get external access to your streams when your Internet connection is behind a private IP address.

- you may need external access for two different things:
    - WebRTC streams (tunnel the WebRTC TCP port, e.g. 8555)
    - go2rtc web interface (tunnel the API HTTP port, e.g. 1984)
- ngrok supports authorization for your web interface
- ngrok automatically adds HTTPS to your web interface

The ngrok free subscription has the following limitations:

- You can reserve a free domain for serving the web interface, but the TCP address you get will always be random and will change with each restart of the ngrok agent (not a problem for WebRTC streams)
- You can forward multiple ports from a single agent, but you can only run one ngrok agent on the free plan

go2rtc will automatically get your external TCP address (if you enable it in the ngrok config) and use it for WebRTC connections (if you enable it in the WebRTC config).

You need to manually download the [ngrok agent](https://ngrok.com/download) for your OS and register with the [ngrok service](https://ngrok.com/signup).

**Tunnel for only WebRTC Stream**

You need to add your [ngrok authtoken](https://dashboard.ngrok.com/get-started/your-authtoken) and WebRTC TCP port to YAML:

```yaml
ngrok:
  command: ngrok tcp 8555 --authtoken eW91IHNoYWxsIG5vdCBwYXNzCnlvdSBzaGFsbCBub3QgcGFzcw
```

**Tunnel for WebRTC and Web interface**

You need to create `ngrok.yaml` config file and add it to the go2rtc config:

```yaml
ngrok:
  command: ngrok start --all --config ngrok.yaml
```

ngrok config example:

```yaml
version: "2"
authtoken: eW91IHNoYWxsIG5vdCBwYXNzCnlvdSBzaGFsbCBub3QgcGFzcw
tunnels:
  api:
    addr: 1984  # use the same port as in the go2rtc config
    proto: http
    basic_auth:
      - admin:password  # you can set login/pass for your web interface
  webrtc:
    addr: 8555  # use the same port as in the go2rtc config
    proto: tcp
```

See the [ngrok agent documentation](https://ngrok.com/docs/agent/config/) for more details on the ngrok configuration file.

---

### Overview (`internal/onvif/README.md`)

# ONVIF

## ONVIF Client

[`new in v1.5.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.5.0)

The source is not very useful if you already know RTSP and snapshot links for your camera. But it can be useful if you don't.

**WebUI > Add** webpage supports ONVIF autodiscovery. Your server must be on the same subnet as the camera. If you use Docker, you must use "network host".

```yaml
streams:
  dahua1: onvif://admin:password@192.168.1.123
  reolink1: onvif://admin:password@192.168.1.123:8000
  tapo1: onvif://admin:password@192.168.1.123:2020
```

## ONVIF Server

A regular camera has a single video source (`GetVideoSources`) and two profiles (`GetProfiles`).

Go2rtc has one video source and one profile per stream.

## Tested clients

Go2rtc works as ONVIF server:

- Happytime onvif client (windows)
- Home Assistant ONVIF integration (linux)
- Onvier (android)
- ONVIF Device Manager (windows)

PS. Supports only TCP transport for RTSP protocol. UDP and HTTP transports - unsupported yet.

## Tested cameras

Go2rtc works as ONVIF client:

- Dahua IPC-K42
- OpenIPC
- Reolink RLC-520A
- TP-Link Tapo TC60

---

### Overview (`internal/pinggy/README.md`)

# Pinggy

[Pinggy](https://pinggy.io/) - nice service for public tunnels to your local services.

**Features:**

- A free account does not require registration.
- It does not require downloading third-party binaries and works over the SSH protocol.
- Works with HTTP, TCP and UDP protocols.
- Creates HTTPS for your HTTP services.

> [!IMPORTANT]
> A free account creates a tunnel with a random address that only works for an hour. It is suitable for testing purposes ONLY.

> [!CAUTION]
> Public access to go2rtc without authorization puts your entire home network at risk. Use with caution.

**Why:**

- It's easy to set up HTTPS for testing two-way audio.
- It's easy to check whether external access via WebRTC technology will work.
- It's easy to share direct access to your RTSP or HTTP camera with the go2rtc developer. If such access is necessary to debug your problem.

## Configuration

You will find public links in the go2rtc log after startup.

**Tunnel to go2rtc WebUI.**

```yaml
pinggy:
  tunnel: http://localhost:1984
```

**Tunnel to RTSP camera.**

For example, you have camera: `rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=0`

```yaml
pinggy:
  tunnel: tcp://192.168.10.91:554
```

In go2rtc logs you will get similar output:

```
16:17:43.167 INF [pinggy] proxy url=tcp://abcde-123-123-123-123.a.free.pinggy.link:12345
```

Now you have a working stream:

```
rtsp://admin:password@abcde-123-123-123-123.a.free.pinggy.link:12345/cam/realmonitor?channel=1&subtype=0
```

---

### Overview (`internal/ring/README.md`)

# Ring

[`new in v1.9.13`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.9.13) by [@seydx](https://github.com/seydx)

This source type supports Ring cameras with [two-way audio](../../README.md#two-way-audio) support.

## Configuration

If you have a `refresh_token` and `device_id`, you can use them in the `go2rtc.yaml` config file.

Otherwise, you can use the go2rtc web interface and add your Ring account (WebUI > Add > Ring). Once added, it will list all your Ring cameras.

```yaml
streams:
  ring: ring:?device_id=XXX&refresh_token=XXX
  ring_snapshot: ring:?device_id=XXX&refresh_token=XXX&snapshot
```

---

### Overview (`internal/roborock/README.md`)

# Roborock

[`new in v1.3.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)

This source type supports Roborock vacuums with cameras. Known working models:

- **Roborock S6 MaxV** - only video (the vacuum has no microphone)
- **Roborock S7 MaxV** - video and two-way audio
- **Roborock Qrevo MaxV** - video and two-way audio

## Configuration

This source supports loading Roborock credentials from the Home Assistant [custom integration](https://github.com/humbertogontijo/homeassistant-roborock) or the [core integration](https://www.home-assistant.io/integrations/roborock). Otherwise, you need to log in to your Roborock account (MiHome account is not supported). Go to go2rtc WebUI > Add webpage. Copy the `roborock://...` source for your vacuum and paste it into your `go2rtc.yaml` config.

If you have a pattern PIN for your vacuum, add it as a numeric PIN (lines: 123, 456, 789) to the end of the `roborock` link.

---

### Overview (`internal/rtmp/README.md`)

# Real-Time Messaging Protocol

This module provides the following features for the RTMP protocol:

- Streaming input - [RTMP client](#rtmp-client)
- Streaming output and ingest in `rtmp` format - [RTMP server](#rtmp-server)
- Streaming output and ingest in `flv` format - [FLV server](#flv-server)

## RTMP Client

You can get a stream from an RTMP server, for example [Nginx with nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module).

### Client Configuration

```yaml
streams:
  rtmp_stream: rtmp://192.168.1.123/live/camera1
```

## RTMP Server

[`new in v1.8.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.8.0)

Streaming output stream in `rtmp` format:

```shell
ffplay rtmp://localhost:1935/camera1
```

Streaming ingest stream in `rtmp` format:

```shell
ffmpeg -re -i BigBuckBunny.mp4 -c copy -f flv rtmp://localhost:1935/camera1
```

### Server Configuration

By default, the RTMP server is disabled.

```yaml
rtmp:
  listen: ":1935"  # by default - disabled!
```

## FLV Server

Streaming output in `flv` format.

```shell
ffplay http://localhost:1984/stream.flv?src=camera1
```

Streaming ingest in `flv` format.

```shell
ffmpeg -re -i BigBuckBunny.mp4 -c copy -f flv http://localhost:1984/api/stream.flv?dst=camera1
```

## Tested clients

| From   | To                              | Comment |
|--------|---------------------------------|---------|
| go2rtc | Reolink RLC-520A fw. v3.1.0.801 | OK      |

**go2rtc.yaml**

```yaml
streams:
  rtmp-reolink1: rtmp://192.168.10.92/bcs/channel0_main.bcs?channel=0&stream=0&user=admin&password=password
  rtmp-reolink2: rtmp://192.168.10.92/bcs/channel0_sub.bcs?channel=0&stream=1&user=admin&password=password
  rtmp-reolink3: rtmp://192.168.10.92/bcs/channel0_ext.bcs?channel=0&stream=1&user=admin&password=password
```

## Tested server

| From                   | To     | Comment             |
|------------------------|--------|---------------------|
| OBS 31.0.2             | go2rtc | OK                  |
| OpenIPC 2.5.03.02-lite | go2rtc | OK                  |
| FFmpeg 6.1             | go2rtc | OK                  |
| GoPro Black 12         | go2rtc | OK, 1080p, 5000kbps |

**go2rtc.yaml**

```yaml
rtmp:
  listen: :1935
streams:
  tmp:
```

**OBS**
 
Settings > Stream:

- Service: Custom
- Server: rtmp://192.168.10.101/tmp
- Stream Key: `<empty>`
- Use auth: `<disabled>`

**OpenIPC**

WebUI > Majestic > Settings > Outgoing

- Enable
- Address: rtmp://192.168.10.101/tmp
- Save
- Restart

**FFmpeg**

```shell
ffmpeg -re -i bbb.mp4 -c copy -f flv rtmp://192.168.10.101/tmp
```

**GoPro**

GoPro Quik > Camera > Translation > Other

---

### Overview (`internal/rtsp/README.md`)

# Real Time Streaming Protocol

This module provides the following features for the RTSP protocol:

 - Streaming input - [RTSP client](#rtsp-client)
 - Streaming output - [RTSP server](#rtsp-server)
 - [Streaming ingest](#streaming-ingest)
 - [Two-way audio](#two-way-audio)

## RTSP Client

### Configuration

```yaml
streams:
  sonoff_camera: rtsp://rtsp:12345678@192.168.1.123/av_stream/ch0
  dahua_camera:
    - rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    - rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=1#backchannel=0
  amcrest_doorbell:
    - rtsp://username:password@192.168.1.123:554/cam/realmonitor?channel=1&subtype=0#backchannel=0
  unifi_camera: rtspx://192.168.1.123:7441/fD6ouM72bWoFijxK
  glichy_camera: ffmpeg:rtsp://username:password@192.168.1.123/live/ch00_1 
```

### Recommendations

- **Amcrest Doorbell** users may want to disable two-way audio, because with an active stream, you won't have a working call button. You need to add `#backchannel=0` to the end of your RTSP link in YAML config file
- **Dahua Doorbell** users may want to change [audio codec](https://github.com/AlexxIT/go2rtc/issues/49#issuecomment-2127107379) for proper two-way audio. Make sure not to request backchannel multiple times by adding `#backchannel=0` to other stream sources of the same doorbell. The `unicast=true&proto=Onvif` is preferred for two-way audio as this makes the doorbell accept multiple codecs for the incoming audio
- **Reolink** users may want NOT to use RTSP protocol at all, some camera models have a very awful, unusable stream implementation
- **Ubiquiti UniFi** users may want to disable HTTPS verification. Use `rtspx://` prefix instead of `rtsps://`. And don't use `?enableSrtp` [suffix](https://github.com/AlexxIT/go2rtc/issues/81)
- **TP-Link Tapo** users may skip login and password, because go2rtc supports login [without them](https://drmnsamoliu.github.io/video.html)
- If your camera has two RTSP links, you can add both as sources. This is useful when streams have different codecs, for example AAC audio with main stream and PCMU/PCMA audio with second stream
- If the stream from your camera is glitchy, try using [ffmpeg source](../ffmpeg/README.md). It will not add CPU load if you don't use transcoding
- If the stream from your camera is very glitchy, try to use transcoding with [ffmpeg source](../ffmpeg/README.md)

### Other options

Format: `rtsp...#{param1}#{param2}#{param3}`

- Add custom timeout `#timeout=30` (in seconds)
- Ignore audio - `#media=video` or ignore video - `#media=audio`
- Ignore two-way audio API `#backchannel=0` - important for some glitchy cameras
- Use WebSocket transport `#transport=ws...`

### RTSP over WebSocket

```yaml
streams:
  # WebSocket with authorization, RTSP - without
  axis-rtsp-ws:  rtsp://192.168.1.123:4567/axis-media/media.amp?overview=0&camera=1&resolution=1280x720&videoframeskipmode=empty&Axis-Orig-Sw=true#transport=ws://user:pass@192.168.1.123:4567/rtsp-over-websocket
  # WebSocket without authorization, RTSP - with
  dahua-rtsp-ws: rtsp://user:pass@192.168.1.123/cam/realmonitor?channel=1&subtype=1&proto=Private3#transport=ws://192.168.1.123/rtspoverwebsocket
```

## RTSP Server

You can get any stream as RTSP-stream: `rtsp://192.168.1.123:8554/{stream_name}`

You can enable external password protection for your RTSP streams. Password protection is always disabled for localhost calls (ex. FFmpeg or Home Assistant on the same server).

### Configuration

```yaml
rtsp:
  listen: ":8554"    # RTSP Server TCP port, default - 8554
  username: "admin"  # optional, default - disabled
  password: "pass"   # optional, default - disabled
  default_query: "video&audio"  # optional, default codecs filters 
```

By default go2rtc provide RTSP-stream with only one first video and only one first audio. You can change it with the `default_query` setting:

- `default_query: "mp4"` - MP4 compatible codecs (H264, H265, AAC)
- `default_query: "video=all&audio=all"` - all tracks from all source (not all players can handle this)
- `default_query: "video=h264,h265"` - only one video track (H264 or H265)
- `default_query: "video&audio=all"` - only one first any video and all audio as separate tracks

Read more about [codecs filters](../../README.md#codecs-filters).

## Streaming ingest

```shell
ffmpeg -re -i BigBuckBunny.mp4 -c copy -rtsp_transport tcp -f rtsp rtsp://localhost:8554/camera1
```

## Two-way audio

Before purchasing, it is difficult to understand whether the camera supports two-way audio via the RTSP protocol or not. This isn't usually mentioned in a camera's description. You can only find out by reading reviews from real buyers.

A camera is considered to support two-way audio if it supports the ONVIF Profile T protocol. But in reality, this isn't always the case. And the ONVIF protocol has no connection with the camera's RTSP implementation.

In go2rtc you can find out if the camera supports two-way audio via WebUI > stream probe.

---

### Overview (`internal/srtp/README.md`)

# SRTP

This is a support module for the [HomeKit](../homekit/README.md) module.

> [!NOTE]
> This module can be removed and its functionality transferred to the homekit module.

## Configuration

```yaml
srtp:
  listen: :8443  # enabled by default
```

---

### Overview (`internal/streams/README.md`)

# Streams

This core module is responsible for managing the stream list.

## Stream to camera

[`new in v1.3.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)

go2rtc supports playing audio files (ex. music or [TTS](https://www.home-assistant.io/integrations/#text-to-speech)) and live streams (ex. radio) on cameras with [two-way audio](../../README.md#two-way-audio) support.

API example:

```text
POST http://localhost:1984/api/streams?dst=camera1&src=ffmpeg:http://example.com/song.mp3#audio=pcma#input=file
```

- you can stream: local files, web files, live streams or any format, supported by FFmpeg
- you should use [ffmpeg source](../ffmpeg/README.md) for transcoding audio to codec, that your camera supports
- you can check camera codecs on the go2rtc WebUI info page when the stream is active
- some cameras support only low quality `PCMA/8000` codec (ex. [Tapo](../tapo/README.md))
- it is recommended to choose higher quality formats if your camera supports them (ex. `PCMA/48000` for some Dahua cameras)
- if you play files over `http` link, you need to add `#input=file` params for transcoding, so the file will be transcoded and played in real time
- if you play live streams, you should skip `#input` param, because it is already in real time
- you can stop active playback by calling the API with the empty `src` parameter
- you will see one active producer and one active consumer in go2rtc WebUI info page during streaming

## Publish stream

[`new in v1.8.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.8.0)

You can publish any stream to streaming services (YouTube, Telegram, etc.) via RTMP/RTMPS. Important:

- Supported codecs: H264 for video and AAC for audio
- AAC audio is required for YouTube; videos without audio will not work
- You don't need to enable [RTMP module](../rtmp/README.md) listening for this task

You can use the API:

```text
POST http://localhost:1984/api/streams?src=camera1&dst=rtmps://...
```

Or config file:

```yaml
publish:
  # publish stream "video_audio_transcode" to Telegram
  video_audio_transcode:
    - rtmps://xxx-x.rtmp.t.me/s/xxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxx
  # publish stream "audio_transcode" to Telegram and YouTube
  audio_transcode:
    - rtmps://xxx-x.rtmp.t.me/s/xxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxx
    - rtmp://xxx.rtmp.youtube.com/live2/xxxx-xxxx-xxxx-xxxx-xxxx

streams:
  video_audio_transcode:
    - ffmpeg:rtsp://user:pass@192.168.1.123/stream1#video=h264#hardware#audio=aac
  audio_transcode:
    - ffmpeg:rtsp://user:pass@192.168.1.123/stream1#video=copy#audio=aac
```

- **Telegram Desktop App** > Any public or private channel or group (where you admin) > Live stream > Start with... > Start streaming.
- **YouTube** > Create > Go live > Stream latency: Ultra low-latency > Copy: Stream URL + Stream key.

## Preload stream

[`new in v1.9.11`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.9.11)

You can preload any stream on go2rtc start. This is useful for cameras that take a long time to start up.

```yaml
preload:
  camera1:                                     # default: video&audio = ANY
  camera2: "video"                             # preload only video track
  camera3: "video=h264&audio=opus"             # preload H264 video and OPUS audio

streams:
  camera1: 
    - rtsp://192.168.1.100/stream
  camera2: 
    - rtsp://192.168.1.101/stream  
  camera3: 
    - rtsp://192.168.1.102/h265stream
    - ffmpeg:camera3#video=h264#audio=opus#hardware
```

## Examples

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Overview (`internal/tapo/README.md`)

# TP-Link Tapo

[`new in v1.2.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.2.0)

[TP-Link Tapo](https://www.tapo.com/) proprietary camera protocol with **two-way audio** support.

- stream quality is the same as [RTSP protocol](https://www.tapo.com/en/faq/34/)
- use the **cloud password**, this is not the RTSP password! you do not need to add a login!
- you can also use **UPPERCASE** MD5 hash from your cloud password with `admin` username
- some new camera firmwares require SHA256 instead of MD5

## Configuration

```yaml
streams:
  # cloud password without username
  camera1: tapo://cloud-password@192.168.1.123
  # admin username and UPPERCASE MD5 cloud-password hash
  camera2: tapo://admin:UPPERCASE-MD5@192.168.1.123
  # admin username and UPPERCASE SHA256 cloud-password hash
  camera3: tapo://admin:UPPERCASE-SHA256@192.168.1.123
  # VGA stream (the so called substream, the lower resolution one)
  camera4: tapo://cloud-password@192.168.1.123?subtype=1 
  # HD stream (default)
  camera5: tapo://cloud-password@192.168.1.123?subtype=0 
```

```bash
echo -n "cloud password" | md5 | awk '{print toupper($0)}'
echo -n "cloud password" | shasum -a 256 | awk '{print toupper($0)}'
```

## TP-Link Kasa

[`new in v1.7.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.7.0)

> [!NOTE]
> This source should be moved to separate module. Because it's source code not related to Tapo.

[TP-Link Kasa](https://www.kasasmart.com/) non-standard protocol [more info](https://medium.com/@hu3vjeen/reverse-engineering-tp-link-kc100-bac4641bf1cd).

- `username` - urlsafe email, `alex@gmail.com` -> `alex%40gmail.com`
- `password` - base64password, `secret1` -> `c2VjcmV0MQ==`

```yaml
streams:
  kc401: kasa://username:password@192.168.1.123:19443/https/stream/mixed
```

Tested: KD110, KC200, KC401, KC420WS, EC71.

## TP-Link Vigi

[`new in v1.9.8`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.9.8)

[TP-Link VIGI](https://www.vigi.com/) cameras. These are cameras from a different sub-brand, but the format is very similar to Tapo. Only the authorization is different. Read more [here](https://github.com/AlexxIT/go2rtc/issues/1470).

```yaml
streams:
  camera1: vigi://admin:{password}@192.168.1.123
```

---

### Overview (`internal/tuya/README.md`)

# Tuya

[`new in v1.9.13`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.9.13) by [@seydx](https://github.com/seydx)

[Tuya](https://www.tuya.com/) is a proprietary camera protocol with **two-way audio** support. go2rtc supports `Tuya Smart API` and `Tuya Cloud API`.

**Tuya Smart API (recommended)**:
- **Smart Life accounts are NOT supported**, you need to create a Tuya Smart account. If the cameras are already added to the Smart Life app, you need to remove them and add them again to the [Tuya Smart](https://play.google.com/store/apps/details?id=com.tuya.smart) app.
- Cameras can be discovered through the go2rtc web interface via Tuya Smart account (Add > Tuya > Select region and fill in email and password > Login).

**Tuya Cloud API**:
- Requires setting up a cloud project in the Tuya Developer Platform.
- Obtain `device_id`, `client_id`, `client_secret`, and `uid` from [Tuya IoT Platform](https://iot.tuya.com/). [Here's a guide](https://xzetsubou.github.io/hass-localtuya/cloud_api/).
- Please ensure that you have subscribed to the `IoT Video Live Stream` service (Free Trial) in the Tuya Developer Platform, otherwise the stream will not work (Tuya Developer Platform > Service API > Authorize > IoT Video Live Stream).

## Configuration

Use the `resolution` parameter to select the stream (not all cameras support an `hd` stream through WebRTC even if the camera supports it):
- `hd` - HD stream (default)
- `sd` - SD stream

```yaml
streams:
  # Tuya Smart API: WebRTC main stream (use Add > Tuya to discover the URL)
  tuya_main:
    - tuya://protect-us.ismartlife.me?device_id=XXX&email=XXX&password=XXX

  # Tuya Smart API: WebRTC sub stream (use Add > Tuya to discover the URL)
  tuya_sub:
    - tuya://protect-us.ismartlife.me?device_id=XXX&email=XXX&password=XXX&resolution=sd

  # Tuya Cloud API: WebRTC main stream
  tuya_webrtc:
   - tuya://openapi.tuyaus.com?device_id=XXX&uid=XXX&client_id=XXX&client_secret=XXX
  
  # Tuya Cloud API: WebRTC sub stream
  tuya_webrtc_sd:
   - tuya://openapi.tuyaus.com?device_id=XXX&uid=XXX&client_id=XXX&client_secret=XXX&resolution=sd
```

---

### Overview (`internal/v4l2/README.md`)

# Video4Linux

[`new in v1.9.9`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.9.9)

What you should to know about [V4L2](https://en.wikipedia.org/wiki/Video4Linux):

- V4L2 (Video for Linux API version 2) works only in Linux
- supports USB cameras and other similar devices
- one device can only be connected to one software simultaneously
- cameras support a fixed list of formats, resolutions and frame rates
- basic cameras supports only RAW (non-compressed) pixel formats
- regular cameras supports MJPEG format (series of JPEG frames)
- advances cameras support H264 format (MSE/MP4, WebRTC compatible)
- using MJPEG and H264 formats (if the camera supports them) won't cost you the CPU usage
- transcoding RAW format to MJPEG or H264 - will cost you a significant CPU usage
- H265 (HEVC) format is also supported (if the camera supports it)

Tests show that the basic Keenetic router with MIPS processor can broadcast three MJPEG cameras in the following resolutions: 1600х1200 + 640х480 + 640х480. The USB bus bandwidth is no more enough for larger resolutions. CPU consumption is no more than 5%.

Supported formats for your camera can be found here: **Go2rtc > WebUI > Add > V4L2**.

## RAW format

Example:

```yaml
streams:
  camera1: v4l2:device?video=/dev/video0&input_format=yuyv422&video_size=1280x720&framerate=10
```

Go2rtc supports built-in transcoding of RAW to MJPEG format. This does not need to be additionally configured.

```
ffplay http://localhost:1984/api/stream.mjpeg?src=camera1
```

**Important.** You don't have to transcode the RAW format to transmit it over the network. You can stream it in `y4m` format, which is perfectly supported by ffmpeg. It won't cost you a CPU usage. But will require high network bandwidth.

```
ffplay http://localhost:1984/api/stream.y4m?src=camera1
```

---

### Overview (`internal/webrtc/README.md`)

# WebRTC

## WebRTC Client

[`new in v1.3.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)

This source type supports four connection formats.

### Creality

[`new in v1.9.10`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.9.10)

[Creality](https://www.creality.com/) 3D printer camera. Read more [here](https://github.com/AlexxIT/go2rtc/issues/1600).

```yaml
streams:
  creality_k2p: webrtc:http://192.168.1.123:8000/call/webrtc_local#format=creality
```

### go2rtc

This format is only supported in go2rtc. Unlike WHEP, it supports asynchronous WebRTC connections and two-way audio.

```yaml
streams:
  webrtc-go2rtc:    webrtc:ws://192.168.1.123:1984/api/ws?src=camera1
```

### Kinesis

[`new in v1.6.1`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.1)

Supports [Amazon Kinesis Video Streams](https://aws.amazon.com/kinesis/video-streams/), using WebRTC protocol. You need to specify the signaling WebSocket URL with all credentials in query params, `client_id` and `ice_servers` list in [JSON format](https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer).

```yaml
streams:
  webrtc-kinesis:   webrtc:wss://...amazonaws.com/?...#format=kinesis#client_id=...#ice_servers=[{...},{...}]
```

**PS.** For `kinesis` sources, you can use [echo](../echo/README.md) to get connection params using `bash`, `python` or any other script language.

### OpenIPC

[`new in v1.7.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.7.0)

Cameras on open-source [OpenIPC](https://openipc.org/) firmware.

```yaml
streams:
  webrtc-openipc:   webrtc:ws://192.168.1.123/webrtc_ws#format=openipc#ice_servers=[{"urls":"stun:stun.kinesisvideo.eu-north-1.amazonaws.com:443"}]
```

### SwitchBot

Support connection to [SwitchBot](https://us.switch-bot.com/) cameras that are based on Kinesis Video Streams. Specifically, this includes [Pan/Tilt Cam Plus 2K](https://us.switch-bot.com/pages/switchbot-pan-tilt-cam-plus-2k) and [Pan/Tilt Cam Plus 3K](https://us.switch-bot.com/pages/switchbot-pan-tilt-cam-plus-3k) and [Smart Video Doorbell](https://www.switchbot.jp/products/switchbot-smart-video-doorbell). `Outdoor Spotlight Cam 1080P`, `Outdoor Spotlight Cam 2K`, `Pan/Tilt Cam`, `Pan/Tilt Cam 2K`, `Indoor Cam` are based on Tuya, so this feature is not available.

```yaml
streams:
  webrtc-switchbot: webrtc:wss://...amazonaws.com/?...#format=switchbot#resolution=hd#play_type=0#client_id=...#ice_servers=[{...},{...}]
```

### WHEP

[WebRTC/WHEP](https://datatracker.ietf.org/doc/draft-murillo-whep/) is replaced by [WebRTC/WISH](https://datatracker.ietf.org/doc/charter-ietf-wish/02/) standard for WebRTC video/audio viewers. But it may already be supported in some third-party software. It is supported in go2rtc.

```yaml
streams:
  webrtc-whep:      webrtc:http://192.168.1.123:1984/api/webrtc?src=camera1
```

### Wyze

[`new in v1.6.1`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.1)

Legacy method to connect to [Wyze](https://www.wyze.com/) cameras using WebRTC protocol via [docker-wyze-bridge](https://github.com/mrlt8/docker-wyze-bridge). For native P2P support without docker-wyze-bridge, see [Source: Wyze](../wyze/README.md).

```yaml
streams:
  webrtc-wyze:      webrtc:http://192.168.1.123:5000/signaling/camera1?kvs#format=wyze
```

## WebRTC Server

What you should know about WebRTC:

- It's almost always a **direct [peer-to-peer](https://en.wikipedia.org/wiki/Peer-to-peer) connection** from your browser to the go2rtc app
- When you use Home Assistant, Frigate, Nginx, Nabu Casa, Cloudflare, and other software, they are only **involved in establishing** the connection; they are **not involved in transferring** media data
- WebRTC media cannot be transferred inside an HTTP connection
- Usually, WebRTC uses random UDP ports on the client and server to establish a connection
- Usually, WebRTC uses public [STUN](https://en.wikipedia.org/wiki/STUN) servers to establish a connection outside the LAN; these servers are only needed to establish a connection and are not involved in data transfer
- Usually, WebRTC will automatically discover all of your local and public addresses and try to establish a connection

If an external connection via STUN is used:

- Uses [UDP hole punching](https://en.wikipedia.org/wiki/UDP_hole_punching) technology to bypass NAT even if you haven't opened your server to the world
- For about 20% of users, the technology will not work because of the [Symmetric NAT](https://tomchen.github.io/symmetric-nat-test/)
- UDP is not suitable for transmitting 2K and 4K high bit rate video over open networks because of the high loss rate:
  - https://habr.com/ru/companies/flashphoner/articles/480006/
  - https://www.youtube.com/watch?v=FXVg2ckuKfs

### Configuration suggestions

- by default, WebRTC uses both TCP and UDP on port 8555 for connections
- you can use this port for external access
- you can change the port in YAML config:

```yaml
webrtc:
  listen: ":8555"  # address of your local server and port (TCP/UDP)
```

#### Static public IP

- forward the port 8555 on your router (you can use the same 8555 port or any other as external port)
- add your external IP address and external port to the YAML config

```yaml
webrtc:
  candidates:
    - 216.58.210.174:8555  # if you have a static public IP address
```

#### Dynamic public IP

- forward the port 8555 on your router (you can use the same 8555 port or any other as the external port)
- add `stun` word and external port to YAML config
    - go2rtc automatically detects your external address with STUN server

```yaml
webrtc:
  candidates:
    - stun:8555  # if you have a dynamic public IP address
```

#### Hard tech way 1. Own TCP-tunnel

If you have a personal [VPS](https://en.wikipedia.org/wiki/Virtual_private_server), you can create a TCP tunnel and setup in the same way as "Static public IP". But use your VPS IP address in the YAML config.

#### Hard tech way 2. Using TURN-server

If you have personal [VPS](https://en.wikipedia.org/wiki/Virtual_private_server), you can install TURN server (e.g. [coturn](https://github.com/coturn/coturn), config [example](https://github.com/AlexxIT/WebRTC/wiki/Coturn-Example)).

```yaml
webrtc:
  ice_servers:
    - urls: [stun:stun.l.google.com:19302]
    - urls: [turn:123.123.123.123:3478]
      username: your_user
      credential: your_pass
```

### Full configuration

**Important!** This example is not for copy/pasting!

```
/* Detailed source-code truncated for AI context efficiency. */
```

By default, go2rtc uses a **fixed TCP** port and **fixed UDP** ports for each **direct** WebRTC connection: `listen: ":8555"`.

You can set a **fixed TCP** port and a **random UDP** port for all connections: `listen: ":8555/tcp"`.

You can also disable the TCP port and leave only random UDP ports: `listen: ""`.

### Configuration filters

**Important!** By default, go2rtc excludes all Docker-like candidates (`172.16.0.0/12`). This cannot be disabled.

Filters allow you to exclude unnecessary candidates. Extra candidates don't make your connection worse or better. But the wrong filter settings can break everything. Skip this setting if you don't understand it.

For example, go2rtc is installed on the host system. And there are unnecessary interfaces. You can keep only the relevant via `interfaces` or `ips` options. You can also exclude IPv6 candidates if your server supports them but your home network does not.

```yaml
webrtc:
  listen: ":8555/tcp"         # use fixed TCP port and random UDP ports
  filters:
    ips: [ 192.168.1.2 ]      # IP-address of your server
    networks: [ udp4, tcp4 ]  # skip IPv6, if it's not supported for you
```

For example, go2rtc is inside a closed Docker container (e.g. [Frigate](https://frigate.video/)). You shouldn't filter Docker interfaces; otherwise, go2rtc won't be able to connect anywhere. But you can filter the Docker candidates because no one can connect to them.

```yaml
webrtc:
  listen: ":8555"                   # use fixed TCP and UDP ports
  candidates: [ 192.168.1.2:8555 ]  # add manual host candidate (use docker port forwarding)
```

## Streaming ingest

### Ingest: Browser

[`new in v1.3.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)

You can turn the browser of any PC or mobile into an IP camera with support for video and two-way audio. Or even broadcast your PC screen:

1. Create empty stream in the `go2rtc.yaml`
2. Go to go2rtc WebUI
3. Open `links` page for your stream
4. Select `camera+microphone` or `display+speaker` option
5. Open `webrtc` local page (your go2rtc **should work over HTTPS!**) or `share link` via [WebTorrent](../webtorrent/README.md) technology (work over HTTPS by default)

### Ingest: WHIP

[`new in v1.3.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)

You can use **OBS Studio** or any other broadcast software with [WHIP](https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html) protocol support. This standard has not yet been approved. But you can download OBS Studio [dev version](https://github.com/obsproject/obs-studio/actions/runs/3969201209):

- Settings > Stream > Service: WHIP > `http://192.168.1.123:1984/api/webrtc?dst=camera1`

## Useful links

- https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html
- https://www.ietf.org/id/draft-murillo-whep-01.html
- https://github.com/Glimesh/broadcast-box/
- https://github.com/obsproject/obs-studio/pull/7926
- https://misi.github.io/webrtc-c0d3l4b/
- https://github.com/webtorrent/webtorrent/blob/master/docs/faq.md

---

### Overview (`internal/webtorrent/README.md`)

# WebTorrent

> [!NOTE]
> This section needs some improvement.

## WebTorrent Client

[`new in v1.3.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)

This source can get a stream from another go2rtc via [WebTorrent](https://en.wikipedia.org/wiki/WebTorrent) protocol.

### Client Configuration

```yaml
streams:
  webtorrent1: webtorrent:?share=huofssuxaty00izc&pwd=k3l2j9djeg8v8r7e
```

## WebTorrent Server

[`new in v1.3.0`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)

This module supports:

- Share any local stream via [WebTorrent](https://webtorrent.io/) technology
- Get any [incoming stream](../webrtc/README.md#ingest-browser) from PC or mobile via [WebTorrent](https://webtorrent.io/) technology
- Get any remote go2rtc source via [WebTorrent](https://webtorrent.io/) technology

Securely and freely. You do not need to open a public access to the go2rtc server. But in some cases (Symmetric NAT), you may need to set up external access to [WebRTC module](../webrtc/README.md).

To generate a sharing link or incoming link, go to the go2rtc WebUI (stream links page). This link is **temporary** and will stop working after go2rtc is restarted!

### Server Configuration

You can create permanent external links in the go2rtc config:

```yaml
webtorrent:
  shares:
    super-secret-share:  # share name, should be unique among all go2rtc users!
      pwd: super-secret-password
      src: rtsp-dahua1   # stream name from streams section
```

Link example: `https://go2rtc.org/webtorrent/#share=02SNtgjKXY&pwd=wznEQqznxW&media=video+audio`

---

### Overview (`internal/wyoming/README.md`)

# Wyoming

> [!NOTE]
> The format is under development and does not yet work stably.

This module provide [Wyoming Protocol](https://www.home-assistant.io/integrations/wyoming/) support to create local voice assistants using [Home Assistant](https://www.home-assistant.io/).

- go2rtc can act as [Wyoming Satellite](https://github.com/rhasspy/wyoming-satellite)
- go2rtc can act as [Wyoming External Microphone](https://github.com/rhasspy/wyoming-mic-external)
- go2rtc can act as [Wyoming External Sound](https://github.com/rhasspy/wyoming-snd-external)
- any supported audio source with PCM codec can be used as audio input
- any supported two-way audio source with PCM codec can be used as audio output
- any desktop/server microphone/speaker can be used as two-way audio source
  - supported any OS via FFmpeg or any similar software
  - supported Linux via alsa source
- you can change the behavior using the built-in scripting engine

## Typical Voice Pipeline

1. Audio stream (MIC)
   - any audio source with PCM codec support (include PCMA/PCMU)
2. Voice Activity Detector (VAD)
3. Wake Word (WAKE)
   - [OpenWakeWord](https://www.home-assistant.io/voice_control/create_wake_word/)
4. Speech-to-Text (STT)
   - [Whisper](https://github.com/home-assistant/addons/blob/master/whisper/) 
   - [Vosk](https://github.com/rhasspy/hassio-addons/blob/master/vosk/)
5. Conversation agent (INTENT)
   - [Home Assistant](https://www.home-assistant.io/integrations/conversation/)
6. Text-to-speech (TTS)
   - [Google Translate](https://www.home-assistant.io/integrations/google_translate/)
   - [Piper](https://github.com/home-assistant/addons/blob/master/piper/)
7. Audio stream (SND)
   - any source with two-way audio (backchannel) and PCM codec support (include PCMA/PCMU)

You can use a large number of different projects for WAKE, STT, INTENT and TTS thanks to the Home Assistant.

And you can use a large number of different technologies for MIC and SND thanks to Go2rtc.

## Configuration

You can optionally specify WAKE service. So go2rtc will start transmitting audio to Home Assistant only after WAKE word. If the WAKE service cannot be connected to or not specified - go2rtc will pass all audio to Home Assistant. In this case WAKE service must be configured in your Voice Assistant pipeline.

You can optionally specify VAD threshold. So go2rtc will start transmitting audio to WAKE service only after some audio noise.

Your stream must support audio transmission in PCM codec (include PCMA/PCMU).

```yaml
wyoming:
  stream_name_from_streams_section:
    listen: :10700 
    name: "My Satellite"                # optional name
    wake_uri: tcp://192.168.1.23:10400  # optional WAKE service
    vad_threshold: 1                    # optional VAD threshold (from 0.1 to 3.5)
```

Home Assistant -> Settings -> Integrations -> Add -> Wyoming Protocol -> Host + Port from `go2rtc.yaml`

Select one or multiple wake words:
```yaml
wake_uri: tcp://192.168.1.23:10400?name=alexa_v0.1&name=hey_jarvis_v0.1&name=hey_mycroft_v0.1&name=hey_rhasspy_v0.1&name=ok_nabu_v0.1
```

## Events

You can add wyoming event handling using the [expr](../expr/README.md) language. For example, to pronounce TTS on some media player from HA.

Turn on the logs to see what kind of events happens.

This is what the default scripts look like:

```yaml
wyoming:
  script_example:
    event:
      run-satellite: Detect()
      pause-satellite: Stop()
      voice-stopped: Pause()
      audio-stop: PlayAudio() && WriteEvent("played") && Detect()
      error: Detect()
      internal-run: WriteEvent("run-pipeline", '{"start_stage":"wake","end_stage":"tts"}') && Stream()
      internal-detection: WriteEvent("run-pipeline", '{"start_stage":"asr","end_stage":"tts"}') && Stream()
```

Supported functions and variables:

- `Detect()` - start the VAD and WAKE word detection process
- `Stream()` - start transmission of audio data to the client (Home Assistant)
- `Stop()` - stop and disconnect stream without disconnecting client (Home Assistant)
- `Pause()` - temporary pause of audio transfer, without disconnecting the stream
- `PlayAudio()` - playing the last audio that was sent from client (Home Assistant)
- `WriteEvent(type, data)` - send event to client (Home Assistant)
- `Sleep(duration)` - temporary script pause (ex. `Sleep('1.5s')`)
- `PlayFile(path)` - play audio from `wav` file
- `Type` - type (name) of event
- `Data` - event data in JSON format (ex. `{"text":"how are you"}`)
- also available other functions from [expr](../expr/README.md) module (ex. `fetch`)

If you write a script for an event - the default action is no longer executed. You need to repeat the necessary steps yourself.

In addition to the standard events, there are two additional events:

- `internal-run` - called after `Detect()` when VAD detected, but WAKE service unavailable
- `internal-detection` - called after `Detect()` when WAKE word detected

**Example 1.** You want to play a sound file when a wake word detected (only `wav` supported):

- `PlayFile` and `PlayAudio` functions are executed synchronously, the following steps will be executed only after they are completed

```yaml
wyoming:
  script_example:
    event:
      internal-detection: PlayFile('/media/beep.wav') && WriteEvent("run-pipeline", '{"start_stage":"asr","end_stage":"tts"}') && Stream()
```

**Example 2.** You want to play TTS on a Home Assistant media player:

Each event has a `Type` and `Data` in JSON format. You can use their values in scripts.

- in the `synthesize` step, we get the value of the `text` and call the HA REST API
- in the `audio-stop` step we get the duration of the TTS in seconds, wait for this time and start the pipeline again

```yaml
wyoming:
  script_example:
    event:
      synthesize: |
        let text = fromJSON(Data).text;
        let token = 'eyJhbGci...';
        fetch('http://localhost:8123/api/services/tts/speak', {
          method: 'POST',
          headers: {'Authorization': 'Bearer '+token,'Content-Type': 'application/json'},
          body: toJSON({
            entity_id: 'tts.google_translate_com',
            media_player_entity_id: 'media_player.google_nest',
            message: text,
            language: 'en',
          }),
        }).ok
      audio-stop: |
        let timestamp = fromJSON(Data).timestamp;
        let delay = string(timestamp)+'s';
        Sleep(delay) && WriteEvent("played") && Detect()
```

## Config examples

Satellite on Windows server using FFmpeg and FFplay.

```yaml
streams:
  satellite_win:
    - exec:ffmpeg -hide_banner -f dshow -i "audio=Microphone (High Definition Audio Device)" -c pcm_s16le -ar 16000 -ac 1 -f wav -
    - exec:ffplay -hide_banner -nodisp -probesize 32 -f s16le -ar 22050 -#backchannel=1#audio=s16le/22050

wyoming:
  satellite_win:
    listen: :10700
    name: "Windows Satellite"
    wake_uri: tcp://192.168.1.23:10400
    vad_threshold: 1
```

Satellite on Dahua camera with two-way audio support.

```yaml
streams:
  dahua_camera:
    - rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif

wyoming:
  dahua_camera:
    listen: :10700
    name: "Dahua Satellite"
    wake_uri: tcp://192.168.1.23:10400
    vad_threshold: 1
```

Satellite on external wyoming Microphone and Sound.

```yaml
streams:
  wyoming_external:
     - wyoming://192.168.1.23:10600                # wyoming-mic-external
     - wyoming://192.168.1.23:10601?backchannel=1  # wyoming-snd-external

wyoming:
   wyoming_external:
    listen: :10700
    name: "Wyoming Satellite"
    wake_uri: tcp://192.168.1.23:10400
    vad_threshold: 1
```

## Wyoming External Microphone and Sound

Advanced users, who want to enjoy the [Wyoming Satellite](https://github.com/rhasspy/wyoming-satellite) project, can use go2rtc as a [Wyoming External Microphone](https://github.com/rhasspy/wyoming-mic-external) or [Wyoming External Sound](https://github.com/rhasspy/wyoming-snd-external).

**go2rtc.yaml**

```yaml
streams:
  wyoming_mic_external:
    - exec:ffmpeg -hide_banner -f dshow -i "audio=Microphone (High Definition Audio Device)" -c pcm_s16le -ar 16000 -ac 1 -f wav -
  wyoming_snd_external:
    - exec:ffplay -hide_banner -nodisp -probesize 32 -f s16le -ar 22050 -#backchannel=1#audio=s16le/22050

wyoming:
  wyoming_mic_external:
    listen: :10600
    mode: mic
  wyoming_snd_external:
    listen: :10601
    mode: snd
```

**docker-compose.yml**

```yaml
version: "3.8"
services:
  satellite:
    build: wyoming-satellite  # https://github.com/rhasspy/wyoming-satellite
    ports:
      - "10700:10700"
    command:
      - "--name"
      - "my satellite"
      - "--mic-uri"
      - "tcp://192.168.1.23:10600"
      - "--snd-uri"
      - "tcp://192.168.1.23:10601"
      - "--debug"
```

## Wyoming External Source

**go2rtc.yaml**

```yaml
streams:
  wyoming_external:
    - wyoming://192.168.1.23:10600
    - wyoming://192.168.1.23:10601?backchannel=1
```

**docker-compose.yml**

```yaml
version: "3.8"
services:
   microphone:
      build: wyoming-mic-external  # https://github.com/rhasspy/wyoming-mic-external
      ports:
         - "10600:10600"
      devices:
         - /dev/snd:/dev/snd
      group_add:
         - audio
      command:
         - "--device"
         - "sysdefault"
         - "--debug"
   playback:
      build: wyoming-snd-external  # https://github.com/rhasspy/wyoming-snd-external
      ports:
         - "10601:10601"
      devices:
         - /dev/snd:/dev/snd
      group_add:
         - audio
      command:
         - "--device"
         - "sysdefault"
         - "--debug"
```

## Debug

```yaml
log:
  wyoming: trace
```

---

### Overview (`internal/wyze/README.md`)

# Wyze

[`new in v1.9.14`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.9.14) by [@seydx](https://github.com/seydx)

This source allows you to stream from [Wyze](https://wyze.com/) cameras using native P2P protocol without the Wyze app or SDK.

**Important:**

1. **Requires Wyze account**. You need to login once via the WebUI to load your cameras.
2. **Requires firmware with DTLS**. Only cameras with DTLS-enabled firmware are supported.
3. Internet access is only needed when loading cameras from your account. After that, all streaming is local P2P.
4. Connection to the camera is local only (direct P2P to camera IP).

**Features:**

- H.264 and H.265 video codec support
- AAC, G.711, PCM, and Opus audio codec support
- Two-way audio (intercom) support
- Resolution switching (HD/SD)

## Setup

1. Get your API Key from [Wyze Developer Portal](https://support.wyze.com/hc/en-us/articles/16129834216731)
2. Go to go2rtc WebUI > Add > Wyze
3. Enter your API ID, API Key, email, and password
4. Select cameras to add - stream URLs are generated automatically

**Example Config**

```yaml
wyze:
  user@email.com:
    api_id: "your-api-id"
    api_key: "your-api-key"
    password: "yourpassword"    # or MD5 triple-hash with "md5:" prefix

streams:
  wyze_cam: wyze://192.168.1.123?uid=WYZEUID1234567890AB&enr=xxx&mac=AABBCCDDEEFF&model=HL_CAM4&dtls=true
```

## Stream URL Format

The stream URL is automatically generated when you add cameras via the WebUI:

```
wyze://[IP]?uid=[P2P_ID]&enr=[ENR]&mac=[MAC]&model=[MODEL]&subtype=[hd|sd]&dtls=true
```

| Parameter | Description                                     |
|-----------|-------------------------------------------------|
| `IP`      | Camera's local IP address                       |
| `uid`     | P2P identifier (20 chars)                       |
| `enr`     | Encryption key for DTLS                         |
| `mac`     | Device MAC address                              |
| `model`   | Camera model (e.g., HL_CAM4)                    |
| `dtls`    | Enable DTLS encryption (default: true)          |
| `subtype` | Camera resolution: `hd` or `sd` (default: `hd`) |

## Configuration

### Resolution

You can change the camera's resolution using the `subtype` parameter:

```yaml
streams:
  wyze_hd: wyze://...&subtype=hd
  wyze_sd: wyze://...&subtype=sd
```

### Two-Way Audio

Two-way audio (intercom) is supported automatically. When a consumer sends audio to the stream, it will be transmitted to the camera's speaker.

## Camera Compatibility

| Name                        | Model          | Firmware     | Protocol | Encryption | Codecs     |
|-----------------------------|----------------|--------------|----------|------------|------------|
| Wyze Cam v4                 | HL_CAM4        | 4.52.9.4188  | TUTK     | TransCode  | h264, aac  |
|                             |                | 4.52.9.5332  | TUTK     | HMAC-SHA1  | h264, aac  |
| Wyze Cam v3 Pro             |                |              | TUTK     |            |            |
| Wyze Cam v3                 | WYZE_CAKP2JFUS | 4.36.14.3497 | TUTK     | TransCode  | h264, pcm  |
| Wyze Cam v2                 | WYZEC1-JZ      | 4.9.9.3006   | TUTK     | TransCode  | h264, pcmu |
| Wyze Cam v1                 |                |              | TUTK     |            |            |
| Wyze Cam Pan v4             |                |              | Gwell*   |            |            |
| Wyze Cam Pan v3             |                |              | TUTK     |            |            |
| Wyze Cam Pan v2             |                |              | TUTK     |            |            |
| Wyze Cam Pan v1             |                |              | TUTK     |            |            |
| Wyze Cam OG                 |                |              | Gwell*   |            |            |
| Wyze Cam OG Telephoto       |                |              | Gwell*   |            |            |
| Wyze Cam OG (2025)          |                |              | Gwell*   |            |            |
| Wyze Cam Outdoor v2         |                |              | TUTK     |            |            |
| Wyze Cam Outdoor v1         |                |              | TUTK     |            |            |
| Wyze Cam Floodlight Pro     |                |              | ?        |            |            |
| Wyze Cam Floodlight v2      |                |              | TUTK     |            |            |
| Wyze Cam Floodlight         |                |              | TUTK     |            |            |
| Wyze Video Doorbell v2      | HL_DB2         | 4.51.3.4992  | TUTK     | TransCode  | h264, pcm  |
| Wyze Video Doorbell v1      |                |              | TUTK     |            |            |
| Wyze Video Doorbell Pro     |                |              | ?        |            |            |
| Wyze Battery Video Doorbell |                |              | ?        |            |            |
| Wyze Duo Cam Doorbell       |                |              | ?        |            |            |
| Wyze Battery Cam Pro        |                |              | ?        |            |            |
| Wyze Solar Cam Pan          |                |              | ?        |            |            |
| Wyze Duo Cam Pan            |                |              | ?        |            |            |
| Wyze Window Cam             |                |              | ?        |            |            |
| Wyze Bulb Cam               |                |              | ?        |            |            |

_* Gwell based protocols are not yet supported._

---

### Overview (`internal/xiaomi/README.md`)

# Xiaomi Mi Home

[`new in v1.9.13`](https://github.com/AlexxIT/go2rtc/releases/tag/v1.9.13)

This source allows you to view cameras from the [Xiaomi Mi Home](https://home.mi.com/) ecosystem.

Since 2020, Xiaomi has introduced a unified protocol for cameras called `miss`. I think it means **Mi Secure Streaming**. Until this point, the camera protocols were in chaos. Almost every model had different authorization, encryption, command lists, and media packet formats.

go2rtc supports two formats: `xiaomi/mess` and `xiaomi/legacy`.
And multiple P2P protocols: `cs2+udp`, `cs2+tcp`, several versions of `tutk+udp`.

Almost all cameras in the `xiaomi/mess` format and the `cs2` protocol work well.
Older `xiaomi/legacy` format cameras may have support issues.
The `tutk` protocol is the worst thing that's ever happened to the P2P world. It works terribly.

**Important:**

1. **Not all cameras are supported**. The list of supported cameras is collected in [this issue](https://github.com/AlexxIT/go2rtc/issues/1982).
2. Each time you connect to the camera, you need Internet access to obtain encryption keys.
3. Connection to the camera is local only.

**Features:**

- Multiple Xiaomi accounts supported
- Cameras from multiple regions are supported for a single account
- Two-way audio is supported
- Cameras with multiple lenses are supported

## Setup

1. Go to go2rtc WebUI > Add > Xiaomi > Login with username and password
2. Receive verification code by email or phone if required.
3. Complete the captcha if required.
4. If everything is OK, your account will be added, and you can load cameras from it.

**Example**

```yaml
xiaomi:
  1234567890: V1:***

streams:
  xiaomi1: xiaomi://1234567890:cn@192.168.1.123?did=9876543210&model=isa.camera.hlc7
```

## Configuration

Quality in the `miss` protocol is specified by a number from 0 to 5. Usually 0 means auto, 1 - sd, 2 - hd.
Go2rtc by default sets quality to 2. But some new cameras have HD quality at number 3.
Old cameras may have broken codec settings at number 3, so this number should not be set for all cameras.

You can change camera quality: `subtype=hd/sd/auto/0-5`.

```yaml
streams:
  xiaomi1: xiaomi://***&subtype=sd
```

You can use a second channel for dual cameras: `channel=2`.

```yaml
streams:
  xiaomi1: xiaomi://***&channel=2
```

---

### Overview (`internal/yandex/README.md`)

# Yandex

Source for receiving stream from new [Yandex IP camera](https://alice.yandex.ru/smart-home/security/ipcamera).

## Get Yandex token

1. Install HomeAssistant integration [YandexStation](https://github.com/AlexxIT/YandexStation).
2. Copy token from HomeAssistant config folder: `/config/.storage/core.config_entries`, key: `"x_token"`.

## Get device ID

1. Open this link in any browser: https://iot.quasar.yandex.ru/m/v3/user/devices
2. Copy ID of your camera, key: `"id"`.

## Configuration

```yaml
streams:
  yandex_stream: yandex:?x_token=XXXX&device_id=XXXX
  yandex_snapshot: yandex:?x_token=XXXX&device_id=XXXX&snapshot
  yandex_snapshot_custom_size: yandex:?x_token=XXXX&device_id=XXXX&snapshot=h=540
```

---

### Overview (`pkg/aac/README.md`)

## AAC-LD and AAC-ELD

| Codec   | Rate  | QuickTime | ffmpeg | VLC |
|---------|-------|-----------|--------|-----|
| AAC-LD  | 8000  | yes       | no     | no  |
| AAC-LD  | 16000 | yes       | no     | no  |
| AAC-LD  | 22050 | yes       | yes    | no  |
| AAC-LD  | 24000 | yes       | yes    | no  |
| AAC-LD  | 32000 | yes       | yes    | no  |
| AAC-ELD | 8000  | yes       | no     | no  |
| AAC-ELD | 16000 | yes       | no     | no  |
| AAC-ELD | 22050 | yes       | yes    | yes |
| AAC-ELD | 24000 | yes       | yes    | yes |
| AAC-ELD | 32000 | yes       | yes    | yes |

## Useful links

- [4.6.20 Enhanced Low Delay Codec](https://csclub.uwaterloo.ca/~ehashman/ISO14496-3-2009.pdf)
- https://stackoverflow.com/questions/40014508/aac-adts-for-aacobject-eld-packets
- https://code.videolan.org/videolan/vlc/-/blob/master/modules/packetizer/mpeg4audio.c

---

### Overview (`pkg/alsa/README.md`)

## Build

```shell
x86_64-linux-gnu-gcc -w -static asound_arch.c -o asound_amd64
i686-linux-gnu-gcc -w -static asound_arch.c -o asound_i386
aarch64-linux-gnu-gcc -w -static asound_arch.c -o asound_arm64
arm-linux-gnueabihf-gcc -w -static asound_arch.c -o asound_arm
mipsel-linux-gnu-gcc -w -static asound_arch.c -o asound_mipsle -D_TIME_BITS=32
```

## Useful links

- https://github.com/torvalds/linux/blob/master/include/uapi/sound/asound.h
- https://github.com/yobert/alsa
- https://github.com/Narsil/alsa-go
- https://github.com/alsa-project/alsa-lib
- https://github.com/anisse/alsa
- https://github.com/tinyalsa/tinyalsa

**Broken pipe**

- https://stackoverflow.com/questions/26545139/alsa-cannot-recovery-from-underrun-prepare-failed-broken-pipe
- https://klipspringer.avadeaux.net/alsa-broken-pipe-errors/

---

### Overview (`pkg/ascii/README.md`)

## Useful links

- https://en.wikipedia.org/wiki/ANSI_escape_code
- https://paulbourke.net/dataformats/asciiart/
- https://github.com/kutuluk/xterm-color-chart
- https://github.com/hugomd/parrot.live

---

### Overview (`pkg/core/README.md`)

## PCM

**RTSP**

- PayloadType=10 - L16/44100/2 - Linear PCM 16-bit big endian
- PayloadType=11 - L16/44100/1 - Linear PCM 16-bit big endian

https://en.wikipedia.org/wiki/RTP_payload_formats

**Apple QuickTime**

- `raw` - 16-bit data is stored in little endian format
- `twos` - 16-bit data is stored in big endian format
- `sowt` - 16-bit data is stored in little endian format
- `in24` - denotes 24-bit, big endian
- `in32` - denotes 32-bit, big endian
- `fl32` - denotes 32-bit floating point PCM
- `fl64` - denotes 64-bit floating point PCM
- `alaw` - denotes A-law logarithmic PCM
- `ulaw` - denotes mu-law logarithmic PCM

https://wiki.multimedia.cx/index.php/PCM

**FFmpeg RTSP**

```
pcm_s16be, 44100 Hz, stereo => 10
pcm_s16be, 48000 Hz, stereo => 96 L16/48000/2
pcm_s16be, 44100 Hz, mono   => 11

pcm_s16le, 48000 Hz, stereo => 96 (b=AS:1536)
pcm_s16le, 44100 Hz, stereo => 96 (b=AS:1411)
pcm_s16le, 16000 Hz, stereo => 96 (b=AS:512)
pcm_s16le, 8000 Hz, stereo  => 96 (b=AS:256)

pcm_s16le, 48000 Hz, mono   => 96 (b=AS:768)
pcm_s16le, 44100 Hz, mono   => 96 (b=AS:705)
pcm_s16le, 16000 Hz, mono   => 96 (b=AS:256)
pcm_s16le, 8000 Hz, mono    => 96 (b=AS:128)
```

---

### Overview (`pkg/creds/README.md`)

# Credentials

This module allows you to get variables:

- from custom storage (ex. config file)
- from [credential files](https://systemd.io/CREDENTIALS/)
- from environment variables

---

### Overview (`pkg/ffmpeg/README.md`)

## FFplay output

[FFplay](https://stackoverflow.com/questions/27778678/what-are-mv-fd-aq-vq-sq-and-f-in-a-video-stream) `7.11 A-V:  0.003 fd=   1 aq=   21KB vq=  321KB sq=    0B f=0/0`:

- `7.11` - master clock, is the time from start of the stream/video
- `A-V` - av_diff, difference between audio and video timestamps
- `fd` - frames dropped
- `aq` - audio queue (0 - no delay)
- `vq` - video queue (0 - no delay)
- `sq` - subtitle queue
- `f` - timestamp error correction rate (Not 100% sure)

`M-V`, `M-A` means video stream only, audio stream only respectively.

## Devices Windows

```
>ffmpeg -hide_banner -f dshow -list_options true -i video="VMware Virtual USB Video Device"
[dshow @ 0000025695e52900] DirectShow video device options (from video devices)
[dshow @ 0000025695e52900]  Pin "Record" (alternative pin name "0")
[dshow @ 0000025695e52900]   pixel_format=yuyv422  min s=1280x720 fps=1 max s=1280x720 fps=10
[dshow @ 0000025695e52900]   pixel_format=yuyv422  min s=1280x720 fps=1 max s=1280x720 fps=10 (tv, bt470bg/bt709/unknown, topleft)
[dshow @ 0000025695e52900]   pixel_format=nv12  min s=1280x720 fps=1 max s=1280x720 fps=23
[dshow @ 0000025695e52900]   pixel_format=nv12  min s=1280x720 fps=1 max s=1280x720 fps=23 (tv, bt470bg/bt709/unknown, topleft)
```

## Devices Mac

```
% ./ffmpeg -hide_banner -f avfoundation -list_devices true -i ""
[AVFoundation indev @ 0x7f8b1f504d80] AVFoundation video devices:
[AVFoundation indev @ 0x7f8b1f504d80] [0] FaceTime HD Camera
[AVFoundation indev @ 0x7f8b1f504d80] [1] Capture screen 0
[AVFoundation indev @ 0x7f8b1f504d80] AVFoundation audio devices:
[AVFoundation indev @ 0x7f8b1f504d80] [0] Soundflower (2ch)
[AVFoundation indev @ 0x7f8b1f504d80] [1] Built-in Microphone
[AVFoundation indev @ 0x7f8b1f504d80] [2] Soundflower (64ch)
```

## Devices Linux

```
# ffmpeg -hide_banner -f v4l2 -list_formats all -i /dev/video0
[video4linux2,v4l2 @ 0x7f7de7c58bc0] Raw       :     yuyv422 :           YUYV 4:2:2 : 640x480 160x120 176x144 320x176 320x240 352x288 432x240 544x288 640x360 752x416 800x448 800x600 864x480 960x544 960x720 1024x576 1184x656 1280x720 1280x960
[video4linux2,v4l2 @ 0x7f7de7c58bc0] Compressed:       mjpeg :          Motion-JPEG : 640x480 160x120 176x144 320x176 320x240 352x288 432x240 544x288 640x360 752x416 800x448 800x600 864x480 960x544 960x720 1024x576 1184x656 1280x720 1280x960
```

## TTS

```yaml
streams:
  tts: ffmpeg:#input=-readrate 1 -readrate_initial_burst 0.001 -f lavfi -i "flite=text='1 2 3 4 5 6 7 8 9 0'"#audio=pcma
```

## Useful links

- https://superuser.com/questions/564402/explanation-of-x264-tune
- https://stackoverflow.com/questions/33624016/why-sliced-thread-affect-so-much-on-realtime-encoding-using-ffmpeg-x264
- https://codec.fandom.com/ru/wiki/X264_-_описание_ключей_кодирования
- https://html5test.com/
- https://trac.ffmpeg.org/wiki/Capture/Webcam
- https://trac.ffmpeg.org/wiki/DirectShow
- https://stackoverflow.com/questions/53207692/libav-mjpeg-encoding-and-huffman-table
- https://github.com/tuupola/esp_video/blob/master/README.md
- https://github.com/leandromoreira/ffmpeg-libav-tutorial
- https://www.reddit.com/user/VeritablePornocopium/comments/okw130/ffmpeg_with_libfdk_aac_for_windows_x64/
- https://slhck.info/video/2017/02/24/vbr-settings.html
- [HomeKit audio samples problem](https://superuser.com/questions/1290996/non-monotonous-dts-with-igndts-flag)

---

### Overview (`pkg/h264/README.md`)

# H264

Payloader code taken from [pion](https://github.com/pion/rtp) library and changed to AVC packets support.

## Useful Links

- [RTP Payload Format for H.264 Video](https://datatracker.ietf.org/doc/html/rfc6184)
- [The H264 Sequence parameter set](https://www.cardinalpeak.com/blog/the-h-264-sequence-parameter-set)
- [H.264 Video Types (Microsoft)](https://docs.microsoft.com/en-us/windows/win32/directshow/h-264-video-types)
- [Automatic Generation of H.264 Parameter Sets to Recover Video File Fragments](https://arxiv.org/pdf/2104.14522.pdf)
- [Chromium sources](https://chromium.googlesource.com/external/webrtc/+/HEAD/common_video/h264)
- [AVC levels](https://en.wikipedia.org/wiki/Advanced_Video_Coding#Levels)
- [AVC profiles table](https://developer.mozilla.org/ru/docs/Web/Media/Formats/codecs_parameter)
- [Supported Media for Google Cast](https://developers.google.com/cast/docs/media)
- [Two stream formats, Annex-B, AVCC (H.264) and HVCC (H.265)](https://www.programmersought.com/article/3901815022/)
- https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/producer-reference-nal.html

---

### Overview (`pkg/h265/README.md`)

# H265

Payloader code taken from [pion](https://github.com/pion/rtp) library branch [h265](https://github.com/pion/rtp/tree/h265), because it's still not in release. Thanks to [@kevmo314](https://github.com/kevmo314).

## Useful links

- https://datatracker.ietf.org/doc/html/rfc7798
- [Add initial support for WebRTC HEVC](https://trac.webkit.org/changeset/259452/webkit)

---

### Overview (`pkg/hap/README.md`)

# Home Accessory Protocol

> PS. Character = Characteristic

**Device** - HomeKit end device (swith, camera, etc)

- mDNS name: `MyCamera._hap._tcp.local.`
- DeviceID - mac-like: `0E:AA:CE:2B:35:71`
- HomeKit device is described by:
  - one or more `Accessories` - has `AID` and `Services`  
  - `Services` - has `IID`, `Type` and `Characters`  
  - `Characters` - has `IID`, `Type`, `Format` and `Value`

**Client** - HomeKit client (iPhone, iPad, MacBook or opensource library)

- ClientID - static random UUID
- ClientPublic/ClientPrivate - static random 32 byte keypair
- can pair with Device (exchange ClientID/ClientPublic, ServerID/ServerPublic using Pin)
- can auth to Device using ClientPrivate
- holding persistant Secure connection to device
- can read device Accessories
- can read and write device Characters
- can subscribe on device Characters change (Event)

**Server** - HomeKit server (soft on end device or opensource library)

- ServerID - same as DeviceID (using for Client auth)
- ServerPublic/ServerPrivate - static random 32 byte keypair

## AAC ELD 

Requires ffmpeg built with `--enable-libfdk-aac`

```
-acodec libfdk_aac -aprofile aac_eld 
```

| SampleRate | RTPTime | constantDuration   | objectType   |
|------------|---------|--------------------|--------------|
| 8000       | 60      | =8000/1000*60=480  | 39 (AAC ELD) |
| 16000      | 30      | =16000/1000*30=480 | 39 (AAC ELD) |
| 24000      | 20      | =24000/1000*20=480 | 39 (AAC ELD) |
| 16000      | 60      | =16000/1000*60=960 | 23 (AAC LD)  |
| 24000      | 40      | =24000/1000*40=960 | 23 (AAC LD)  |

## Useful links

- https://github.com/apple/HomeKitADK/blob/master/Documentation/crypto.md
- https://github.com/apple/HomeKitADK/blob/master/HAP/HAPPairingPairSetup.c
- [Extracting HomeKit Pairing Keys](https://pvieito.com/2019/12/extract-homekit-pairing-keys)
- [HAP in AirPlay2 receiver](https://github.com/openairplay/airplay2-receiver/blob/master/ap2/pairing/hap.py)
- [HomeKit Secure Video Unofficial Specification](https://github.com/Supereg/secure-video-specification)
- [Homebridge Camera FFmpeg](https://sunoo.github.io/homebridge-camera-ffmpeg/configs/)
- https://github.com/ljezny/Particle-HAP/blob/master/HAP-Specification-Non-Commercial-Version.pdf

---

### Overview (`pkg/ioctl/README.md`)

# IOCTL

This is just an example how Linux IOCTL constants works.

---

### Overview (`pkg/mdns/README.md`)

# Useful links

- https://grouper.ieee.org/groups/1722/contributions/2009/Bonjour%20Device%20Discovery.pdf

---

### Overview (`pkg/mjpeg/README.md`)

## Useful links

- https://www.rfc-editor.org/rfc/rfc2435
- https://github.com/GStreamer/gst-plugins-good/blob/master/gst/rtp/gstrtpjpegdepay.c
- https://mjpeg.sanford.io/

---

### Overview (`pkg/mp4/README.md`)

## Fragmented MP4

```
ffmpeg -i "rtsp://..." -movflags +frag_keyframe+separate_moof+default_base_moof+empty_moov -frag_duration 1 -c copy -t 5 sample.mp4
```

- movflags frag_keyframe 
  Start a new fragment at each video keyframe.
- frag_duration duration
  Create fragments that are duration microseconds long.
- movflags separate_moof
  Write a separate moof (movie fragment) atom for each track.
- movflags default_base_moof
  Similarly to the omit_tfhd_offset, this flag avoids writing the absolute base_data_offset field in tfhd atoms, but does so by using the new default-base-is-moof flag instead.

https://ffmpeg.org/ffmpeg-formats.html#Options-13

## HEVC

| Browser     | avc1 | hvc1 | hev1 |
|-------------|------|------|------|
 | Mac Chrome  | +    | -    | +    |
 | Mac Safari  | +    | +    | -    |
 | iOS 15?     | +    | +    | -    |
 | Mac Firefox | +    | -    | -    |
 | iOS 12      | +    | -    | -    |
 | Android 13  | +    | -    | -    |

## Useful links

- https://stackoverflow.com/questions/63468587/what-hevc-codec-tag-to-use-with-fmp4-hvc1-or-hev1
- https://stackoverflow.com/questions/32152090/encode-h265-to-hvc1-codec
- https://jellyfin.org/docs/general/clients/codec-support.html
- https://github.com/StaZhu/enable-chromium-hevc-hardware-decoding
- https://developer.mozilla.org/ru/docs/Web/Media/Formats/codecs_parameter
- https://gstreamer-devel.narkive.com/rhkUolp2/rtp-dts-pts-result-in-varying-mp4-frame-durations

---

### Overview (`pkg/mpegts/README.md`)

## PTS/DTS/CTS

```
if DTS == 0 {
    // for I and P frames
	packet.Timestamp = PTS (presentation time)
} else {
    // for B frames
    packet.Timestamp = DTS (decode time)
    CTS = PTS-DTS (composition time)
}
```

- MPEG-TS container uses PTS and optional DTS.
- MP4 container uses DTS and CTS
- RTP container uses PTS

## MPEG-TS

FFmpeg:
- PMTID=4096
- H264: PESID=256, StreamType=27, StreamID=224
- H265: PESID=256, StreamType=36, StreamID=224
- AAC: PESID=257, StreamType=15, StreamID=192

Tapo:
- PMTID=18
- H264: PESID=68, StreamType=27, StreamID=224
- AAC: PESID=69, StreamType=144, StreamID=192

## Useful links

- https://github.com/theREDspace/video-onboarding/blob/main/MPEGTS%20Knowledge.md
- https://en.wikipedia.org/wiki/MPEG_transport_stream
- https://en.wikipedia.org/wiki/Program-specific_information

---

### Overview (`pkg/onvif/README.md`)

## Profiles

- Profile A - For access control configuration
- Profile C - For door control and event management
- Profile S - For basic video streaming
  - Video streaming and configuration
- Profile T - For advanced video streaming
  - H.264 / H.265 video compression
  - Imaging settings
  - Motion alarm and tampering events
  - Metadata streaming
  - Bi-directional audio

## Services

https://www.onvif.org/profiles/specifications/

- https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl
- https://www.onvif.org/ver20/imaging/wsdl/imaging.wsdl
- https://www.onvif.org/ver10/media/wsdl/media.wsdl

## TMP

|                        | Dahua   | Reolink | TP-Link |
|------------------------|---------|---------|---------|
| GetCapabilities        | no auth | no auth | no auth |
| GetServices            | no auth | no auth | no auth |
| GetServiceCapabilities | no auth | no auth | auth    |
| GetSystemDateAndTime   | no auth | no auth | no auth |
| GetNetworkInterfaces   | auth    | auth    | auth    |
| GetDeviceInformation   | auth    | auth    | auth    |
| GetProfiles            | auth    | auth    | auth    |
| GetScopes              | auth    | auth    | auth    |

- Dahua - onvif://192.168.10.90:80
- Reolink - onvif://192.168.10.92:8000
- TP-Link - onvif://192.168.10.91:2020/onvif/device_service
-

---

### Overview (`pkg/opus/README.md`)

## Useful links

- [RFC 3550: RTP: A Transport Protocol for Real-Time Applications](https://datatracker.ietf.org/doc/html/rfc3550)
- [RFC 6716: Definition of the Opus Audio Codec](https://datatracker.ietf.org/doc/html/rfc6716)
- [RFC 7587: RTP Payload Format for the Opus Speech and Audio Codec](https://datatracker.ietf.org/doc/html/rfc7587)

---

### Overview (`pkg/rtmp/README.md`)

## Tests

- go2rtc rtmp client => Reolink
- go2rtc rtmp server <= Dahua
- go2rtc rtmp publish => YouTube
- go2rtc rtmp publish => Telegram

## Logs

```
request  []interface {}{"connect", 1, map[string]interface {}{"app":"s", "flashVer":"FMLE/3.0 (compatible; FMSc/1.0)", "tcUrl":"rtmps://xxx.rtmp.t.me/s/xxxxx"}}
response []interface {}{"_result", 1, map[string]interface {}{"capabilities":31, "fmsVer":"FMS/3,0,1,123"}, map[string]interface {}{"code":"NetConnection.Connect.Success", "description":"Connection succeeded.", "level":"status", "objectEncoding":0}}
request  []interface {}{"releaseStream", 2, interface {}(nil), "xxxxx"}
request  []interface {}{"FCPublish", 3, interface {}(nil), "xxxxx"}
request  []interface {}{"createStream", 4, interface {}(nil)}
response []interface {}{"_result", 2, interface {}(nil)}
response []interface {}{"_result", 4, interface {}(nil), 1}
request  []interface {}{"publish", 5, interface {}(nil), "xxxxx", "live"}
response []interface {}{"onStatus", 0, interface {}(nil), map[string]interface {}{"code":"NetStream.Publish.Start", "description":"xxxxx is now published", "detail":"xxxxx", "level":"status"}}
```

## Useful links

- https://en.wikipedia.org/wiki/Flash_Video
- https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol
- https://rtmp.veriskope.com/pdf/rtmp_specification_1.0.pdf
- https://rtmp.veriskope.com/docs/spec/

---

### Overview (`pkg/rtsp/README.md`)

## Useful links

- https://www.kurento.org/blog/rtp-i-intro-rtp-and-sdp

---

### Overview (`pkg/tuya/README.md`)

## Useful links

- https://developer.tuya.com/en/docs/iot/webrtc?id=Kacsd4x2hl0se
- https://github.com/tuya/webrtc-demo-go
- https://github.com/bacco007/HomeAssistantConfig/blob/master/custom_components/xtend_tuya/multi_manager/tuya_iot/ipc/webrtc/xt_tuya_iot_webrtc_manager.py
- https://github.com/tuya/tuya-device-sharing-sdk
- https://github.com/make-all/tuya-local/blob/main/custom_components/tuya_local/cloud.py
- https://ipc-us.ismartlife.me/
- https://protect-us.ismartlife.me/

---

### Overview (`pkg/webrtc/README.md`)

## StateChange

1. offer = pc.CreateOffer()
2. pc.SetLocalDescription(offer)
3. OnICEGatheringStateChange: gathering
4. OnSignalingStateChange: have-local-offer
*. OnICEGatheringStateChange: complete
5. pc.SetRemoteDescription(answer)
6. OnSignalingStateChange: stable
7. OnICEConnectionStateChange: checking
8. OnICEConnectionStateChange: connected

---

### Overview (`pkg/wyoming/README.md`)

##  Default wake words

- alexa_v0.1
- hey_jarvis_v0.1
- hey_mycroft_v0.1
- hey_rhasspy_v0.1
- ok_nabu_v0.1

## Useful Links

- https://github.com/rhasspy/wyoming-satellite
- https://github.com/rhasspy/wyoming-openwakeword
- https://github.com/fwartner/home-assistant-wakewords-collection
- https://github.com/esphome/micro-wake-word-models/tree/main?tab=readme-ov-file

---

### Overview (`pkg/y4m/README.md`)

## Planar YUV formats

Packed YUV - yuyv422 - YUYV 4:2:2
Semi-Planar - nv12 - Y/CbCr 4:2:0
Planar YUV - yuv420p - Planar YUV 4:2:0 - aka. [cosited](https://manned.org/yuv4mpeg.5)

```
[video4linux2,v4l2 @ 0x55fddc42a940] Raw       :     yuyv422 :           YUYV 4:2:2 : 1920x1080
[video4linux2,v4l2 @ 0x55fddc42a940] Raw       :        nv12 :         Y/CbCr 4:2:0 : 1920x1080
[video4linux2,v4l2 @ 0x55fddc42a940] Raw       :     yuv420p :     Planar YUV 4:2:0 : 1920x1080
```

## Useful links

- https://learn.microsoft.com/en-us/windows/win32/medfound/recommended-8-bit-yuv-formats-for-video-rendering
- https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_concepts
- https://fourcc.org/yuv.php#YV12
- https://docs.kernel.org/userspace-api/media/v4l/pixfmt-yuv-planar.html
- https://gist.github.com/Jim-Bar/3cbba684a71d1a9d468a6711a6eddbeb

---

### Overview (`internal/api/ws/README.md`)

# WebSocket

Endpoint: `/api/ws`

Query parameters:

- `src` (required) - Stream name

### WebRTC

Request SDP:

```json
{"type":"webrtc/offer","value":"v=0\r\n..."}
```

Response SDP:

```json
{"type":"webrtc/answer","value":"v=0\r\n..."}
```

Request/response candidate:

- empty value also allowed and optional

```json
{"type":"webrtc/candidate","value":"candidate:3277516026 1 udp 2130706431 192.168.1.123 54321 typ host"}
```

### MSE

Request:

- codecs list optional

```json
{"type":"mse","value":"avc1.640029,avc1.64002A,avc1.640033,hvc1.1.6.L153.B0,mp4a.40.2,mp4a.40.5,flac,opus"}
```

Response:

```json
{"type":"mse","value":"video/mp4; codecs=\"avc1.64001F,mp4a.40.2\""}
```

### HLS

Request:

```json
{"type":"hls","value":"avc1.640029,avc1.64002A,avc1.640033,hvc1.1.6.L153.B0,mp4a.40.2,mp4a.40.5,flac"}
```

Response:

- you MUST rewrite full HTTP path to `http://192.168.1.123:1984/api/hls/playlist.m3u8`

```json
{"type":"hls","value":"#EXTM3U\n#EXT-X-STREAM-INF:BANDWIDTH=1000000,CODECS=\"avc1.64001F,mp4a.40.2\"\nhls/playlist.m3u8?id=DvmHdd9w"}
```

### MJPEG

Request/response:

```json
{"type":"mjpeg"}
```

---

### Overview (`internal/ffmpeg/device/README.md`)

# FFmpeg Device

You can get video from any USB camera or Webcam as RTSP or WebRTC stream. This is part of FFmpeg integration.

- check available devices in web interface
- `video_size` and `framerate` must be supported by your camera!
- for Linux supported only video for now
- for macOS you can stream FaceTime camera or whole desktop!
- for macOS important to set right framerate

## Configuration

Format: `ffmpeg:device?{input-params}#{param1}#{param2}#{param3}`

```yaml
streams:
  linux_usbcam:   ffmpeg:device?video=0&video_size=1280x720#video=h264
  windows_webcam: ffmpeg:device?video=0#video=h264
  macos_facetime: ffmpeg:device?video=0&audio=1&video_size=1280x720&framerate=30#video=h264#audio=pcma
```

**PS.** It is recommended to check the available devices in the WebUI add page.

---

### Overview (`internal/ffmpeg/hardware/README.md`)

# Hardware

You **DON'T** need hardware acceleration if:

- you're not using the [FFmpeg source](../README.md)
- you're using only `#video=copy` for the FFmpeg source
- you're using only `#audio=...` (any audio) transcoding for the FFmpeg source

You **NEED** hardware acceleration if you're using `#video=h264`, `#video=h265`, `#video=mjpeg` (video) transcoding.

## Important

- Acceleration is disabled by default because it can be unstable (this may change in the future)
- go2rtc can automatically detect supported hardware acceleration if enabled
- go2rtc will enable hardware decoding only if hardware encoding is supported
- go2rtc will use the same GPU for decoder and encoder
- Intel and AMD will switch to a software decoder if the input codec isn't supported by the hardware decoder
- NVIDIA will fail if the input codec isn't supported by the hardware decoder
- Raspberry Pi always uses a software decoder

```yaml
streams:
  # auto select hardware encoder
  camera1_hw: ffmpeg:rtsp://rtsp:12345678@192.168.1.123/av_stream/ch0#video=h264#hardware

  # manual select hardware encoder (vaapi, cuda, v4l2m2m, dxva2, videotoolbox)
  camera1_vaapi: ffmpeg:rtsp://rtsp:12345678@192.168.1.123/av_stream/ch0#video=h264#hardware=vaapi
```

## Docker and Hass Addon

There are two versions of the Docker container and Hass Add-on:

- Latest (Alpine) supports hardware acceleration for Intel iGPU (CPU with graphics) and Raspberry Pi.
- Hardware (Debian 12) supports Intel iGPU, AMD GPU, NVIDIA GPU.

## Intel iGPU

**Supported on:** Windows binary, Linux binary, Docker, Hass Addon.

If you have an Intel Sandy Bridge (2011) CPU with graphics, you already have hardware decoding/encoding support for `AVC/H.264`.

If you have an Intel Skylake (2015) CPU with graphics, you already have hardware decoding/encoding support for `AVC/H.264`, `HEVC/H.265` and `MJPEG`.

Read more [here](https://en.wikipedia.org/wiki/Intel_Quick_Sync_Video#Hardware_decoding_and_encoding) and [here](https://en.wikipedia.org/wiki/Intel_Graphics_Technology#Capabilities_(GPU_video_acceleration)).

Linux and Docker:

- It may be important to have a recent OS and Linux kernel. For example, on my **Debian 10 (kernel 4.19)** it did not work, but after updating to **Debian 11 (kernel 5.10)** everything was fine.
- If you run into trouble, check that you have the `/dev/dri/` folder on your host.

Docker users should add the `--privileged` option to the container for access to the hardware.

**PS.** Supported via [VAAPI](https://trac.ffmpeg.org/wiki/Hardware/VAAPI) engine on Linux and [DXVA2+QSV](https://trac.ffmpeg.org/wiki/Hardware/QuickSync) engine on Windows.

## AMD GPU

*I don't have the hardware to test this!!!*

**Supported on:** Linux binary, Docker, Hass Addon.

Docker users should install: `alexxit/go2rtc:master-hardware`. Docker users should add the `--privileged` option to the container for access to the hardware.

Hass Addon users should install **go2rtc master hardware** version.

**PS.** Supported via [VAAPI](https://trac.ffmpeg.org/wiki/Hardware/VAAPI) engine.

## NVIDIA GPU

**Supported on:** Windows binary, Linux binary, Docker.

Docker users should install: `alexxit/go2rtc:master-hardware`.

Read more [here](https://docs.frigate.video/configuration/hardware_acceleration) and [here](https://jellyfin.org/docs/general/administration/hardware-acceleration/#nvidia-hardware-acceleration-on-docker-linux).

**PS.** Supported via [CUDA](https://trac.ffmpeg.org/wiki/HWAccelIntro#CUDANVENCNVDEC) engine.

## Raspberry Pi 3

**Supported on:** Linux binary, Docker, Hass Addon.

I don't recommend using transcoding on the Raspberry Pi 3. It's extremely slow, even with hardware acceleration. Also, it may fail when transcoding a 2K+ stream.

## Raspberry Pi 4

*I don't have the hardware to test this!!!*

**Supported on:** Linux binary, Docker, Hass Addon.

**PS.** Supported via [v4l2m2m](https://lalitm.com/hw-encoding-raspi/) engine.

## macOS

In my tests, transcoding is faster on the M1 CPU than on the M1 GPU. Transcoding time on the M1 CPU is better than any Intel iGPU and comparable to an NVIDIA RTX 2070.

**PS.** Supported via [videotoolbox](https://trac.ffmpeg.org/wiki/HWAccelIntro#VideoToolbox) engine.

## Rockchip

- It's important to use a custom FFmpeg build with Rockchip support from [@nyanmisaka](https://github.com/nyanmisaka/ffmpeg-rockchip)
  - Static binaries from [@MarcA711](https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/)
- It's important to have Linux kernel 5.10 or 6.1

**Tested**

- [Orange Pi 3B](https://www.armbian.com/orangepi3b/) with Armbian 6.1, supports transcoding H.264, H.265, MJPEG

---

### Overview (`pkg/hap/camera/README.md`)

## Useful links

- https://github.com/bauer-andreas/secure-video-specification

---

### Overview (`pkg/v4l2/device/README.md`)

# Video For Linux Two

Build on Ubuntu

```bash
sudo apt install gcc-x86-64-linux-gnu
sudo apt install gcc-i686-linux-gnu
sudo apt install gcc-aarch64-linux-gnu binutils
sudo apt install gcc-arm-linux-gnueabihf
sudo apt install gcc-mipsel-linux-gnu

x86_64-linux-gnu-gcc -w -static videodev2_arch.c -o videodev2_x86_64
i686-linux-gnu-gcc -w -static videodev2_arch.c -o videodev2_i686
aarch64-linux-gnu-gcc -w -static videodev2_arch.c -o videodev2_aarch64
arm-linux-gnueabihf-gcc -w -static videodev2_arch.c -o videodev2_armhf
mipsel-linux-gnu-gcc -w -static videodev2_arch.c -o videodev2_mipsel -D_TIME_BITS=32
```

## Useful links

- https://github.com/torvalds/linux/blob/master/include/uapi/linux/videodev2.h

---

--- METRICS ---
- Files Extracted: 80
- Estimated Token Budget: ~46513 tokens
- Canonical Reference: https://codewiki.google/github.com/AlexxIT/go2rtc
