From 152719441e1e7a15845db074243c090893964f9d Mon Sep 17 00:00:00 2001
From: dadav <33197631+dadav@users.noreply.github.com>
Date: Wed, 10 Jan 2024 20:20:00 +0100
Subject: [PATCH] feat: Add signal related params to exec
---
README.md | 302 ++++++++++++++++++----------------
internal/exec/exec.go | 27 ++-
internal/exec/params.go | 34 ++++
internal/exec/params_linux.go | 88 ++++++++++
internal/exec/pipe.go | 15 +-
internal/exec/pipe_linux.go | 48 ++++++
6 files changed, 358 insertions(+), 156 deletions(-)
create mode 100644 internal/exec/params.go
create mode 100644 internal/exec/params_linux.go
create mode 100644 internal/exec/pipe_linux.go
diff --git a/README.md b/README.md
index aaed9410..b99e20eb 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# go2rtc
-[](https://github.com/AlexxIT/go2rtc/stargazers)
-[](https://hub.docker.com/r/alexxit/go2rtc)
+[](https://github.com/AlexxIT/go2rtc/stargazers)
+[](https://hub.docker.com/r/alexxit/go2rtc)
[](https://github.com/AlexxIT/go2rtc/releases)
[](https://goreportcard.com/report/github.com/AlexxIT/go2rtc)
@@ -20,9 +20,9 @@ Ultimate camera streaming application with support RTSP, WebRTC, HomeKit, FFmpeg
- on the fly transcoding for unsupported codecs via [FFmpeg](#source-ffmpeg)
- play audio files and live streams on some cameras with [speaker](#stream-to-camera)
- multi-source 2-way [codecs negotiation](#codecs-negotiation)
- - mixing tracks from different sources to single stream
- - auto match client supported codecs
- - [2-way audio](#two-way-audio) for some cameras
+ - mixing tracks from different sources to single stream
+ - auto match client supported codecs
+ - [2-way audio](#two-way-audio) for some cameras
- streaming from private networks via [ngrok](#module-ngrok)
- can be [integrated to](#module-api) any smart home platform or be used as [standalone app](#go2rtc-binary)
@@ -37,60 +37,60 @@ Ultimate camera streaming application with support RTSP, WebRTC, HomeKit, FFmpeg
---
-* [Fast start](#fast-start)
- * [go2rtc: Binary](#go2rtc-binary)
- * [go2rtc: Docker](#go2rtc-docker)
- * [go2rtc: Home Assistant Add-on](#go2rtc-home-assistant-add-on)
- * [go2rtc: Home Assistant Integration](#go2rtc-home-assistant-integration)
- * [go2rtc: Dev version](#go2rtc-dev-version)
-* [Configuration](#configuration)
- * [Module: Streams](#module-streams)
- * [Two way audio](#two-way-audio)
- * [Source: RTSP](#source-rtsp)
- * [Source: RTMP](#source-rtmp)
- * [Source: HTTP](#source-http)
- * [Source: ONVIF](#source-onvif)
- * [Source: FFmpeg](#source-ffmpeg)
- * [Source: FFmpeg Device](#source-ffmpeg-device)
- * [Source: Exec](#source-exec)
- * [Source: Echo](#source-echo)
- * [Source: Expr](#source-expr)
- * [Source: HomeKit](#source-homekit)
- * [Source: Bubble](#source-bubble)
- * [Source: DVRIP](#source-dvrip)
- * [Source: Tapo](#source-tapo)
- * [Source: Kasa](#source-kasa)
- * [Source: GoPro](#source-gopro)
- * [Source: Ivideon](#source-ivideon)
- * [Source: Hass](#source-hass)
- * [Source: ISAPI](#source-isapi)
- * [Source: Nest](#source-nest)
- * [Source: Roborock](#source-roborock)
- * [Source: WebRTC](#source-webrtc)
- * [Source: WebTorrent](#source-webtorrent)
- * [Incoming sources](#incoming-sources)
- * [Stream to camera](#stream-to-camera)
- * [Publish stream](#publish-stream)
- * [Module: API](#module-api)
- * [Module: RTSP](#module-rtsp)
- * [Module: RTMP](#module-rtmp)
- * [Module: WebRTC](#module-webrtc)
- * [Module: HomeKit](#module-homekit)
- * [Module: WebTorrent](#module-webtorrent)
- * [Module: ngrok](#module-ngrok)
- * [Module: Hass](#module-hass)
- * [Module: MP4](#module-mp4)
- * [Module: HLS](#module-hls)
- * [Module: MJPEG](#module-mjpeg)
- * [Module: Log](#module-log)
-* [Security](#security)
-* [Codecs filters](#codecs-filters)
-* [Codecs madness](#codecs-madness)
-* [Codecs negotiation](#codecs-negotiation)
-* [Projects using go2rtc](#projects-using-go2rtc)
-* [Camera experience](#cameras-experience)
-* [TIPS](#tips)
-* [FAQ](#faq)
+- [Fast start](#fast-start)
+ - [go2rtc: Binary](#go2rtc-binary)
+ - [go2rtc: Docker](#go2rtc-docker)
+ - [go2rtc: Home Assistant Add-on](#go2rtc-home-assistant-add-on)
+ - [go2rtc: Home Assistant Integration](#go2rtc-home-assistant-integration)
+ - [go2rtc: Dev version](#go2rtc-dev-version)
+- [Configuration](#configuration)
+ - [Module: Streams](#module-streams)
+ - [Two way audio](#two-way-audio)
+ - [Source: RTSP](#source-rtsp)
+ - [Source: RTMP](#source-rtmp)
+ - [Source: HTTP](#source-http)
+ - [Source: ONVIF](#source-onvif)
+ - [Source: FFmpeg](#source-ffmpeg)
+ - [Source: FFmpeg Device](#source-ffmpeg-device)
+ - [Source: Exec](#source-exec)
+ - [Source: Echo](#source-echo)
+ - [Source: Expr](#source-expr)
+ - [Source: HomeKit](#source-homekit)
+ - [Source: Bubble](#source-bubble)
+ - [Source: DVRIP](#source-dvrip)
+ - [Source: Tapo](#source-tapo)
+ - [Source: Kasa](#source-kasa)
+ - [Source: GoPro](#source-gopro)
+ - [Source: Ivideon](#source-ivideon)
+ - [Source: Hass](#source-hass)
+ - [Source: ISAPI](#source-isapi)
+ - [Source: Nest](#source-nest)
+ - [Source: Roborock](#source-roborock)
+ - [Source: WebRTC](#source-webrtc)
+ - [Source: WebTorrent](#source-webtorrent)
+ - [Incoming sources](#incoming-sources)
+ - [Stream to camera](#stream-to-camera)
+ - [Publish stream](#publish-stream)
+ - [Module: API](#module-api)
+ - [Module: RTSP](#module-rtsp)
+ - [Module: RTMP](#module-rtmp)
+ - [Module: WebRTC](#module-webrtc)
+ - [Module: HomeKit](#module-homekit)
+ - [Module: WebTorrent](#module-webtorrent)
+ - [Module: ngrok](#module-ngrok)
+ - [Module: Hass](#module-hass)
+ - [Module: MP4](#module-mp4)
+ - [Module: HLS](#module-hls)
+ - [Module: MJPEG](#module-mjpeg)
+ - [Module: Log](#module-log)
+- [Security](#security)
+- [Codecs filters](#codecs-filters)
+- [Codecs madness](#codecs-madness)
+- [Codecs negotiation](#codecs-negotiation)
+- [Projects using go2rtc](#projects-using-go2rtc)
+- [Camera experience](#cameras-experience)
+- [TIPS](#tips)
+- [FAQ](#faq)
## Fast start
@@ -134,8 +134,8 @@ Container [alexxit/go2rtc](https://hub.docker.com/r/alexxit/go2rtc) with support
[](https://my.home-assistant.io/redirect/supervisor_addon/?addon=a889bffc_go2rtc&repository_url=https%3A%2F%2Fgithub.com%2FAlexxIT%2Fhassio-addons)
1. Install Add-On:
- - Settings > Add-ons > Plus > Repositories > Add `https://github.com/AlexxIT/hassio-addons`
- - go2rtc > Install > Start
+ - Settings > Add-ons > Plus > Repositories > Add `https://github.com/AlexxIT/hassio-addons`
+ - go2rtc > Install > Start
2. Setup [Integration](#module-hass)
### go2rtc: Home Assistant Integration
@@ -152,7 +152,7 @@ Latest, but maybe unstable version:
## Configuration
-- by default go2rtc will search `go2rtc.yaml` in the current work dirrectory
+- 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
@@ -230,7 +230,7 @@ streams:
amcrest_doorbell:
- rtsp://username:password@192.168.1.123:554/cam/realmonitor?channel=1&subtype=0#backchannel=0
unifi_camera: rtspx://192.168.1.123:7441/fD6ouM72bWoFijxK
- glichy_camera: ffmpeg:rstp://username:password@192.168.1.123/live/ch00_1
+ glichy_camera: ffmpeg:rstp://username:password@192.168.1.123/live/ch00_1
```
**Recommendations**
@@ -249,7 +249,7 @@ streams:
Format: `rtsp...#{param1}#{param2}#{param3}`
- Add custom timeout `#timeout=30` (in seconds)
-- Ignore audio - `#media=video` or ignore video - `#media=audio`
+- 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...`
@@ -258,7 +258,7 @@ Format: `rtsp...#{param1}#{param2}#{param3}`
```yaml
streams:
# WebSocket with authorization, RTSP - without
- axis-rtsp-ws: rtsp://192.168.1.123:4567/axis-media/media.amp?overview=0&camera=1&resolution=1280x720&videoframeskipmode=empty&Axis-Orig-Sw=true#transport=ws://user:pass@192.168.1.123:4567/rtsp-over-websocket
+ axis-rtsp-ws: rtsp://192.168.1.123:4567/axis-media/media.amp?overview=0&camera=1&resolution=1280x720&videoframeskipmode=empty&Axis-Orig-Sw=true#transport=ws://user:pass@192.168.1.123:4567/rtsp-over-websocket
# WebSocket without authorization, RTSP - with
dahua-rtsp-ws: rtsp://user:pass@192.168.1.123/cam/realmonitor?channel=1&subtype=1&proto=Private3#transport=ws://192.168.1.123/rtspoverwebsocket
```
@@ -287,7 +287,7 @@ Source also support HTTP and TCP streams with autodetection for different format
streams:
# [HTTP-FLV] stream in video/x-flv format
http_flv: http://192.168.1.123:20880/api/camera/stream/780900131155/657617
-
+
# [JPEG] snapshots from Dahua camera, will be converted to MJPEG stream
dahua_snap: http://admin:password@192.168.1.123/cgi-bin/snapshot.cgi?channel=1
@@ -305,7 +305,7 @@ streams:
#### Source: ONVIF
-*[New in v1.5.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.5.0)*
+_[New in v1.5.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.5.0)_
The source is not very useful if you already know RTSP and snapshot links for your camera. But it can be useful if you don't.
@@ -354,7 +354,7 @@ But you can override them via YAML config. You can also add your own formats to
```yaml
ffmpeg:
- bin: ffmpeg # path to ffmpeg binary
+ bin: ffmpeg # path to ffmpeg binary
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 5000000 -i {input}"
@@ -390,7 +390,7 @@ Format: `ffmpeg:device?{input-params}#{param1}#{param2}#{param3}`
```yaml
streams:
- linux_usbcam: ffmpeg:device?video=0&video_size=1280x720#video=h264
+ 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
```
@@ -399,12 +399,23 @@ streams:
#### Source: Exec
-Exec source can run any external application and expect data from it. Two transports are supported - **pipe** (*from [v1.5.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.5.0)*) and **RTSP**.
+Exec source can run any external application and expect data from it. Two transports are supported - **pipe** (_from [v1.5.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.5.0)_) and **RTSP**.
If you want to use **RTSP** transport - the command must contain the `{output}` argument in any place. On launch, it will be replaced by the local address of the RTSP server.
**pipe** reads data from app stdout in different formats: **MJPEG**, **H.264/H.265 bitstream**, **MPEG-TS**.
+Pipe commands support two parameters:
+
+- **killsignal**: Signal which will be send to stop the process (default: sigkill)
+- **killtimeout**: Time in seconds after the process will killed with sigkill (default: 5)
+
+The **killtimeout** parameter is only relevant if **killsignal** is not sigkill.
+Setting **killtimeout** to a negative number (or zero) will result in an immediate SIGKILL.
+See `man 7 signal` to get a full list of all the signals.
+
+Format: `exec:{command}#{param1}#{param2}`
+
The source can be used with:
- [FFmpeg](https://ffmpeg.org/) - go2rtc ffmpeg source just a shortcut to exec source
@@ -417,6 +428,7 @@ 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 -
+ canon: exec:gphoto2 --capture-movie --stdout#killsignal=sigint
```
#### Source: Echo
@@ -434,7 +446,7 @@ streams:
#### Source: Expr
-*[New in v1.8.2](https://github.com/AlexxIT/go2rtc/releases/tag/v1.8.2)*
+_[New in v1.8.2](https://github.com/AlexxIT/go2rtc/releases/tag/v1.8.2)_
Like `echo` source, but uses the built-in [expr](https://github.com/antonmedv/expr) expression language ([read more](https://github.com/AlexxIT/go2rtc/blob/master/internal/expr/README.md)).
@@ -473,7 +485,7 @@ RTSP link with "normal" audio for any player: `rtsp://192.168.1.123:8554/aqara_g
#### Source: Bubble
-*[New in v1.6.1](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.1)*
+_[New in v1.6.1](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.1)_
Other names: [ESeeCloud](http://www.eseecloud.com/), [dvr163](http://help.dvr163.com/).
@@ -487,7 +499,7 @@ streams:
#### Source: DVRIP
-*[New in v1.2.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.2.0)*
+_[New in v1.2.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.2.0)_
Other names: DVR-IP, NetSurveillance, Sofia protocol (NETsurveillance ActiveX plugin XMeye SDK).
@@ -507,7 +519,7 @@ streams:
#### Source: Tapo
-*[New in v1.2.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.2.0)*
+_[New in v1.2.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.2.0)_
[TP-Link Tapo](https://www.tapo.com/) proprietary camera protocol with **two way audio** support.
@@ -533,7 +545,7 @@ echo -n "cloud password" | shasum -a 256 | awk '{print toupper($0)}'
#### Source: Kasa
-*[New in v1.7.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.7.0)*
+_[New in v1.7.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.7.0)_
[TP-Link Kasa](https://www.kasasmart.com/) non-standard protocol [more info](https://medium.com/@hu3vjeen/reverse-engineering-tp-link-kc100-bac4641bf1cd).
@@ -544,7 +556,7 @@ streams:
#### Source: GoPro
-*[New in v1.8.3](https://github.com/AlexxIT/go2rtc/releases/tag/v1.8.3)*
+_[New in v1.8.3](https://github.com/AlexxIT/go2rtc/releases/tag/v1.8.3)_
Support streaming from [GoPro](https://gopro.com/) cameras, connected via USB or Wi-Fi to Linux, Mac, Windows. [Read more](https://github.com/AlexxIT/go2rtc/tree/master/internal/gopro).
@@ -568,14 +580,14 @@ Support import camera links from [Home Assistant](https://www.home-assistant.io/
```yaml
hass:
- config: "/config" # skip this setting if you Hass Add-on user
+ config: "/config" # skip this setting if you Hass Add-on user
streams:
- generic_camera: hass:Camera1 # Settings > Integrations > Integration Name
+ generic_camera: hass:Camera1 # Settings > Integrations > Integration Name
aqara_g3: hass:Camera-Hub-G3-AB12
```
-**WebRTC Cameras** (*from [v1.6.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.0)*)
+**WebRTC Cameras** (_from [v1.6.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.0)_)
Any cameras in WebRTC format are supported. But at the moment Home Assistant only supports some [Nest](https://www.home-assistant.io/integrations/nest/) cameras in this fomat.
@@ -595,7 +607,7 @@ By default, the Home Assistant API does not allow you to get dynamic RTSP link t
#### Source: ISAPI
-*[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)*
+_[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)_
This source type support only backchannel audio for Hikvision ISAPI protocol. So it should be used as second source in addition to the RTSP protocol.
@@ -608,7 +620,7 @@ streams:
#### Source: Nest
-*[New in v1.6.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.0)*
+_[New in v1.6.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.0)_
Currently only WebRTC cameras are supported. Stream reconnects every 5 minutes.
@@ -621,7 +633,7 @@ streams:
#### Source: Roborock
-*[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)*
+_[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)_
This source type support Roborock vacuums with cameras. Known working models:
@@ -634,7 +646,7 @@ If you have graphic pin for your vacuum - add it as numeric pin (lines: 123, 456
#### Source: WebRTC
-*[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)*
+_[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)_
This source type support four connection formats.
@@ -646,24 +658,24 @@ This source type support four connection formats.
This format is only supported in go2rtc. Unlike WHEP it supports asynchronous WebRTC connection and two way audio.
-**openipc** (*from [v1.7.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.7.0)*)
+**openipc** (_from [v1.7.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.7.0)_)
Support connection to [OpenIPC](https://openipc.org/) cameras.
-**wyze** (*from [v1.6.1](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.1)*)
+**wyze** (_from [v1.6.1](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.1)_)
Supports connection to [Wyze](https://www.wyze.com/) cameras, using WebRTC protocol. You can use [docker-wyze-bridge](https://github.com/mrlt8/docker-wyze-bridge) project to get connection credentials.
-**kinesis** (*from [v1.6.1](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.1)*)
+**kinesis** (_from [v1.6.1](https://github.com/AlexxIT/go2rtc/releases/tag/v1.6.1)_)
Supports [Amazon Kinesis Video Streams](https://aws.amazon.com/kinesis/video-streams/), using WebRTC protocol. You need to specify signalling WebSocket URL with all credentials in query params, `client_id` and `ice_servers` list in [JSON format](https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer).
```yaml
streams:
- webrtc-whep: webrtc:http://192.168.1.123:1984/api/webrtc?src=camera1
- webrtc-go2rtc: webrtc:ws://192.168.1.123:1984/api/ws?src=camera1
+ webrtc-whep: webrtc:http://192.168.1.123:1984/api/webrtc?src=camera1
+ webrtc-go2rtc: webrtc:ws://192.168.1.123:1984/api/ws?src=camera1
webrtc-openipc: webrtc:ws://192.168.1.123/webrtc_ws#format=openipc#ice_servers=[{"urls":"stun:stun.kinesisvideo.eu-north-1.amazonaws.com:443"}]
- webrtc-wyze: webrtc:http://192.168.1.123:5000/signaling/camera1?kvs#format=wyze
+ webrtc-wyze: webrtc:http://192.168.1.123:5000/signaling/camera1?kvs#format=wyze
webrtc-kinesis: webrtc:wss://...amazonaws.com/?...#format=kinesis#client_id=...#ice_servers=[{...},{...}]
```
@@ -671,7 +683,7 @@ streams:
#### Source: WebTorrent
-*[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)*
+_[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)_
This source can get a stream from another go2rtc via [WebTorrent](#module-webtorrent) protocol.
@@ -711,7 +723,7 @@ By default, go2rtc establishes a connection to the source when any client reques
#### Incoming: Browser
-*[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)*
+_[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)_
You can turn the browser of any PC or mobile into an IP-camera with support video and two way audio. Or even broadcast your PC screen:
@@ -723,7 +735,7 @@ You can turn the browser of any PC or mobile into an IP-camera with support vide
#### Incoming: WebRTC/WHIP
-*[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)*
+_[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)_
You can use **OBS Studio** or any other broadcast software with [WHIP](https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html) protocol support. This standard has not yet been approved. But you can download OBS Studio [dev version](https://github.com/obsproject/obs-studio/actions/runs/3969201209):
@@ -731,7 +743,7 @@ You can use **OBS Studio** or any other broadcast software with [WHIP](https://w
#### Stream to camera
-*[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)*
+_[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)_
go2rtc support play audio files (ex. music or [TTS](https://www.home-assistant.io/integrations/#text-to-speech)) and live streams (ex. radio) on cameras with [two way audio](#two-way-audio) support (RTSP/ONVIF cameras, TP-Link Tapo, Hikvision ISAPI, Roborock vacuums, any Browser).
@@ -741,7 +753,7 @@ API example:
POST http://localhost:1984/api/streams?dst=camera1&src=ffmpeg:http://example.com/song.mp3#audio=pcma#input=file
```
-- you can stream: local files, web files, live streams or any format, supported by FFmpeg
+- you can stream: local files, web files, live streams or any format, supported by FFmpeg
- you should use [ffmpeg source](#source-ffmpeg) 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](#source-tapo))
@@ -753,7 +765,7 @@ POST http://localhost:1984/api/streams?dst=camera1&src=ffmpeg:http://example.com
### Publish stream
-*[New in v1.8.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.8.0)*
+_[New in v1.8.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.8.0)_
You can publish any stream to streaming services (YouTube, Telegram, etc.) via RTMP/RTMPS. Important:
@@ -804,22 +816,22 @@ The HTTP API is the main part for interacting with the application. Default addr
```yaml
api:
- listen: ":1984" # default ":1984", HTTP API port ("" - disabled)
- username: "admin" # default "", Basic auth for WebUI
- password: "pass" # default "", Basic auth for WebUI
- base_path: "/rtc" # default "", API prefix for serve on suburl (/api => /rtc/api)
- static_dir: "www" # default "", folder for static files (custom web interface)
- origin: "*" # default "", allow CORS requests (only * supported)
+ listen: ":1984" # default ":1984", HTTP API port ("" - disabled)
+ username: "admin" # default "", Basic auth for WebUI
+ password: "pass" # default "", Basic auth for WebUI
+ base_path: "/rtc" # default "", API prefix for serve 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
+ tls_cert: | # default "", PEM-encoded fullchain certificate for HTTPS
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
- tls_key: | # default "", PEM-encoded private key for HTTPS
+ 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
+ unix_listen: "/tmp/go2rtc.sock" # default "", unix socket listener for API
```
**PS:**
@@ -835,10 +847,10 @@ You can enable external password protection for your RTSP streams. Password prot
```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
+ 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:
@@ -852,15 +864,15 @@ Read more about [codecs filters](#codecs-filters).
### Module: RTMP
-*[New in v1.8.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.8.0)*
+_[New in v1.8.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.8.0)_
You can get any stream as RTMP-stream: `rtmp://192.168.1.123/{stream_name}`. Only H264/AAC codecs supported right now.
-[Incoming stream](#incoming-sources) in RTMP-format tested only with [OBS Studio](https://obsproject.com/) and Dahua camera. Different FFmpeg versions has differnt problems with this format.
+[Incoming stream](#incoming-sources) in RTMP-format tested only with [OBS Studio](https://obsproject.com/) and Dahua camera. Different FFmpeg versions has differnt problems with this format.
```yaml
rtmp:
- listen: ":1935" # by default - disabled!
+ listen: ":1935" # by default - disabled!
```
### Module: WebRTC
@@ -878,7 +890,7 @@ But about 10-20% of users may need to configure additional settings for external
```yaml
webrtc:
- listen: ":8555" # address of your local server and port (TCP/UDP)
+ listen: ":8555" # address of your local server and port (TCP/UDP)
```
**Static public IP**
@@ -889,7 +901,7 @@ webrtc:
```yaml
webrtc:
candidates:
- - 216.58.210.174:8555 # if you have static public IP-address
+ - 216.58.210.174:8555 # if you have static public IP-address
```
**Dynamic public IP**
@@ -901,7 +913,7 @@ webrtc:
```yaml
webrtc:
candidates:
- - stun:8555 # if you have dynamic public IP-address
+ - stun:8555 # if you have dynamic public IP-address
```
**Private IP**
@@ -932,7 +944,7 @@ webrtc:
### Module: HomeKit
-*[New in v1.7.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.7.0)*
+_[New in v1.7.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.7.0)_
HomeKit module can work in two modes:
@@ -949,7 +961,7 @@ HomeKit module can work in two modes:
streams:
dahua1: rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=0
homekit:
- dahua1: # same stream ID from streams list, default PIN - 19550224
+ dahua1: # same stream ID from streams list, default PIN - 19550224
```
**Full config**
@@ -958,15 +970,15 @@ homekit:
streams:
dahua1:
- rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=0
- - ffmpeg:dahua1#video=h264#hardware # if your camera doesn't support H264, important for HomeKit
- - ffmpeg:dahua1#audio=opus # only OPUS audio supported by HomeKit
+ - 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
+ 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**
@@ -978,15 +990,15 @@ homekit:
streams:
aqara1:
- homekit://...
- - ffmpeg:aqara1#audio=aac#audio=opus # optional audio transcoding
+ - ffmpeg:aqara1#audio=aac#audio=opus # optional audio transcoding
homekit:
- aqara1: # same stream ID from streams list
+ aqara1: # same stream ID from streams list
```
### Module: WebTorrent
-*[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)*
+_[New in v1.3.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.3.0)_
This module support:
@@ -1003,9 +1015,9 @@ You can create permanent external links in go2rtc config:
```yaml
webtorrent:
shares:
- super-secret-share: # share name, should be unique among all go2rtc users!
+ super-secret-share: # share name, should be unique among all go2rtc users!
pwd: super-secret-password
- src: rtsp-dahua1 # stream name from streams section
+ src: rtsp-dahua1 # stream name from streams section
```
Link example: https://alexxit.github.io/go2rtc/#share=02SNtgjKXY&pwd=wznEQqznxW&media=video+audio
@@ -1057,12 +1069,12 @@ version: "2"
authtoken: eW91IHNoYWxsIG5vdCBwYXNzCnlvdSBzaGFsbCBub3QgcGFzcw
tunnels:
api:
- addr: 1984 # use the same port as in go2rtc config
+ addr: 1984 # use the same port as in go2rtc config
proto: http
basic_auth:
- - admin:password # you can set login/pass for your web interface
+ - admin:password # you can set login/pass for your web interface
webrtc:
- addr: 8555 # use the same port as in go2rtc config
+ addr: 8555 # use the same port as in go2rtc config
proto: tcp
```
@@ -1118,7 +1130,7 @@ 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)
+- 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`)
@@ -1127,11 +1139,11 @@ API examples:
Read more about [codecs filters](#codecs-filters).
-**PS.** Rotate and scale params don't use transcoding and change video using metadata.
+**PS.** Rotate and scale params don't use transcoding and change video using metadata.
### Module: HLS
-*[New in v1.1.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.1.0)*
+_[New in v1.1.0](https://github.com/AlexxIT/go2rtc/releases/tag/v1.1.0)_
[HLS](https://en.wikipedia.org/wiki/HTTP_Live_Streaming) is the worst technology for real-time streaming. It can only be useful on devices that do not support more modern technology, like [WebRTC](#module-webrtc), [MSE/MP4](#module-mp4).
@@ -1168,7 +1180,7 @@ API examples:
- MJPEG stream: `http://192.168.1.123:1984/api/stream.mjpeg?src=camera1`
- JPEG snapshots: `http://192.168.1.123:1984/api/frame.jpeg?src=camera1`
- - You can use `width`/`w` and/or `height`/`h` params
+ - You can use `width`/`w` and/or `height`/`h` params
- You can use `rotate` param with `90`, `180`, `270` or `-90` values
- You can use `hardware`/`hw` param [read more](https://github.com/AlexxIT/go2rtc/wiki/Hardware-acceleration)
@@ -1178,7 +1190,7 @@ You can set different log levels for different modules.
```yaml
log:
- level: info # default level
+ level: info # default level
api: trace
exec: debug
ngrok: info
@@ -1240,18 +1252,18 @@ Some examples:
`AVC/H.264` video can be played almost anywhere. But `HEVC/H.265` has a lot of limitations in supporting with different devices and browsers. It's all about patents and money, you can't do anything about it.
-| Device | WebRTC | MSE | HTTP* | HLS |
-|--------------------------------------------------------------------------|-----------------------------------------|-----------------------------------------|----------------------------------------------|-----------------------------|
-| *latency* | best | medium | bad | bad |
-| - Desktop Chrome 107+
- Desktop Edge
- Android Chrome 107+ | H264
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][1] | no | no | no | H264, H265
AAC, FLAC* |
+| Device | WebRTC | MSE | HTTP\* | HLS |
+| ------------------------------------------------------------------------ | ---------------------------------------- | --------------------------------------- | -------------------------------------------- | ---------------------------- |
+| _latency_ | best | medium | bad | bad |
+| - Desktop Chrome 107+
- Desktop Edge
- Android Chrome 107+ | H264
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][1] | no | no | no | H264, H265
AAC, FLAC\* |
[1]: https://apps.apple.com/app/home-assistant/id1099568401
-`HTTP*` - HTTP Progressive Streaming, not related with [Progressive download](https://en.wikipedia.org/wiki/Progressive_download), because the file has no size and no end
+`HTTP*` - HTTP Progressive Streaming, not related with [Progressive download](https://en.wikipedia.org/wiki/Progressive_download), because the file has no size and no end
- Chrome H265: [read this](https://chromestatus.com/feature/5186511939567616) and [read this](https://github.com/StaZhu/enable-chromium-hevc-hardware-decoding)
- Edge H265: [read this](https://www.reddit.com/r/MicrosoftEdge/comments/v9iw8k/enable_hevc_support_in_edge/)
diff --git a/internal/exec/exec.go b/internal/exec/exec.go
index 36dacfaa..cf3aa7e6 100644
--- a/internal/exec/exec.go
+++ b/internal/exec/exec.go
@@ -20,6 +20,12 @@ import (
"github.com/rs/zerolog"
)
+type Params struct {
+ KillSignal os.Signal
+ Command string
+ KillTimeout time.Duration
+}
+
func Init() {
rtsp.HandleFunc(func(conn *pkg.Conn) bool {
waitersMu.Lock()
@@ -47,7 +53,12 @@ func Init() {
func execHandle(url string) (core.Producer, error) {
var path string
- args := shell.QuoteSplit(url[5:]) // remove `exec:`
+ params, err := parseParams(url)
+ if err != nil {
+ return nil, err
+ }
+
+ args := shell.QuoteSplit(params.Command[5:]) // remove `exec:`
for i, arg := range args {
if arg == "{output}" {
if rtsp.Port == "" {
@@ -67,14 +78,14 @@ func execHandle(url string) (core.Producer, error) {
}
if path == "" {
- return handlePipe(url, cmd)
+ return handlePipe(url, cmd, params)
}
return handleRTSP(url, path, cmd)
}
-func handlePipe(url string, cmd *exec.Cmd) (core.Producer, error) {
- r, err := PipeCloser(cmd)
+func handlePipe(_ string, cmd *exec.Cmd, params *Params) (core.Producer, error) {
+ r, err := PipeCloser(cmd, params)
if err != nil {
return nil, err
}
@@ -144,6 +155,8 @@ func handleRTSP(url, path string, cmd *exec.Cmd) (core.Producer, error) {
// internal
-var log zerolog.Logger
-var waiters = map[string]chan core.Producer{}
-var waitersMu sync.Mutex
+var (
+ log zerolog.Logger
+ waiters = map[string]chan core.Producer{}
+ waitersMu sync.Mutex
+)
diff --git a/internal/exec/params.go b/internal/exec/params.go
new file mode 100644
index 00000000..3d736a4b
--- /dev/null
+++ b/internal/exec/params.go
@@ -0,0 +1,34 @@
+//go:build !linux
+
+package exec
+
+import (
+ "fmt"
+ "net/url"
+ "runtime"
+ "strings"
+
+ "github.com/AlexxIT/go2rtc/internal/streams"
+)
+
+func parseParams(s string) (*Params, error) {
+ args := &Params{
+ Command: s,
+ }
+
+ var query url.Values
+ if i := strings.IndexByte(s, '#'); i > 0 {
+ query = streams.ParseQuery(s[i+1:])
+ args.Command = s[:i]
+ }
+
+ if _, ok := query["killsignal"]; ok {
+ return nil, fmt.Errorf("killsignal is not supported this %s", runtime.GOOS)
+ }
+
+ if _, ok := query["killtimeout"]; ok {
+ return nil, fmt.Errorf("killtimeout is not supported in %s", runtime.GOOS)
+ }
+
+ return args, nil
+}
diff --git a/internal/exec/params_linux.go b/internal/exec/params_linux.go
new file mode 100644
index 00000000..6a7ce444
--- /dev/null
+++ b/internal/exec/params_linux.go
@@ -0,0 +1,88 @@
+package exec
+
+import (
+ "fmt"
+ "net/url"
+ "os"
+ "strconv"
+ "strings"
+ "syscall"
+ "time"
+
+ "github.com/AlexxIT/go2rtc/internal/streams"
+)
+
+func parseParams(s string) (*Params, error) {
+ args := &Params{
+ KillSignal: syscall.SIGKILL,
+ KillTimeout: 5 * time.Second,
+ Command: s,
+ }
+
+ var query url.Values
+ if i := strings.IndexByte(s, '#'); i > 0 {
+ query = streams.ParseQuery(s[i+1:])
+ args.Command = s[:i]
+ }
+
+ if val, ok := query["killsignal"]; ok {
+ if sig, err := parseSignal(val[0]); err == nil {
+ args.KillSignal = sig
+ } else {
+ return nil, fmt.Errorf("could not parse killsignal param (%s)", val[0])
+ }
+ }
+
+ if val, ok := query["killtimeout"]; ok {
+ if i, err := strconv.Atoi(val[0]); err == nil {
+ args.KillTimeout = time.Duration(i) * time.Second
+ } else {
+ return nil, fmt.Errorf("could not convert killtimeout param (%s) to int", val[0])
+ }
+ }
+
+ return args, nil
+}
+
+func parseSignal(signalString string) (os.Signal, error) {
+ signalMap := map[string]os.Signal{
+ "sighup": syscall.SIGHUP,
+ "sigint": syscall.SIGINT,
+ "sigquit": syscall.SIGQUIT,
+ "sigill": syscall.SIGILL,
+ "sigtrap": syscall.SIGTRAP,
+ "sigabrt": syscall.SIGABRT,
+ "sigbus": syscall.SIGBUS,
+ "sigfpe": syscall.SIGFPE,
+ "sigkill": syscall.SIGKILL,
+ "sigusr1": syscall.SIGUSR1,
+ "sigsegv": syscall.SIGSEGV,
+ "sigusr2": syscall.SIGUSR2,
+ "sigpipe": syscall.SIGPIPE,
+ "sigalrm": syscall.SIGALRM,
+ "sigterm": syscall.SIGTERM,
+ "sigchld": syscall.SIGCHLD,
+ "sigcont": syscall.SIGCONT,
+ "sigstop": syscall.SIGSTOP,
+ "sigtstp": syscall.SIGTSTP,
+ "sigttin": syscall.SIGTTIN,
+ "sigttou": syscall.SIGTTOU,
+ "sigurg": syscall.SIGURG,
+ "sigxcpu": syscall.SIGXCPU,
+ "sigxfsz": syscall.SIGXFSZ,
+ "sigvtalrm": syscall.SIGVTALRM,
+ "sigprof": syscall.SIGPROF,
+ "sigwinch": syscall.SIGWINCH,
+ "sigio": syscall.SIGIO,
+ "sigpoll": syscall.SIGPOLL,
+ "sigpwr": syscall.SIGPWR,
+ "sigsys": syscall.SIGSYS,
+ }
+
+ signalValue, ok := signalMap[strings.ToLower(signalString)]
+ if !ok {
+ return nil, fmt.Errorf("invalid signal: %s", signalString)
+ }
+
+ return signalValue, nil
+}
diff --git a/internal/exec/pipe.go b/internal/exec/pipe.go
index a76f381c..9c40cccc 100644
--- a/internal/exec/pipe.go
+++ b/internal/exec/pipe.go
@@ -1,3 +1,5 @@
+//go:build !linux
+
package exec
import (
@@ -9,22 +11,27 @@ import (
)
// PipeCloser - return StdoutPipe that Kill cmd on Close call
-func PipeCloser(cmd *exec.Cmd) (io.ReadCloser, error) {
+func PipeCloser(cmd *exec.Cmd, params *Params) (io.ReadCloser, error) {
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
// add buffer for pipe reader to reduce syscall
- return pipeCloser{bufio.NewReaderSize(stdout, core.BufferSize), stdout, cmd}, nil
+ return pipeCloser{bufio.NewReaderSize(stdout, core.BufferSize), stdout, cmd, params}, nil
}
type pipeCloser struct {
io.Reader
io.Closer
- cmd *exec.Cmd
+ cmd *exec.Cmd
+ params *Params
}
func (p pipeCloser) Close() error {
- return core.Any(p.Closer.Close(), p.cmd.Process.Kill(), p.cmd.Wait())
+ finished := make(chan bool)
+
+ err := core.Any(p.Closer.Close(), p.cmd.Process.Kill(), p.cmd.Wait())
+ finished <- true
+ return err
}
diff --git a/internal/exec/pipe_linux.go b/internal/exec/pipe_linux.go
new file mode 100644
index 00000000..9b28702e
--- /dev/null
+++ b/internal/exec/pipe_linux.go
@@ -0,0 +1,48 @@
+package exec
+
+import (
+ "bufio"
+ "io"
+ "os/exec"
+ "syscall"
+ "time"
+
+ "github.com/AlexxIT/go2rtc/pkg/core"
+)
+
+// PipeCloser - return StdoutPipe that Kill cmd on Close call
+func PipeCloser(cmd *exec.Cmd, params *Params) (io.ReadCloser, error) {
+ stdout, err := cmd.StdoutPipe()
+ if err != nil {
+ return nil, err
+ }
+
+ // add buffer for pipe reader to reduce syscall
+ return pipeCloser{bufio.NewReaderSize(stdout, core.BufferSize), stdout, cmd, params}, nil
+}
+
+type pipeCloser struct {
+ io.Reader
+ io.Closer
+ cmd *exec.Cmd
+ params *Params
+}
+
+func (p pipeCloser) Close() error {
+ finished := make(chan bool)
+
+ if p.params.KillSignal != syscall.SIGKILL {
+ go func() {
+ select {
+ case <-time.After(p.params.KillTimeout):
+ p.cmd.Process.Kill()
+ break
+ case <-finished:
+ break
+ }
+ }()
+ }
+ err := core.Any(p.Closer.Close(), p.cmd.Process.Signal(p.params.KillSignal), p.cmd.Wait())
+ finished <- true
+ return err
+}