go2rtc Documentation

Ultimate camera streaming application

14,430 stars Go Go 80 files · ~46,591 tokens #ffmpeg#go#golang#hassio#hls#home-assistant#homekit#media-server
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy go2rtc on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name go2rtc -p 1984:1984 --restart always alexxit/go2rtc:latest

Technical Documentation: AlexxIT/go2rtc

ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference

Overview (`README.md`)

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

Inspired by

Table of Contents

Installation

  1. Download binary or use Docker or Home Assistant add-on or integration
  2. Open web interface: http://localhost:1984/
  3. 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

  1. Settings > Add-ons > Plus > Repositories > Add
    text
    https://github.com/AlexxIT/hassio-addons
  2. 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:master or alexxit/go2rtc:master-hardware versions
  • Home Assistant add-on: go2rtc master or go2rtc master hardware versions

Configuration

This is the go2rtc.yaml file in YAML-format.
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:

yaml
streams:
  hall-camera: rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=0
  • by default go2rtc will search go2rtc.yaml in the current work directory
  • api server will start on default 1984 port (TCP)
  • rtsp server will start on default 8554 port (TCP)
  • webrtc will use port 8555 (TCP/UDP) for connections

More information can be found here.

Features

A summary table of all modules and features can be found here.

Core modules

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

devices

  • alsa - A framework for receiving audio from devices on Linux OS.
  • v4l2 - A framework for receiving video from devices on Linux OS.

files

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

Streaming output

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.

read more

Publish stream

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

read more

Preload stream

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

read more

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 above
  • rtsp://192.168.1.123:8554/camera1?video=h264&audio=aac&audio=opus - H264 video codec and two separate audio tracks
  • rtsp://192.168.1.123:8554/camera1?video&audio=all - any video codec and all audio codecs as separate tracks
  • http://192.168.1.123:1984/api/stream.m3u8?src=camera1&mp4 - HLS stream with MP4 compatible codecs (HLS/fMP4)
  • http://192.168.1.123:1984/api/stream.m3u8?src=camera1&mp4=flac - HLS stream with PCMA/PCMU/PCM audio support (HLS/fMP4), won't work on old devices
  • http://192.168.1.123:1984/api/stream.mp4?src=camera1&mp4=flac - MP4 file with PCMA/PCMU/PCM audio support, won't work on old devices (ex. iOS 12)
  • http://192.168.1.123:1984/api/stream.mp4?src=camera1&mp4=all - MP4 file with non-standard audio codecs, won't work on some players

Codecs madness

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

Device WebRTC MSE HTTP* HLS
latency best medium bad bad
Desktop Chrome 136+ 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*

Audio

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

Apple devices

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

Built-in transcoding

There are no plans to embed complex transcoding algorithms inside go2rtc.
FFmpeg source 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:

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

Resample PCMA/PCMU for WebRTC

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

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

Important

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

Codecs negotiation

For example, you want to watch an RTSP stream from a Dahua IPC-K42 camera in your Chrome browser.

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

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

yaml
streams:
  dahua:
    - rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    - ffmpeg:rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=0#audio=opus

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

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

Security

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

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

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

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

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

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

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

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

rtsp:
  listen: "127.0.0.1:8554" # localhost

webrtc:
  listen: ":8555" # external TCP/UDP port
  • local access to RTSP is not a problem for FFmpeg 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

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_1 in RTSP URL) - awful but usable RTSP protocol implementation, low stream quality, few settings, packet loss?

Tips

Using apps for low RTSP delay

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

Snapshots to Telegram

read more


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

Docker compose

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

Basic Deployment

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

Deployment with GPU Acceleration

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

Overview (`internal/README.md`)

Modules

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

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 format
  • pkg/{format}/backchannel.go - producer with only backchannel func

Mentioning modules:


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

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

Dependencies

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

Licenses

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

Virus


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.md files located in the root of the repository, as well as in the internal folder.
  • Project's API in OpenAPI format, and the Redoc viewer
  • Project's assets (logo).

Overview (`www/README.md`)

www

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

HTTP API

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

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

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

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

JavaScript API

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

video-rtc.js features:

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

Technology selection based on priorities:

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

Browser support

