Technical Documentation: AlexxIT/go2rtc
ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference
Overview (`README.md`)
Ultimate camera streaming application with support for dozens formats and protocols.
- zero-dependency small app for all OS (Windows, macOS, Linux, FreeBSD)
- zero-delay for many supported protocols (lowest possible streaming latency)
- streaming input from dozens formats and protocols
- streaming output in all popular formats
- streaming ingest in a number of popular formats
- publish any source to popular streaming services (YouTube, Telegram)
- on-the-fly transcoding only if necessary via FFmpeg
- two-way audio support for many formats
- streaming audio to all cameras with two-way audio support
- mixing tracks from different sources to single stream
- auto-match client-supported streaming formats and codecs
- streaming stats for all active connections
- can be integrated to any project or be used as standalone app
Inspired by
- series of streaming projects from @deepch
- webrtc go library and whole @pion team
- rtsp-simple-server idea from @aler9
- GStreamer framework pipeline idea
- MediaSoup framework routing idea
- HomeKit Accessory Protocol from @brutella
- creator of the project's logo @v_novoseltsev
Table of Contents
Installation
- Download binary or use Docker or Home Assistant add-on or integration
- Open web interface:
http://localhost:1984/ - Add streams to config
Developers: integrate HTTP API into your smart home platform.
go2rtc: Binary
Download binary for your OS from latest release:
| name | description |
|---|---|
| go2rtc_win64.zip | Windows 10+ 64-bit |
| go2rtc_win32.zip | Windows 10+ 32-bit |
| go2rtc_win_arm64.zip | Windows ARM 64-bit |
| go2rtc_linux_amd64 | Linux 64-bit |
| go2rtc_linux_i386 | Linux 32-bit |
| go2rtc_linux_arm64 | Linux ARM 64-bit (ex. Raspberry 64-bit OS) |
| go2rtc_linux_arm | Linux ARM 32-bit (ex. Raspberry 32-bit OS) |
| go2rtc_linux_armv6 | Linux ARMv6 (for old Raspberry 1 and Zero) |
| go2rtc_linux_mipsel | Linux MIPS (ex. Xiaomi Gateway 3, Wyze cameras) |
| go2rtc_mac_amd64.zip | macOS 11+ Intel 64-bit |
| go2rtc_mac_arm64.zip | macOS ARM 64-bit |
| go2rtc_freebsd_amd64.zip | FreeBSD 64-bit |
| 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 depend on the Go language.
go2rtc: Docker
The Docker containers alexxit/go2rtc and ghcr.io/alexxit/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 but are designed to operate independently of Home Assistant.
It comes preinstalled with FFmpeg and Python.
go2rtc: Home Assistant add-on
- Settings > Add-ons > Plus > Repositories > Addtext
https://github.com/AlexxIT/hassio-addons - go2rtc > Install > Start
go2rtc: Home Assistant Integration
WebRTC Camera custom component can be used on any Home Assistant installation, including 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
- Docker:
alexxit/go2rtc:masteroralexxit/go2rtc:master-hardwareversions - Home Assistant add-on:
go2rtc masterorgo2rtc master hardwareversions
Configuration
This is the go2rtc.yaml file in YAML-format.
The configuration can be changed in the WebUI at http://localhost:1984.
The editor provides syntax highlighting and checking.
The simplest config looks like this:
streams:
hall-camera: rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=0- by default go2rtc will search
go2rtc.yamlin the current work directory apiserver will start on default 1984 port (TCP)rtspserver will start on default 8554 port (TCP)webrtcwill use port 8555 (TCP/UDP) for connections
More information can be found here.
Features
A summary table of all modules and features can be found here.
Core modules
app- Reading configs and setting up logs.api- Handle HTTP and WebSocket API.streams- Handle a list of streams.
Streaming input
public protocols
mpjpeg- The legacy but still used MJPEG protocol for real-time media transmission.onvif- A popular ONVIF protocol for receiving media in RTSP format.rtmp- The legacy but still used RTMP protocol for real-time media transmission.rtsp- The most common RTSP protocol for real-time media transmission.webrtc- WebRTC web-compatible protocol for real-time media transmission.yuv4mpegpipe- Raw YUV frame stream with YUV4MPEG header.
private protocols
bubble- Some NVR from dvr163.com and eseecloud.com.doorbird- Doorbird devices with two-way audio.dvrip- DVR-IP NVR, NetSurveillance, Sofia protocol (XMeye SDK).eseecloud- Some NVR from dvr163.com and eseecloud.com.gopro- GoPro cameras, connected via USB or Wi-Fi.hass- Import cameras from Home Assistant config files.homekit- Cameras with Apple HomeKit protocol.isapi- Two-way audio for Hikvision ISAPI protocol.kasa- TP-Link Kasa cameras.multitrans- Two-way audio for Chinese version of TP-Link cameras.nest- Google Nest cameras through user-unfriendly and paid APIs.ring- Ring cameras with two-way audio support.roborock- Roborock vacuums with cameras with two-way audio support.tapo- TP-Link Tapo cameras with two-way audio support.vigi- TP-Link Vigi cameras.tuya- Tuya ecosystem cameras with two-way audio support.webtorrent- Stream from another go2rtc via WebTorrent protocol.wyze- Wyze cameras using native P2P protocolxiaomi- Xiaomi Mi Home ecosystem cameras with two-way audio support.
devices
alsa- A framework for receiving audio from devices on Linux OS.v4l2- A framework for receiving video from devices on Linux OS.
files
adts- Audio stream in AAC codec with Audio Data Transport Stream headers.flv- The legacy but still used Flash Video format.h264- AVC/H.264 bitstream.hevc- HEVC/H.265 bitstream.hls- A popular HTTP Live Streaming format.mjpeg- A continuous sequence of JPEG frames (without HTTP headers).mpegts- The legacy MPEG transport stream format.wav- Audio stream in Waveform Audio File format.
scripts
echo- If the source has a dynamic link, you can use a bash or python script to get it.exec- You can run an external application (ffmpeg,gstreamer,rpicam, etc.) and receive a media stream from it.expr- If the source has a dynamic link, you can use Expr language to get it.ffmpeg- Use FFmpeg as a stream source. Hardware-accelerated transcoding and streaming from USB devices are supported.
webrtc
creality- Creality 3D printer cameras.kinesis- Amazon Kinesis video streams.openipc- Cameras on open-source OpenIPC firmware.switchbot- SwitchBot cameras.whep- WebRTC/WHEP is replaced by WebRTC/WISH standard for WebRTC video/audio viewers.wyze- Legacy method to connect to Wyze cameras via docker-wyze-bridge.
Streaming output
adts- Output stream in ADTS format with AAC audio.ascii- Just for fun stream as ASCII to Terminal.flv- Output stream in Flash Video format.hls- Output stream in HTTP Live Streaming format.homekit- Output stream to Apple Home using HomeKit protocol.jpeg- Output snapshots in JPEG format.mpjpeg- Output a stream in MJPEG format.mp4- Output as MP4 stream or Media Source Extensions (MSE) compatible format.mpegts- Output stream in MPEG transport stream format.onvif- Output stream using ONVIF protocol.rtmp- Output stream using Real-Time Messaging protocol.rtsp- Output stream using Real-Time Streaming protocol.webrtc- Output stream using Web Real-Time Communication API.webtorrent- Output stream using WebTorrent protocol.yuv4mpegpipe- Output in raw YUV frame stream with YUV4MPEG header.
Streaming ingest
Supported for:flv,mjpeg,mpegts,rtmp,rtsp,webrtc.
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,dvrip,exec,isapi,multitrans,ring,roborock,rtsp,tapo,tuya,webrtc,wyze,xiaomi.
Two-way audio can be used in browser with WebRTC technology. The browser will give access to the microphone only for HTTPS sites (read more).
Stream to camera
You can play audio files or live streams on any camera with two-way audio support.
Publish stream
You can publish any stream to streaming services (YouTube, Telegram, etc.) via RTMP/RTMPS.
Preload stream
You can preload any stream on go2rtc start. This is useful for cameras that take a long time to start up.
Streaming stats
WebUI provides detailed information about all active connections, including IP-addresses, formats, protocols, number of packets and bytes transferred.
Via the HTTP API in json or dot 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 and MSE technologies.
But it cannot be done for RTSP, HTTP progressive streaming, HLS 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.
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 abovertsp://192.168.1.123:8554/camera1?video=h264&audio=aac&audio=opus- H264 video codec and two separate audio tracksrtsp://192.168.1.123:8554/camera1?video&audio=all- any video codec and all audio codecs as separate trackshttp://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 deviceshttp://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+ Desktop Edge Android Chrome 136+ | H264, H265* PCMU, PCMA OPUS | H264, H265* AAC, FLAC* OPUS | H264, H265* AAC, FLAC* OPUS, MP3 | no |
| Desktop Firefox | H264 PCMU, PCMA OPUS | H264 AAC, FLAC* OPUS | H264 AAC, FLAC* OPUS | no |
| Desktop Safari 14+ iPad Safari 14+ iPhone Safari 17.1+ | H264, H265* PCMU, PCMA OPUS | H264, H265 AAC, FLAC* | no! | H264, H265 AAC, FLAC* |
| iPhone Safari 14+ | H264, H265* PCMU, PCMA OPUS | no! | no! | H264, H265 AAC, FLAC* |
| macOS Hass App | no | no | no | H264, H265 AAC, FLAC* |
HTTP*- HTTP Progressive Streaming, not related to progressive download, because the file has no size and no endWebRTC H265- supported in Chrome 136+, supported in Safari 18+MSE iPhone- supported in iOS 17.1+
Audio
- go2rtc supports automatic repackaging of
PCMA/PCMU/PCMcodecs intoFLACfor MSE/MP4/HLS so they'll work almost anywhere - WebRTC audio codecs:
PCMU/8000,PCMA/8000,OPUS/48000/2 OPUSandMP3inside 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 does a great job with this.
Including 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:
PCMA/PCMU => PCM => FLAC => MSE/MP4/HLSResample 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:
PCM/xxx => PCMA/8000 => WebRTC
PCMA/xxx => PCMA/8000 => WebRTC
PCMU/xxx => PCMU/8000 => WebRTCImportant
- 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 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
H264in camera settings - this camera supports codecs AAC, PCMU, PCMA for sending audio (from mic), and you select
AAC/16000in 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/2codec, because it is higher quality than thePCMU/8000orPCMA/8000
Now you have a stream with two sources - RTSP and FFmpeg:
streams:
dahua:
- rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
- ffmpeg:rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=0#audio=opusgo2rtc 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:
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:
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 integration, because it runs locally on your server
- local access to API is not a problem for the 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)
- 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, Caddy, 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). 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 2024.11+ - top open-source smart home project
- Frigate 0.12+ - open-source NVR built around real-time AI object detection
- camera.ui - The modern, local-first platform for professional video surveillance.
- Advanced Camera Card - custom card for Home Assistant
- OpenIPC - alternative IP camera firmware from an open community
- wz_mini_hacks - custom firmware for Wyze cameras
- EufyP2PStream - a small project that provides a video/audio stream from Eufy cameras that don't directly support RTSP
- ioBroker.euSec - ioBroker adapter for controlling Eufy security devices
- MMM-go2rtc - MagicMirror² module
- ring-mqtt - Ring-to-MQTT bridge
- lightNVR
Distributions
Camera experience
- Dahua - reference implementation streaming protocols, a lot of settings, high stream quality, multiple streaming clients
- EZVIZ - awful RTSP protocol implementation, many bugs in SDP
- Hikvision - a lot of proprietary streaming technologies
- Reolink - 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 - very low stream quality, no settings, not the best protocol implementation
- TP-Link - few streaming clients, packet loss?
- Cheap noname cameras, Wyze Cams, Xiaomi cameras with hacks (usually have
/live/ch00_1in 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
Overview (`docker/README.md`)
Docker
Images are built automatically via GitHub actions and published on Docker Hub and GitHub.
Versions
alexxit/go2rtc:latest- latest release based onalpine(amd64,386,arm/v6,arm/v7,arm64) with support for hardware transcoding for Intel iGPU and Raspberryalexxit/go2rtc:latest-hardware- latest release based ondebian 13(amd64) with support for hardware transcoding for Intel iGPU, AMD GPU and NVidia GPUalexxit/go2rtc:latest-rockchip- latest release based ondebian 12(arm64) with support for hardware transcoding for Rockchip RK35xxalexxit/go2rtc:master- latest unstable version based onalpinealexxit/go2rtc:master-hardware- latest unstable version based ondebian 13(amd64)alexxit/go2rtc:master-rockchip- latest unstable version based ondebian 12(arm64)
Docker compose
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
docker run -d \
--name go2rtc \
--network host \
--privileged \
--restart unless-stopped \
-e TZ=Atlantic/Bermuda \
-v ~/go2rtc:/config \
alexxit/go2rtcDeployment with GPU Acceleration
docker run -d \
--name go2rtc \
--network host \
--privileged \
--restart unless-stopped \
-e TZ=Atlantic/Bermuda \
--gpus all \
-v ~/go2rtc:/config \
alexxit/go2rtc:latest-hardwareOverview (`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,hassandonvifmodules receive a link to a stream. They don't know the protocol in advance. - The
execandffmpegmodules support many formats. They are identical to thehttpmodule. - The
api,app,debug,ngrok,pinggy,srtp,streamsare 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 |
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 formatpkg/{format}/backchannel.go- producer with only backchannel func
Mentioning modules:
main.goREADME.mdinternal/README.mdwebsite/.vitepress/config.jswebsite/api/openapi.yamlwww/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
- THEOplayer
- How Generate DTS/PTS
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 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\
./goweightDependencies
- 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/toolsLicenses
- 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
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 website. It's content published on GitHub Pages and is a mirror of alexxit.github.io/go2rtc/.
The site contains:
- Project's documentation, which is compiled via vitepress from
README.mdfiles located in the root of the repository, as well as in theinternalfolder. - Project's API in OpenAPI format, and the 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=320pxor percentswidth=50%
www/webrtc.html - WebRTC viewer with support two way audio and params in URL:
media=video+audio- simple viewermedia=video+audio+microphone- two way audio from cameramedia=camera+microphone- stream from browsermedia=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:
- Video and Audio better than just Video
- H265 better than H264
- WebRTC better than MSE, than HLS, than MJPEG
Browser support
ECMAScript 2019 (ES10) supported by iOS 12 (iPhone 5S, iPad Air, iPad Mini 2, etc.).
But ECMAScript 2017 (ES8) almost fine (es6 + async) and recommended for React+TypeScript.
Known problems
- Autoplay doesn't work for WebRTC in Safari read more.
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
go run examples/onvif_client/main.go http://admin:[email protected] GetAudioEncoderConfigurationsOverview (`examples/tutk_decoder/README.md`)
tutk_decoder
- Wireshark > Select any packet > Follow > UDP Stream
- Wireshark > File > Export Packet Dissections > As JSON > Displayed, Values
tutk_decoder wireshark.json decoded.txt
Overview (`internal/alsa/README.md`)
ALSA
[!WARNING]
This source is under development and does not always work well.
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 format. It can be explored in interactive viewer. WebSocket API described here.
The project's static HTML and JS files are located in the www 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_pathand host go2rtc on your main app webserver suburl - all files from
static_dirhosted on root path:/ - you can use raw TLS cert/key content or path to files
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 APIPS:
- MJPEG over WebSocket plays better than native MJPEG because Chrome bug
- 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.
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.yamlconfig 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
- YAML:
- 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.yamlor a simpler version
go2rtc -c log.format=text -c /config/go2rtc.yaml -c rtsp.listen='' -c /usr/local/go2rtc/go2rtc.yamlEnvironment variables
There is support for loading external variables into the config. First, they will be loaded from credential files. 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.
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 setJSON Schema
Editors like GoLand and VS Code support autocomplete and syntax validation.
# yaml-language-server: $schema=https://raw.githubusercontent.com/AlexxIT/go2rtc/master/www/schema.jsonor from a running go2rtc:
# yaml-language-server: $schema=http://localhost:1984/schema.jsonDefaults
- Default values may change in updates
- FFmpeg module has many presets, they are not listed here because they may also change in updates
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.
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 levelModules: 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
Private format in some cameras from dvr163.com and eseecloud.com.
Configuration
- you can skip
username,password,port,chandstreamif they are default - set up separate streams for different channels and streams
streams:
camera1: bubble://username:[email protected]:34567/bubble/live?ch=0&stream=0Overview (`internal/debug/README.md`)
Debug
This module provides GET /api/stack, with which you can find hanging goroutines
Overview (`internal/doorbird/README.md`)
Doorbird
This source type supports Doorbird 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
streams:
doorbird1:
- rtsp://admin:[email protected]:8557/mpeg/720p/media.amp # RTSP stream
- doorbird://admin:[email protected]?media=video # MJPEG stream
- doorbird://admin:[email protected]?media=audio # audio stream
- doorbird://admin:[email protected] # two-way audioOverview (`internal/dvrip/README.md`)
DVR-IP
Private format from DVR-IP NVR, NetSurveillance, Sofia protocol (NETsurveillance ActiveX plugin XMeye SDK).
Configuration
- you can skip
username,password,port,channelandsubtypeif they are default - set up separate streams for different channels
- use
subtype=0for Main stream, andsubtype=1for Extra1 stream - only the TCP protocol is supported
streams:
only_stream: dvrip://username:[email protected]:34567?channel=0&subtype=0
only_tts: dvrip://username:[email protected]:34567?backchannel=1
two_way_audio:
- dvrip://username:[email protected]:34567?channel=0&subtype=0
- dvrip://username:[email protected]:34567?backchannel=1Overview (`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
streams:
apple_hls: echo:python3 hls.py https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.htmlInstall python libraries
Docker and Hass Add-on users have preinstalled python3 without any additional libraries, like requests or others. If you need some additional libraries - you need to install them to folder with your script:
- Install SSH & Web Terminal
- Goto Add-on Web UI
- Install library:
pip install requests -t /config/echo - Add your script to
/config/echo/myscript.py - Use your script as source
echo:python3 /config/echo/myscript.py
Example: Apple HLS
streams:
apple_hls: echo:python3 hls.py https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.htmlhls.py
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
This source is for cameras with a link like this http://admin:@192.168.1.123:80/livestream/12. Related issue.
Configuration
streams:
camera1: eseecloud://user:[email protected]:80/livestream/12Overview (`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) 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 - go2rtc ffmpeg source is just a shortcut to exec source
- FFplay - play audio on your server
- GStreamer
- Raspberry Pi Cameras
- 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 sigkillbackchannel- enable backchannel for two-way audiostarttimeout- time in seconds for waiting first byte from RTSP
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=1Backchannel
- You can check audio card names in the Go2rtc > WebUI > Add
- You can specify multiple backchannel lines with different codecs
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/8000Overview (`internal/expr/README.md`)
Expr
Expr - expression language and expression evaluation for Go.
- 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 requestsmatch- JS-like RegExp queries
Fetch examples
Multiple fetch requests are executed within a single session. They share the same cookie.
HTTP GET
var r = fetch('https://example.org/products.json');HTTP POST JSON
var r = fetch('https://example.org/post', {
method: 'POST',
// Content-Type: application/json will be set automatically
json: {username: 'example'}
});HTTP POST Form
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
streams:
dahua_vto: |
expr:
let host = 'admin:[email protected]';
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
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.URLdom.ufanet.ru
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_lParse HLS files from Apple
Same example in two languages - python and expr.
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 folder
Configuration
Format: ffmpeg:{input}#{param1}#{param2}#{param3}. Examples:
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://[email protected]/av_stream/ch0#video=h264#rotate=90All transcoding formats have built-in templates: 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.
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
videoandaudioparams multiple times (ex.#video=copy#audio=copy#audio=pcmu) - You can use
rotateparam with90,180,270or-90values, important with transcoding (ex.#video=h264#rotate=90) - You can use
widthand/orheightparams, important with transcoding (ex.#video=h264#width=1280) - You can use
drawtextto 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
timeoutparam to set RTSP input timeout in seconds (ex.#timeout=10) - You can use
rawparam for any additional FFmpeg arguments (ex.#raw=-vf transpose=1) - You can use
inputparam to override default input template (ex.#input=rtsp/udpwill 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
- You can use raw input value (ex.
Read more about hardware acceleration.
PS. It is recommended to check the available hardware in the WebUI add page.
Overview (`internal/flussonic/README.md`)
Flussonic
Support streams from Flussonic server. Related issue.
Overview (`internal/gopro/README.md`)
GoPro
Support streaming from GoPro cameras, connected via USB or Wi-Fi to Linux, Mac, Windows.
Supported models: HERO9, HERO10, HERO11, HERO12.
Supported OS: Linux, Mac, Windows, HassOS
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
- if the camera is detected but the stream does not start, you need to disable the firewall
- Discover camera address: WebUI > Add > GoPro
- Add camera to config
streams:
hero12: gopro://172.20.100.51Useful links
Overview (`internal/hass/README.md`)
Hass
Support import camera links from Home Assistant config files:
- Generic Camera, setup via GUI
- HomeKit Camera
- ONVIF
- Roborock vacuums with camera
Configuration
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-AB12WebRTC Cameras
Any cameras in WebRTC format are supported. But at the moment Home Assistant only supports some 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 - it supports extending the stream.
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 can work around it.
Overview (`internal/hls/README.md`)
HLS
HLS is the worst technology for real-time streaming.
It can only be useful on devices that do not support more modern technology, like WebRTC, MP4.
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.
Useful links
Overview (`internal/homekit/README.md`)
Apple HomeKit
This module supports both client and server for the Apple HomeKit 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 between the device and go2rtc
go2rtc supports importing paired HomeKit devices from Home Assistant.
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
VLCand 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:
streams:
aqara_g3:
- hass:Camera-Hub-G3-AB12
- ffmpeg:aqara_g3#audio=aac#audio=opusRTSP 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 (both EU and CN versions).
HomeKit Server
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
streams:
dahua1: rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=0
homekit:
dahua1: # same stream ID from streams list, default PIN - 19550224Full config
streams:
dahua1:
- rtsp://admin:[email protected]/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 IDProxy 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
streams:
aqara1:
- homekit://...
- ffmpeg:aqara1#audio=aac#audio=opus # optional audio transcoding
homekit:
aqara1: # same stream ID from streams listOverview (`internal/http/README.md`)
HTTP
This source supports receiving a stream via an HTTP link.
It can determine the source format from theContent-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 (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 codec with Audio Data Transport Stream (ADTS) headers.flv- The legacy but still used 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 format.wav- Audio stream in WAV format.yuv4mpegpipe- Raw YUV frame stream with YUV4MPEG header.
Configuration
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:[email protected]/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
This source type supports only backchannel audio for the Hikvision ISAPI protocol. So it should be used as a second source in addition to the RTSP protocol.
Configuration
streams:
hikvision1:
- rtsp://admin:[email protected]:554/Streaming/Channels/101
- isapi://admin:[email protected]:80/Overview (`internal/ivideon/README.md`)
Ivideon
Support public cameras from the service Ivideon.
Configuration
streams:
quailcam: ivideon:100-tu5dkUPct39cTp9oNEN2B6/0Overview (`internal/kasa/README.md`)
TP-Link Kasa
TP-Link Kasa non-standard protocol more info.
username- urlsafe email,[email protected]->alex%40gmail.compassword- base64password,secret1->c2VjcmV0MQ==
streams:
kc401: kasa://username:[email protected]:19443/https/stream/mixedTested: 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 (ex. second stream for Dahua cameras)
- some cameras have an HTTP link with MJPEG stream
- some cameras have an HTTP link with snapshots - go2rtc can convert them to MJPEG stream
- you can convert an H264/H265 stream from your camera via FFmpeg integration
With this example, your stream will have both H264 and MJPEG codecs:
streams:
camera1:
- rtsp://rtsp:[email protected]/av_stream/ch0
- ffmpeg:camera1#video=mjpegMJPEG Server
mpjpeg
Output a stream in MJPEG format. In FFmpeg, this format is called mpjpeg because it contains HTTP headers.
ffplay http://192.168.1.123:1984/api/stream.mjpeg?src=camera1jpeg
Receiving a JPEG snapshot.
curl http://192.168.1.123:1984/api/frame.jpeg?src=camera1- You can use
width/wand/orheight/hparameters. - You can use
rotateparam with90,180,270or-90values. - You can use
hardware/hwparam read more. - You can use
cacheparam (1m,10s, etc.) to get a cached snapshot.- The snapshot is cached only when requested with the
cacheparameter. - A cached snapshot will be used if its time is not older than the time specified in the
cacheparameter. - The
cacheparameter does not check the image dimensions from the cache and those specified in the query.
- The snapshot is cached only when requested with the
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.
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
textparameter - you can stream any camera or file from disk
go2rtc.yaml - transcoding to MJPEG, terminal size - 210x59 (16/9), fps - 10
streams:
gamazda: ffmpeg:gamazda.mp4#video=mjpeg#hardware#width=210#height=59#raw=-r 10API params
color- foreground color, values: empty,8,256,rgb, SGR- example:
30(black),37(white),38;5;226(yellow)
- example:
back- background color, values: empty,8,256,rgb, SGR- example:
40(black),47(white),48;5;226(yellow)
- example:
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)
- example:
Examples
% 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 frame stream with YUV4MPEG header.
ffplay http://192.168.1.123:1984/api/stream.y4m?src=camera1Streaming ingest
ffmpeg -re -i BigBuckBunny.mp4 -c mjpeg -f mpjpeg http://localhost:1984/api/stream.mjpeg?dst=camera1Overview (`internal/mp4/README.md`)
MP4
This module provides several features:
- MSE stream (fMP4 over WebSocket)
- Camera snapshots in MP4 format (single frame), can be sent to Telegram
- 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=flacandmp4=allparam for codec filters - You can use
durationparam in seconds (ex.duration=15) - You can use
filenameparam (ex.filename=record.mp4) - You can use
rotateparam with90,180or270values - You can use
scaleparam with positive integer values (ex.scale=4:3)
- You can use
Read more about 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 integration.
- change
urlto your go2rtc web API (http://localhost:1984/for most users) - change
targetto your Telegram chat ID (support list) - change
src=camera1to 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
service: telegram_bot.send_video
data:
url: http://localhost:1984/api/frame.mp4?src=camera1
target: 123456789Record from H264 or H265 camera
Record from service call to the future. Doesn't support loopback.
mp4=flac- adds support PCM audio familyfilename=record.mp4- set name for downloaded file
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: 123456789Snapshot from JPEG or MJPEG camera
This example works via the mjpeg module.
service: telegram_bot.send_photo
data:
url: http://localhost:1984/api/frame.jpeg?src=camera1
target: 123456789Overview (`internal/mpeg/README.md`)
MPEG
This module provides an HTTP API for:
- Streaming output in
mpegtsformat. - Streaming output in
adtsformat. - Streaming ingest in
mpegtsformat.
MPEG-TS Server
ffplay http://localhost:1984/api/stream.ts?src=camera1ADTS Server
ffplay http://localhost:1984/api/stream.aac?src=camera1Streaming ingest
ffmpeg -re -i BigBuckBunny.mp4 -c copy -f mpegts http://localhost:1984/api/stream.ts?dst=camera1Overview (`internal/multitrans/README.md`)
TP-Link MULTITRANS
new in v1.9.14 by @forrestsocool
Two-way audio support for Chinese version of TP-Link cameras.
Configuration
streams:
tplink_cam:
# video uses standard RTSP
- rtsp://admin:[email protected]:554/stream1
# two-way audio uses MULTITRANS schema
- multitrans://admin:[email protected]:554Useful 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
For simplicity, it is recommended to connect the Nest/WebRTC camera to the Home Assistant.
But if you can somehow get the below parameters, Nest/WebRTC source will work without Home Assistant.
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 for your OS and register with the ngrok service.
Tunnel for only WebRTC Stream
You need to add your ngrok authtoken and WebRTC TCP port to YAML:
ngrok:
command: ngrok tcp 8555 --authtoken eW91IHNoYWxsIG5vdCBwYXNzCnlvdSBzaGFsbCBub3QgcGFzcwTunnel for WebRTC and Web interface
You need to create ngrok.yaml config file and add it to the go2rtc config:
ngrok:
command: ngrok start --all --config ngrok.yamlngrok config example:
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: tcpSee the ngrok agent documentation for more details on the ngrok configuration file.
Overview (`internal/onvif/README.md`)
ONVIF
ONVIF Client
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".
streams:
dahua1: onvif://admin:[email protected]
reolink1: onvif://admin:[email protected]:8000
tapo1: onvif://admin:[email protected]:2020ONVIF 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 - 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.
pinggy:
tunnel: http://localhost:1984Tunnel to RTSP camera.
For example, you have camera: rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=0
pinggy:
tunnel: tcp://192.168.10.91:554In 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:12345Now you have a working stream:
rtsp://admin:[email protected]:12345/cam/realmonitor?channel=1&subtype=0Overview (`internal/ring/README.md`)
Ring
This source type supports Ring cameras with 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.
streams:
ring: ring:?device_id=XXX&refresh_token=XXX
ring_snapshot: ring:?device_id=XXX&refresh_token=XXX&snapshotOverview (`internal/roborock/README.md`)
Roborock
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 or the core integration. 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
- Streaming output and ingest in
rtmpformat - RTMP server - Streaming output and ingest in
flvformat - FLV server
RTMP Client
You can get a stream from an RTMP server, for example Nginx with nginx-rtmp-module.
Client Configuration
streams:
rtmp_stream: rtmp://192.168.1.123/live/camera1RTMP Server
Streaming output stream in rtmp format:
ffplay rtmp://localhost:1935/camera1Streaming ingest stream in rtmp format:
ffmpeg -re -i BigBuckBunny.mp4 -c copy -f flv rtmp://localhost:1935/camera1Server Configuration
By default, the RTMP server is disabled.
rtmp:
listen: ":1935" # by default - disabled!FLV Server
Streaming output in flv format.
ffplay http://localhost:1984/stream.flv?src=camera1Streaming ingest in flv format.
ffmpeg -re -i BigBuckBunny.mp4 -c copy -f flv http://localhost:1984/api/stream.flv?dst=camera1Tested clients
| From | To | Comment |
|---|---|---|
| go2rtc | Reolink RLC-520A fw. v3.1.0.801 | OK |
go2rtc.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=passwordTested 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
rtmp:
listen: :1935
streams:
tmp:OBS
Settings > Stream:
- Service: Custom
- Server: rtmp://192.168.10.101/tmp
- Stream Key: ``
- Use auth:
<disabled>
OpenIPC
WebUI > Majestic > Settings > Outgoing
- Enable
- Address: rtmp://192.168.10.101/tmp
- Save
- Restart
FFmpeg
ffmpeg -re -i bbb.mp4 -c copy -f flv rtmp://192.168.10.101/tmpGoPro
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
- Streaming output - RTSP server
- Streaming ingest
- Two-way audio
RTSP Client
Configuration
streams:
sonoff_camera: rtsp://rtsp:[email protected]/av_stream/ch0
dahua_camera:
- rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
- rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=1#backchannel=0
amcrest_doorbell:
- rtsp://username:[email protected]:554/cam/realmonitor?channel=1&subtype=0#backchannel=0
unifi_camera: rtspx://192.168.1.123:7441/fD6ouM72bWoFijxK
glichy_camera: ffmpeg:rtsp://username:[email protected]/live/ch00_1Recommendations
- 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=0to the end of your RTSP link in YAML config file - Dahua Doorbell users may want to change audio codec for proper two-way audio. Make sure not to request backchannel multiple times by adding
#backchannel=0to other stream sources of the same doorbell. Theunicast=true&proto=Onvifis 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 ofrtsps://. And don't use?enableSrtpsuffix - TP-Link Tapo users may skip login and password, because go2rtc supports login without them
- 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. 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
Other options
Format: rtsp...#{param1}#{param2}#{param3}
- Add custom timeout
#timeout=30(in seconds) - Ignore audio -
#media=videoor ignore video -#media=audio - Ignore two-way audio API
#backchannel=0- important for some glitchy cameras - Use WebSocket transport
#transport=ws...
RTSP over WebSocket
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:[email protected]:4567/rtsp-over-websocket
# WebSocket without authorization, RTSP - with
dahua-rtsp-ws: rtsp://user:[email protected]/cam/realmonitor?channel=1&subtype=1&proto=Private3#transport=ws://192.168.1.123/rtspoverwebsocketRTSP 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
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 filtersBy 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.
Streaming ingest
ffmpeg -re -i BigBuckBunny.mp4 -c copy -rtsp_transport tcp -f rtsp rtsp://localhost:8554/camera1Two-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 module.
[!NOTE]
This module can be removed and its functionality transferred to the homekit module.
Configuration
srtp:
listen: :8443 # enabled by defaultOverview (`internal/streams/README.md`)
Streams
This core module is responsible for managing the stream list.
Stream to camera
go2rtc supports playing audio files (ex. music or TTS) and live streams (ex. radio) on cameras with two-way audio support.
API example:
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 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/8000codec (ex. Tapo) - it is recommended to choose higher quality formats if your camera supports them (ex.
PCMA/48000for some Dahua cameras) - if you play files over
httplink, you need to add#input=fileparams for transcoding, so the file will be transcoded and played in real time - if you play live streams, you should skip
#inputparam, because it is already in real time - you can stop active playback by calling the API with the empty
srcparameter - you will see one active producer and one active consumer in go2rtc WebUI info page during streaming
Publish stream
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 listening for this task
You can use the API:
POST http://localhost:1984/api/streams?src=camera1&dst=rtmps://...Or config file:
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:[email protected]/stream1#video=h264#hardware#audio=aac
audio_transcode:
- ffmpeg:rtsp://user:[email protected]/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
You can preload any stream on go2rtc start. This is useful for cameras that take a long time to start up.
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#hardwareExamples
/* Detailed source-code truncated for AI context efficiency. */Overview (`internal/tapo/README.md`)
TP-Link Tapo
TP-Link Tapo proprietary camera protocol with two-way audio support.
- stream quality is the same as RTSP protocol
- 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
adminusername - some new camera firmwares require SHA256 instead of MD5
Configuration
streams:
# cloud password without username
camera1: tapo://[email protected]
# admin username and UPPERCASE MD5 cloud-password hash
camera2: tapo://admin:[email protected]
# admin username and UPPERCASE SHA256 cloud-password hash
camera3: tapo://admin:[email protected]
# VGA stream (the so called substream, the lower resolution one)
camera4: tapo://[email protected]?subtype=1
# HD stream (default)
camera5: tapo://[email protected]?subtype=0echo -n "cloud password" | md5 | awk '{print toupper($0)}'
echo -n "cloud password" | shasum -a 256 | awk '{print toupper($0)}'TP-Link Kasa
[!NOTE]
This source should be moved to separate module. Because it's source code not related to Tapo.
TP-Link Kasa non-standard protocol more info.
username- urlsafe email,[email protected]->alex%40gmail.compassword- base64password,secret1->c2VjcmV0MQ==
streams:
kc401: kasa://username:[email protected]:19443/https/stream/mixedTested: KD110, KC200, KC401, KC420WS, EC71.
TP-Link Vigi
TP-Link VIGI 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.
streams:
camera1: vigi://admin:{password}@192.168.1.123Overview (`internal/tuya/README.md`)
Tuya
Tuya 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 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, anduidfrom Tuya IoT Platform. Here's a guide. - Please ensure that you have subscribed to the
IoT Video Live Streamservice (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
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=sdOverview (`internal/v4l2/README.md`)
Video4Linux
What you should to know about V4L2:
- 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:
streams:
camera1: v4l2:device?video=/dev/video0&input_format=yuyv422&video_size=1280x720&framerate=10Go2rtc 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=camera1Important. 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=camera1Overview (`internal/webrtc/README.md`)
WebRTC
WebRTC Client
This source type supports four connection formats.
Creality
Creality 3D printer camera. Read more here.
streams:
creality_k2p: webrtc:http://192.168.1.123:8000/call/webrtc_local#format=crealitygo2rtc
This format is only supported in go2rtc. Unlike WHEP, it supports asynchronous WebRTC connections and two-way audio.
streams:
webrtc-go2rtc: webrtc:ws://192.168.1.123:1984/api/ws?src=camera1Kinesis
Supports Amazon 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.
streams:
webrtc-kinesis: webrtc:wss://...amazonaws.com/?...#format=kinesis#client_id=...#ice_servers=[{...},{...}]PS. For kinesis sources, you can use echo to get connection params using bash, python or any other script language.
OpenIPC
Cameras on open-source OpenIPC firmware.
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 cameras that are based on Kinesis Video Streams. Specifically, this includes Pan/Tilt Cam Plus 2K and Pan/Tilt Cam Plus 3K and 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.
streams:
webrtc-switchbot: webrtc:wss://...amazonaws.com/?...#format=switchbot#resolution=hd#play_type=0#client_id=...#ice_servers=[{...},{...}]WHEP
WebRTC/WHEP is replaced by WebRTC/WISH standard for WebRTC video/audio viewers. But it may already be supported in some third-party software. It is supported in go2rtc.
streams:
webrtc-whep: webrtc:http://192.168.1.123:1984/api/webrtc?src=camera1Wyze
Legacy method to connect to Wyze cameras using WebRTC protocol via docker-wyze-bridge. For native P2P support without docker-wyze-bridge, see Source: Wyze.
streams:
webrtc-wyze: webrtc:http://192.168.1.123:5000/signaling/camera1?kvs#format=wyzeWebRTC Server
What you should know about WebRTC:
- It's almost always a direct 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 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 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
- UDP is not suitable for transmitting 2K and 4K high bit rate video over open networks because of the high loss rate:
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:
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
webrtc:
candidates:
- 216.58.210.174:8555 # if you have a static public IP addressDynamic public IP
- forward the port 8555 on your router (you can use the same 8555 port or any other as the external port)
- add
stunword and external port to YAML config- go2rtc automatically detects your external address with STUN server
webrtc:
candidates:
- stun:8555 # if you have a dynamic public IP addressHard tech way 1. Own TCP-tunnel
If you have a personal VPS, 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, you can install TURN server (e.g. coturn, config example).
webrtc:
ice_servers:
- urls: [stun:stun.l.google.com:19302]
- urls: [turn:123.123.123.123:3478]
username: your_user
credential: your_passFull 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.
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 youFor example, go2rtc is inside a closed Docker container (e.g. Frigate). 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.
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
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:
- Create empty stream in the
go2rtc.yaml - Go to go2rtc WebUI
- Open
linkspage for your stream - Select
camera+microphoneordisplay+speakeroption - Open
webrtclocal page (your go2rtc should work over HTTPS!) orshare linkvia WebTorrent technology (work over HTTPS by default)
Ingest: WHIP
You can use OBS Studio or any other broadcast software with WHIP protocol support. This standard has not yet been approved. But you can download OBS Studio dev version:
- 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
This source can get a stream from another go2rtc via WebTorrent protocol.
Client Configuration
streams:
webtorrent1: webtorrent:?share=huofssuxaty00izc&pwd=k3l2j9djeg8v8r7eWebTorrent Server
This module supports:
- Share any local stream via WebTorrent technology
- Get any incoming stream from PC or mobile via WebTorrent technology
- Get any remote go2rtc source via WebTorrent 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.
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:
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 sectionLink 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 support to create local voice assistants using Home Assistant.
- go2rtc can act as Wyoming Satellite
- go2rtc can act as Wyoming External Microphone
- go2rtc can act as Wyoming External Sound
- 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
- Audio stream (MIC)
- any audio source with PCM codec support (include PCMA/PCMU)
- Voice Activity Detector (VAD)
- Wake Word (WAKE)
- Speech-to-Text (STT)
- Conversation agent (INTENT)
- Text-to-speech (TTS)
- 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).
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:
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.1Events
You can add wyoming event handling using the expr 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:
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 processStream()- 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 streamPlayAudio()- 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 fromwavfileType- type (name) of eventData- event data in JSON format (ex.{"text":"how are you"})- also available other functions from expr 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 afterDetect()when VAD detected, but WAKE service unavailableinternal-detection- called afterDetect()when WAKE word detected
Example 1. You want to play a sound file when a wake word detected (only wav supported):
PlayFileandPlayAudiofunctions are executed synchronously, the following steps will be executed only after they are completed
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
synthesizestep, we get the value of thetextand call the HA REST API - in the
audio-stopstep we get the duration of the TTS in seconds, wait for this time and start the pipeline again
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.
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: 1Satellite on Dahua camera with two-way audio support.
streams:
dahua_camera:
- rtsp://admin:[email protected]/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: 1Satellite on external wyoming Microphone and Sound.
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: 1Wyoming External Microphone and Sound
Advanced users, who want to enjoy the Wyoming Satellite project, can use go2rtc as a Wyoming External Microphone or Wyoming External Sound.
go2rtc.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: snddocker-compose.yml
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
streams:
wyoming_external:
- wyoming://192.168.1.23:10600
- wyoming://192.168.1.23:10601?backchannel=1docker-compose.yml
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
log:
wyoming: traceOverview (`internal/wyze/README.md`)
Wyze
This source allows you to stream from Wyze cameras using native P2P protocol without the Wyze app or SDK.
Important:
- Requires Wyze account. You need to login once via the WebUI to load your cameras.
- Requires firmware with DTLS. Only cameras with DTLS-enabled firmware are supported.
- Internet access is only needed when loading cameras from your account. After that, all streaming is local P2P.
- 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
- Get your API Key from Wyze Developer Portal
- Go to go2rtc WebUI > Add > Wyze
- Enter your API ID, API Key, email, and password
- Select cameras to add - stream URLs are generated automatically
Example Config
wyze:
[email protected]:
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=trueStream 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:
streams:
wyze_hd: wyze://...&subtype=hd
wyze_sd: wyze://...&subtype=sdTwo-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
This source allows you to view cameras from the Xiaomi Mi Home 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:
- Not all cameras are supported. The list of supported cameras is collected in this issue.
- Each time you connect to the camera, you need Internet access to obtain encryption keys.
- 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
- Go to go2rtc WebUI > Add > Xiaomi > Login with username and password
- Receive verification code by email or phone if required.
- Complete the captcha if required.
- If everything is OK, your account will be added, and you can load cameras from it.
Example
xiaomi:
1234567890: V1:***
streams:
xiaomi1: xiaomi://1234567890:[email protected]?did=9876543210&model=isa.camera.hlc7Configuration
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.
streams:
xiaomi1: xiaomi://***&subtype=sdYou can use a second channel for dual cameras: channel=2.
streams:
xiaomi1: xiaomi://***&channel=2Overview (`internal/yandex/README.md`)
Yandex
Source for receiving stream from new Yandex IP camera.
Get Yandex token
- Install HomeAssistant integration YandexStation.
- Copy token from HomeAssistant config folder:
/config/.storage/core.config_entries, key:"x_token".
Get device ID
- Open this link in any browser: https://iot.quasar.yandex.ru/m/v3/user/devices
- Copy ID of your camera, key:
"id".
Configuration
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=540Overview (`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://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
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=32Useful 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 formattwos- 16-bit data is stored in big endian formatsowt- 16-bit data is stored in little endian formatin24- denotes 24-bit, big endianin32- denotes 32-bit, big endianfl32- denotes 32-bit floating point PCMfl64- denotes 64-bit floating point PCMalaw- denotes A-law logarithmic PCMulaw- 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
- from environment variables
Overview (`pkg/ffmpeg/README.md`)
FFplay output
FFplay 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/videoA-V- av_diff, difference between audio and video timestampsfd- frames droppedaq- audio queue (0 - no delay)vq- video queue (0 - no delay)sq- subtitle queuef- 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 1280x960TTS
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=pcmaUseful 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
Overview (`pkg/h264/README.md`)
H264
Payloader code taken from pion library and changed to AVC packets support.
Useful Links
- RTP Payload Format for H.264 Video
- The H264 Sequence parameter set
- H.264 Video Types (Microsoft)
- Automatic Generation of H.264 Parameter Sets to Recover Video File Fragments
- Chromium sources
- AVC levels
- AVC profiles table
- Supported Media for Google Cast
- Two stream formats, Annex-B, AVCC (H.264) and HVCC (H.265)
- https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/producer-reference-nal.html
Overview (`pkg/h265/README.md`)
H265
Payloader code taken from pion library branch h265, because it's still not in release. Thanks to @kevmo314.
Useful links
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- hasAIDandServices Services- hasIID,TypeandCharactersCharacters- hasIID,Type,FormatandValue
- one or more
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
- HAP in AirPlay2 receiver
- HomeKit Secure Video Unofficial Specification
- Homebridge Camera FFmpeg
- 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
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
- RFC 6716: Definition of the Opus Audio Codec
- RFC 7587: RTP Payload Format for the Opus Speech and Audio Codec
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
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
- offer = pc.CreateOffer()
- pc.SetLocalDescription(offer)
- OnICEGatheringStateChange: gathering
- OnSignalingStateChange: have-local-offer
*. OnICEGatheringStateChange: complete - pc.SetRemoteDescription(answer)
- OnSignalingStateChange: stable
- OnICEConnectionStateChange: checking
- 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
[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 : 1920x1080Useful 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:
{"type":"webrtc/offer","value":"v=0\r\n..."}Response SDP:
{"type":"webrtc/answer","value":"v=0\r\n..."}Request/response candidate:
- empty value also allowed and optional
{"type":"webrtc/candidate","value":"candidate:3277516026 1 udp 2130706431 192.168.1.123 54321 typ host"}MSE
Request:
- codecs list optional
{"type":"mse","value":"avc1.640029,avc1.64002A,avc1.640033,hvc1.1.6.L153.B0,mp4a.40.2,mp4a.40.5,flac,opus"}Response:
{"type":"mse","value":"video/mp4; codecs=\"avc1.64001F,mp4a.40.2\""}HLS
Request:
{"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
{"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:
{"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_sizeandframeratemust 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}
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=pcmaPS. 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
- you're using only
#video=copyfor 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
streams:
# auto select hardware encoder
camera1_hw: ffmpeg:rtsp://rtsp:[email protected]/av_stream/ch0#video=h264#hardware
# manual select hardware encoder (vaapi, cuda, v4l2m2m, dxva2, videotoolbox)
camera1_vaapi: ffmpeg:rtsp://rtsp:[email protected]/av_stream/ch0#video=h264#hardware=vaapiDocker 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.
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 engine on Linux and DXVA2+QSV 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 engine.
NVIDIA GPU
Supported on: Windows binary, Linux binary, Docker.
Docker users should install: alexxit/go2rtc:master-hardware.
PS. Supported via CUDA 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 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 engine.
Rockchip
- It's important to use a custom FFmpeg build with Rockchip support from @nyanmisaka
- Static binaries from @MarcA711
- It's important to have Linux kernel 5.10 or 6.1
Tested
- Orange Pi 3B with Armbian 6.1, supports transcoding H.264, H.265, MJPEG
Overview (`pkg/hap/camera/README.md`)
Useful links
Overview (`pkg/v4l2/device/README.md`)
Video For Linux Two
Build on Ubuntu
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=32Useful links
--- METRICS ---
- Files Extracted: 80
- Estimated Token Budget: ~46513 tokens
- Canonical Reference: https://codewiki.google/github.com/AlexxIT/go2rtc