ECMAScript 2019 (ES10) 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.

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

ONVIF Client

shell
go run examples/onvif_client/main.go http://admin:[email protected] GetAudioEncoderConfigurations

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

tutk_decoder

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

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

ALSA

new in v1.9.10

[!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_path and host go2rtc on your main app webserver suburl
  • all files from static_dir hosted on root path: /
  • you can use raw TLS cert/key content or path to files
yaml
api:
  listen: ":1984"    # default ":1984", HTTP API port ("" - disabled)
  username: "admin"  # default "", Basic auth for WebUI
  password: "pass"   # default "", Basic auth for WebUI
  local_auth: true   # default false, Enable auth check for localhost requests
  base_path: "/rtc"  # default "", API prefix for serving on suburl (/api => /rtc/api)
  static_dir: "www"  # default "", folder for static files (custom web interface)
  origin: "*"        # default "", allow CORS requests (only * supported)
  tls_listen: ":443" # default "", enable HTTPS server
  tls_cert: |        # default "", PEM-encoded fullchain certificate for HTTPS
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
  tls_key: |         # default "", PEM-encoded private key for HTTPS
    -----BEGIN PRIVATE KEY-----
    ...
    -----END PRIVATE KEY-----
  unix_listen: "/tmp/go2rtc.sock"  # default "", unix socket listener for API

PS:

  • MJPEG over WebSocket plays better than native MJPEG because Chrome bug
  • 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.yaml config file in the current working directory
  • go2rtc supports multiple config files:
    • go2rtc -c config1.yaml -c config2.yaml -c config3.yaml
  • go2rtc supports inline config in multiple formats from the command line:
    • YAML: go2rtc -c '{log: {format: text}}'
    • JSON: go2rtc -c '{"log":{"format":"text"}}'
    • key=value: go2rtc -c log.format=text
  • Each subsequent config will overwrite the previous one (but only for defined params)
text
go2rtc -config "{log: {format: text}}" -config /config/go2rtc.yaml -config "{rtsp: {listen: ''}}" -config /usr/local/go2rtc/go2rtc.yaml

or a simpler version

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

Environment variables

There is support for loading external variables into the config. First, they will be loaded from credential files. If CREDENTIALS_DIRECTORY is not set, then the key will be loaded from an environment variable. If no environment variable is set, then the string will be left as-is.

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

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

JSON Schema

Editors like GoLand and VS Code support autocomplete and syntax validation.

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

or from a running go2rtc:

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

Defaults

  • Default values may change in updates
  • FFmpeg module has many presets, they are not listed here because they may also change in updates
yaml
api:
  listen: ":1984"  # default public port for WebUI and HTTP API

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

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

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

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

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

Log

You can set different log levels for different modules.

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

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


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

Bubble

new in v1.6.1

Private format in some cameras from dvr163.com and eseecloud.com.

Configuration

  • you can skip username, password, port, ch and stream if they are default
  • set up separate streams for different channels and streams
yaml
streams:
  camera1: bubble://username:[email protected]:34567/bubble/live?ch=0&stream=0

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

Debug

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


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

Doorbird

new in v1.9.8

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

yaml
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 audio

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

DVR-IP

new in v1.2.0

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

Configuration

  • you can skip username, password, port, channel and subtype if they are default
  • set up separate streams for different channels
  • use subtype=0 for Main stream, and subtype=1 for Extra1 stream
  • only the TCP protocol is supported
yaml
streams:
  only_stream: dvrip://username:[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=1

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

Echo

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

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

Configuration

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

Install python libraries

Docker and Hass Add-on users have preinstalled python3 without any additional libraries, like requests or others. If you need some additional libraries - you need to install them to folder with your script:

  1. Install SSH & Web Terminal
  2. Goto Add-on Web UI
  3. Install library: pip install requests -t /config/echo
  4. Add your script to /config/echo/myscript.py
  5. Use your script as source echo:python3 /config/echo/myscript.py

Example: Apple HLS

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

hls.py

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

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

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

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

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

EseeCloud

new in v1.9.10

This source is for cameras with a link like this http://admin:@192.168.1.123:80/livestream/12. Related issue.

Configuration

yaml
streams:
  camera1: eseecloud://user:[email protected]:80/livestream/12

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

Exec

Exec source can run any external application and expect data from it. Two transports are supported - pipe (new in v1.5.0) 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:

Configuration

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

  • killsignal - signal which will be sent to stop the process (numeric form)
  • killtimeout - time in seconds for forced termination with sigkill
  • backchannel - enable backchannel for two-way audio
  • starttimeout - time in seconds for waiting first byte from RTSP
yaml
streams:
  stream: exec:ffmpeg -re -i /media/BigBuckBunny.mp4 -c copy -rtsp_transport tcp -f rtsp {output}
  picam_h264: exec:libcamera-vid -t 0 --inline -o -
  picam_mjpeg: exec:libcamera-vid -t 0 --codec mjpeg -o -
  pi5cam_h264: exec:libcamera-vid -t 0 --libav-format h264 -o -
  canon: exec:gphoto2 --capture-movie --stdout#killsignal=2#killtimeout=5
  play_pcma: exec:ffplay -fflags nobuffer -f alaw -ar 8000 -i -#backchannel=1
  play_pcm48k: exec:ffplay -fflags nobuffer -f s16be -ar 48000 -i -#backchannel=1

Backchannel

  • You can check audio card names in the Go2rtc > WebUI > Add
  • You can specify multiple backchannel lines with different codecs
yaml
sources:
  two_way_audio_win:
    - exec:ffmpeg -hide_banner -f dshow -i "audio=Microphone (High Definition Audio Device)" -c pcm_s16le -ar 16000 -ac 1 -f wav -
    - exec:ffplay -nodisp -probesize 32 -f s16le -ar 16000 -#backchannel=1#audio=s16le/16000
    - exec:ffplay -nodisp -probesize 32 -f alaw -ar 8000 -#backchannel=1#audio=alaw/8000

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

Expr

new in v1.8.2

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 requests
    • match - JS-like RegExp queries

Fetch examples

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

HTTP GET

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

HTTP POST JSON

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

HTTP POST Form

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

Script examples

Two way audio for Dahua VTO

yaml
streams:
  dahua_vto: |
    expr:
    let host = 'admin:[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

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

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

dom.ufanet.ru

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

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

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

Parse HLS files from Apple

Same example in two languages - python and expr.

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

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

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

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

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

  example_expr: |
    expr:

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

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

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

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

Comparison

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

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

FFmpeg

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

  • FFmpeg preinstalled for Docker and Home Assistant add-on users
  • Home Assistant add-on users can target files from /media folder

Configuration

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

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

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

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

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

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

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

All 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.

yaml
ffmpeg:
  bin: ffmpeg  # path to ffmpeg binary
  global: "-hide_banner"
  timeout: 5  # default timeout in seconds for rtsp inputs
  h264: "-codec:v libx264 -g:v 30 -preset:v superfast -tune:v zerolatency -profile:v main -level:v 4.1"
  mycodec: "-any args that supported by ffmpeg..."
  myinput: "-fflags nobuffer -flags low_delay -timeout {timeout} -i {input}"
  myraw: "-ss 00:00:20"
  • You can use go2rtc stream name as ffmpeg input (ex. ffmpeg:camera1#video=h264)
  • You can use video and audio params multiple times (ex. #video=copy#audio=copy#audio=pcmu)
  • You can use rotate param with 90, 180, 270 or -90 values, important with transcoding (ex. #video=h264#rotate=90)
  • You can use width and/or height params, important with transcoding (ex. #video=h264#width=1280)
  • You can use drawtext to add a timestamp (ex. drawtext=x=2:y=2:fontsize=12:fontcolor=white:box=1:boxcolor=black)
    • This will greatly increase the CPU of the server, even with hardware acceleration
  • You can use timeout param to set RTSP input timeout in seconds (ex. #timeout=10)
  • You can use raw param for any additional FFmpeg arguments (ex. #raw=-vf transpose=1)
  • You can use input param to override default input template (ex. #input=rtsp/udp will change RTSP transport from TCP to UDP+TCP)
    • You can use raw input value (ex. #input=-timeout {timeout} -i {input})
    • You can add your own input templates

Read more about hardware acceleration.

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


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

Flussonic

new in v1.9.10

Support streams from Flussonic server. Related issue.


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

GoPro

new in v1.8.3

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
  1. Discover camera address: WebUI > Add > GoPro
  2. Add camera to config
yaml
streams:
  hero12: gopro://172.20.100.51

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

Hass

Support import camera links from Home Assistant config files:

Configuration

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

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

WebRTC Cameras

new in v1.6.0

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.

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

RTSP Cameras

By default, the Home Assistant API does not allow you to get a dynamic RTSP link to a camera stream. This method can work around it.


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

HLS

new in v1.1.0

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.


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 VLC and probably any other player
  • Audio should be transcoded for use with MSE, WebRTC, etc.

Client Configuration

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

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

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

This source is in active development! Tested only with Aqara Camera Hub G3 (both EU and CN versions).

HomeKit Server

new in v1.7.0

HomeKit module can work in two modes:

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

Important

  • HomeKit cameras support only H264 video and OPUS audio

Server Configuration

Minimal config

yaml
streams:
  dahua1: rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=0
homekit:
  dahua1:  # same stream ID from streams list, default PIN - 19550224

Full config

yaml
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 ID

Proxy HomeKit camera

  • Video stream from HomeKit camera to Apple device (iPhone, Apple TV) will be transmitted directly
  • Video stream from HomeKit camera to RTSP/WebRTC/MP4/etc. will be transmitted via go2rtc
yaml
streams:
  aqara1:
    - homekit://...
    - ffmpeg:aqara1#audio=aac#audio=opus  # optional audio transcoding

homekit:
  aqara1:  # same stream ID from streams list

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

HTTP

This source supports receiving a stream via an HTTP link.

It can determine the source format from 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

yaml
streams:
  # [HTTP-FLV] stream in video/x-flv format
  http_flv: http://192.168.1.123:20880/api/camera/stream/780900131155/657617
  
  # [JPEG] snapshots from Dahua camera, will be converted to MJPEG stream
  dahua_snap: http://admin:[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

new in v1.3.0

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

yaml
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

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

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

new in v1.7.0

TP-Link Kasa non-standard protocol more info.

  • username - urlsafe email, [email protected] -> alex%40gmail.com
  • password - base64password, secret1 -> c2VjcmV0MQ==
yaml
streams:
  kc401: kasa://username:[email protected]:19443/https/stream/mixed

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


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

Motion JPEG

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

MJPEG Client

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

You can receive an MJPEG stream in several ways:

  • some cameras support MJPEG codec inside RTSP stream (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:

yaml
streams:
  camera1:
    - rtsp://rtsp:[email protected]/av_stream/ch0
    - ffmpeg:camera1#video=mjpeg

MJPEG Server

mpjpeg

Output a stream in MJPEG format. In FFmpeg, this format is called mpjpeg because it contains HTTP headers.

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

jpeg

Receiving a JPEG snapshot.

text
curl http://192.168.1.123:1984/api/frame.jpeg?src=camera1
  • You can use width/w and/or height/h parameters.
  • You can use rotate param with 90, 180, 270 or -90 values.
  • You can use hardware/hw param read more.
  • You can use cache param (1m, 10s, etc.) to get a cached snapshot.
    • The snapshot is cached only when requested with the cache parameter.
    • A cached snapshot will be used if its time is not older than the time specified in the cache parameter.
    • The cache parameter does not check the image dimensions from the cache and those specified in the query.

ascii

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

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

Tips

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

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

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

API params

  • color - foreground color, values: empty, 8, 256, rgb, SGR
    • example: 30 (black), 37 (white), 38;5;226 (yellow)
  • back - background color, values: empty, 8, 256, rgb, SGR
    • example: 40 (black), 47 (white), 48;5;226 (yellow)
  • text - character set, values: empty, one character, block, list of chars (in order of brightness)
    • example: %20 (space), block (keyword for block elements), ox (two chars)

Examples

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

yuv4mpegpipe

Raw YUV frame stream with YUV4MPEG header.

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

Streaming ingest

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

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

MP4

This module provides several features:

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

API examples

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

Read more about codecs filters.

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 url to your go2rtc web API (http://localhost:1984/ for most users)
  • change target to your Telegram chat ID (support list)
  • change src=camera1 to your stream name from go2rtc config

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

Snapshot from H264 or H265 camera

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

Record from H264 or H265 camera

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

  • mp4=flac - adds support PCM audio family
  • filename=record.mp4 - set name for downloaded file
yaml
service: telegram_bot.send_video
data:
  url: http://localhost:1984/api/stream.mp4?src=camera1&mp4=flac&duration=5&filename=record.mp4  # duration in seconds
  target: 123456789

Snapshot from JPEG or MJPEG camera

This example works via the mjpeg module.

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

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

MPEG

This module provides an HTTP API for:

  • Streaming output in mpegts format.
  • Streaming output in adts format.
  • Streaming ingest in mpegts format.

MPEG-TS Server

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

ADTS Server

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

Streaming ingest

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

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

new in v1.9.14 by @forrestsocool

Two-way audio support for Chinese version of TP-Link cameras.

Configuration

yaml
streams:
  tplink_cam:
    # video uses standard RTSP
    - rtsp://admin:[email protected]:554/stream1
    # two-way audio uses MULTITRANS schema
    - multitrans://admin:[email protected]:554

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

Google Nest

new in v1.6.0

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.

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

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

ngrok

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

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

The ngrok free subscription has the following limitations:

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

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

You need to manually download the ngrok agent 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:

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

Tunnel for WebRTC and Web interface

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

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

ngrok config example:

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

See the ngrok agent documentation for more details on the ngrok configuration file.


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

ONVIF

ONVIF Client

new in v1.5.0

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

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

yaml
streams:
  dahua1: onvif://admin:[email protected]
  reolink1: onvif://admin:[email protected]:8000
  tapo1: onvif://admin:[email protected]:2020

ONVIF Server

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

Go2rtc has one video source and one profile per stream.

Tested clients

Go2rtc works as ONVIF server:

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

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

Tested cameras

Go2rtc works as ONVIF client:

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

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

Pinggy

Pinggy - nice service for public tunnels to your local services.

Features:

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

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

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

Why:

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

Configuration

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

Tunnel to go2rtc WebUI.

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

Tunnel to RTSP camera.

For example, you have camera: rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=0

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

In go2rtc logs you will get similar output:

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

Now you have a working stream:

text
rtsp://admin:[email protected]:12345/cam/realmonitor?channel=1&subtype=0

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

Ring

new in v1.9.13 by @seydx

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.

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

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

Roborock

new in v1.3.0

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:

RTMP Client

You can get a stream from an RTMP server, for example Nginx with nginx-rtmp-module.

Client Configuration

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

RTMP Server

new in v1.8.0

Streaming output stream in rtmp format:

shell
ffplay rtmp://localhost:1935/camera1

Streaming ingest stream in rtmp format:

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

Server Configuration

By default, the RTMP server is disabled.

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

FLV Server

Streaming output in flv format.

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

Streaming ingest in flv format.

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

Tested clients

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

go2rtc.yaml

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

Tested server

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

go2rtc.yaml

yaml
rtmp:
  listen: :1935
streams:
  tmp:

OBS

Settings > Stream:

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

OpenIPC

WebUI > Majestic > Settings > Outgoing

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

FFmpeg

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

GoPro

GoPro Quik > Camera > Translation > Other


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

Real Time Streaming Protocol

This module provides the following features for the RTSP protocol:

RTSP Client

Configuration

yaml
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_1

Recommendations

  • Amcrest Doorbell users may want to disable two-way audio, because with an active stream, you won't have a working call button. You need to add #backchannel=0 to the end of your RTSP link in YAML config file
  • Dahua Doorbell users may want to change audio codec for proper two-way audio. Make sure not to request backchannel multiple times by adding #backchannel=0 to other stream sources of the same doorbell. The unicast=true&proto=Onvif is preferred for two-way audio as this makes the doorbell accept multiple codecs for the incoming audio
  • Reolink users may want NOT to use RTSP protocol at all, some camera models have a very awful, unusable stream implementation
  • Ubiquiti UniFi users may want to disable HTTPS verification. Use rtspx:// prefix instead of rtsps://. And don't use ?enableSrtp suffix
  • 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=video or ignore video - #media=audio
  • Ignore two-way audio API #backchannel=0 - important for some glitchy cameras
  • Use WebSocket transport #transport=ws...

RTSP over WebSocket

yaml
streams:
  # WebSocket with authorization, RTSP - without
  axis-rtsp-ws:  rtsp://192.168.1.123:4567/axis-media/media.amp?overview=0&camera=1&resolution=1280x720&videoframeskipmode=empty&Axis-Orig-Sw=true#transport=ws://user:[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/rtspoverwebsocket

RTSP Server

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

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

Configuration

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

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

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

Read more about codecs filters.

Streaming ingest

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

Two-way audio

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

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

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


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

SRTP

This is a support module for the HomeKit module.

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

Configuration

yaml
srtp:
  listen: :8443  # enabled by default

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

Streams

This core module is responsible for managing the stream list.

Stream to camera

new in v1.3.0

go2rtc supports playing audio files (ex. music or TTS) and live streams (ex. radio) on cameras with two-way audio support.

API example:

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

Publish stream

new in v1.8.0

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:

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

Or config file:

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

streams:
  video_audio_transcode:
    - ffmpeg:rtsp://user:[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

new in v1.9.11

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

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

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

Examples

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

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

new in v1.2.0

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 admin username
  • some new camera firmwares require SHA256 instead of MD5

Configuration

yaml
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=0
bash
echo -n "cloud password" | md5 | awk '{print toupper($0)}'
echo -n "cloud password" | shasum -a 256 | awk '{print toupper($0)}'

new in v1.7.0

[!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.com
  • password - base64password, secret1 -> c2VjcmV0MQ==
yaml
streams:
  kc401: kasa://username:[email protected]:19443/https/stream/mixed

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

new in v1.9.8

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.

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

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

Tuya

new in v1.9.13 by @seydx

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, and uid from Tuya IoT Platform. Here's a guide.
  • Please ensure that you have subscribed to the IoT Video Live Stream service (Free Trial) in the Tuya Developer Platform, otherwise the stream will not work (Tuya Developer Platform > Service API > Authorize > IoT Video Live Stream).

Configuration

Use the resolution parameter to select the stream (not all cameras support an hd stream through WebRTC even if the camera supports it):

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

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

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

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

Video4Linux

new in v1.9.9

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:

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

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

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

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

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

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

WebRTC

WebRTC Client

new in v1.3.0

This source type supports four connection formats.

Creality

new in v1.9.10

Creality 3D printer camera. Read more here.

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

go2rtc

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

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

Kinesis

new in v1.6.1

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.

yaml
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

new in v1.7.0

Cameras on open-source OpenIPC firmware.

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

SwitchBot

Support connection to SwitchBot 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.

yaml
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.

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

Wyze

new in v1.6.1

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.

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

WebRTC Server

What you should know about WebRTC:

  • It's almost always a direct peer-to-peer 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:

Configuration suggestions

  • by default, WebRTC uses both TCP and UDP on port 8555 for connections
  • you can use this port for external access
  • you can change the port in YAML config:
yaml
webrtc:
  listen: ":8555"  # address of your local server and port (TCP/UDP)

Static public IP

  • forward the port 8555 on your router (you can use the same 8555 port or any other as external port)
  • add your external IP address and external port to the YAML config
yaml
webrtc:
  candidates:
    - 216.58.210.174:8555  # if you have a static public IP address

Dynamic public IP

  • forward the port 8555 on your router (you can use the same 8555 port or any other as the external port)
  • add stun word and external port to YAML config
    • go2rtc automatically detects your external address with STUN server
yaml
webrtc:
  candidates:
    - stun:8555  # if you have a dynamic public IP address

Hard tech way 1. Own TCP-tunnel

If you have a personal VPS, 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).

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

Full configuration

Important! This example is not for copy/pasting!

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

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

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

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

Configuration filters

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

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

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

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

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

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

Streaming ingest

Ingest: Browser

new in v1.3.0

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

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

Ingest: WHIP

new in v1.3.0

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

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

WebTorrent

[!NOTE]
This section needs some improvement.

WebTorrent Client

new in v1.3.0

This source can get a stream from another go2rtc via WebTorrent protocol.

Client Configuration

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

WebTorrent Server

new in v1.3.0

This module supports:

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:

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

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


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

Wyoming

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

This module provide Wyoming Protocol 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

  1. Audio stream (MIC)
    • any audio source with PCM codec support (include PCMA/PCMU)
  2. Voice Activity Detector (VAD)
  3. Wake Word (WAKE)
  4. Speech-to-Text (STT)
  5. Conversation agent (INTENT)
  6. Text-to-speech (TTS)
  7. Audio stream (SND)
    • any source with two-way audio (backchannel) and PCM codec support (include PCMA/PCMU)

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

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

Configuration

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

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

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

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

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

Select one or multiple wake words:

yaml
wake_uri: tcp://192.168.1.23:10400?name=alexa_v0.1&name=hey_jarvis_v0.1&name=hey_mycroft_v0.1&name=hey_rhasspy_v0.1&name=ok_nabu_v0.1

Events

You can add wyoming event handling using the expr language. For example, to pronounce TTS on some media player from HA.

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

This is what the default scripts look like:

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

Supported functions and variables:

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

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

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

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

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

  • PlayFile and PlayAudio functions are executed synchronously, the following steps will be executed only after they are completed
yaml
wyoming:
  script_example:
    event:
      internal-detection: PlayFile('/media/beep.wav') && WriteEvent("run-pipeline", '{"start_stage":"asr","end_stage":"tts"}') && Stream()

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

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

  • in the synthesize step, we get the value of the text and call the HA REST API
  • in the audio-stop step we get the duration of the TTS in seconds, wait for this time and start the pipeline again
yaml
wyoming:
  script_example:
    event:
      synthesize: |
        let text = fromJSON(Data).text;
        let token = 'eyJhbGci...';
        fetch('http://localhost:8123/api/services/tts/speak', {
          method: 'POST',
          headers: {'Authorization': 'Bearer '+token,'Content-Type': 'application/json'},
          body: toJSON({
            entity_id: 'tts.google_translate_com',
            media_player_entity_id: 'media_player.google_nest',
            message: text,
            language: 'en',
          }),
        }).ok
      audio-stop: |
        let timestamp = fromJSON(Data).timestamp;
        let delay = string(timestamp)+'s';
        Sleep(delay) && WriteEvent("played") && Detect()

Config examples

Satellite on Windows server using FFmpeg and FFplay.

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

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

Satellite on Dahua camera with two-way audio support.

yaml
streams:
  dahua_camera:
    - rtsp://admin:[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: 1

Satellite on external wyoming Microphone and Sound.

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

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

Wyoming External Microphone and Sound

Advanced users, who want to enjoy the Wyoming Satellite project, can use go2rtc as a Wyoming External Microphone or Wyoming External Sound.

go2rtc.yaml

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

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

docker-compose.yml

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

Wyoming External Source

go2rtc.yaml

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

docker-compose.yml

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

Debug

yaml
log:
  wyoming: trace

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

Wyze

new in v1.9.14 by @seydx

This source allows you to stream from Wyze cameras using native P2P protocol without the Wyze app or SDK.

Important:

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

Features:

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

Setup

  1. Get your API Key from Wyze Developer Portal
  2. Go to go2rtc WebUI > Add > Wyze
  3. Enter your API ID, API Key, email, and password
  4. Select cameras to add - stream URLs are generated automatically

Example Config

yaml
wyze:
  [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=true

Stream URL Format

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

text
wyze://[IP]?uid=[P2P_ID]&enr=[ENR]&mac=[MAC]&model=[MODEL]&subtype=[hd|sd]&dtls=true
Parameter Description
IP Camera's local IP address
uid P2P identifier (20 chars)
enr Encryption key for DTLS
mac Device MAC address
model Camera model (e.g., HL_CAM4)
dtls Enable DTLS encryption (default: true)
subtype Camera resolution: hd or sd (default: hd)

Configuration

Resolution

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

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

Two-Way Audio

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

Camera Compatibility

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

* Gwell based protocols are not yet supported.


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

Xiaomi Mi Home

new in v1.9.13

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:

  1. Not all cameras are supported. The list of supported cameras is collected in this issue.
  2. Each time you connect to the camera, you need Internet access to obtain encryption keys.
  3. Connection to the camera is local only.

Features:

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

Setup

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

Example

yaml
xiaomi:
  1234567890: V1:***

streams:
  xiaomi1: xiaomi://1234567890:[email protected]?did=9876543210&model=isa.camera.hlc7

Configuration

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

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

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

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

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

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

Yandex

Source for receiving stream from new Yandex IP camera.

Get Yandex token

  1. Install HomeAssistant integration YandexStation.
  2. Copy token from HomeAssistant config folder: /config/.storage/core.config_entries, key: "x_token".

Get device ID

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

Configuration

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

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

AAC-LD and AAC-ELD

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

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

Build

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

Broken pipe


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


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

PCM

RTSP

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

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

Apple QuickTime

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

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

FFmpeg RTSP

text
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/video
  • A-V - av_diff, difference between audio and video timestamps
  • fd - frames dropped
  • aq - audio queue (0 - no delay)
  • vq - video queue (0 - no delay)
  • sq - subtitle queue
  • f - timestamp error correction rate (Not 100% sure)

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

Devices Windows

text
>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

text
% ./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

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

TTS

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

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

H264

Payloader code taken from pion library and changed to AVC packets support.


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

H265

Payloader code taken from pion library branch h265, because it's still not in release. Thanks to @kevmo314.


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

Home Accessory Protocol

PS. Character = Characteristic

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

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

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

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

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

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

AAC ELD

Requires ffmpeg built with --enable-libfdk-aac

text
-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)

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

IOCTL

This is just an example how Linux IOCTL constants works.


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


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


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

Fragmented MP4

text
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 + - -

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

PTS/DTS/CTS

text
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

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/

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`)


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

Tests

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

Logs

text
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"}}

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


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


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

StateChange

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

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

Default wake words

  • alexa_v0.1
  • hey_jarvis_v0.1
  • hey_mycroft_v0.1
  • hey_rhasspy_v0.1
  • ok_nabu_v0.1

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

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

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

WebSocket

Endpoint: /api/ws

Query parameters:

  • src (required) - Stream name

WebRTC

Request SDP:

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

Response SDP:

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

Request/response candidate:

  • empty value also allowed and optional
json
{"type":"webrtc/candidate","value":"candidate:3277516026 1 udp 2130706431 192.168.1.123 54321 typ host"}

MSE

Request:

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

Response:

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

HLS

Request:

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

Response:

  • you MUST rewrite full HTTP path to http://192.168.1.123:1984/api/hls/playlist.m3u8
json
{"type":"hls","value":"#EXTM3U\n#EXT-X-STREAM-INF:BANDWIDTH=1000000,CODECS=\"avc1.64001F,mp4a.40.2\"\nhls/playlist.m3u8?id=DvmHdd9w"}

MJPEG

Request/response:

json
{"type":"mjpeg"}

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

FFmpeg Device

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

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

Configuration

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

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

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


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

Hardware

You DON'T need hardware acceleration if:

  • you're not using the FFmpeg source
  • you're using only #video=copy for the FFmpeg source
  • you're using only #audio=... (any audio) transcoding for the FFmpeg source

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

Important

  • Acceleration is disabled by default because it can be unstable (this may change in the future)
  • go2rtc can automatically detect supported hardware acceleration if enabled
  • go2rtc will enable hardware decoding only if hardware encoding is supported
  • go2rtc will use the same GPU for decoder and encoder
  • Intel and AMD will switch to a software decoder if the input codec isn't supported by the hardware decoder
  • NVIDIA will fail if the input codec isn't supported by the hardware decoder
  • Raspberry Pi always uses a software decoder
yaml
streams:
  # auto select hardware encoder
  camera1_hw: ffmpeg:rtsp://rtsp:[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=vaapi

Docker and Hass Addon

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

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

Intel iGPU

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

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

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

Read more here and here.

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.

Read more here and here.

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
  • 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`)


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

Video For Linux Two

Build on Ubuntu

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

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

--- METRICS ---