Compare commits

..

7 Commits

Author SHA1 Message Date
Alexey Khit 863bf503e2 Fix empty remote for webrtc 2022-08-21 18:00:02 +03:00
Alexey Khit 7a3a1a5336 Fix empty producer track 2022-08-21 17:51:36 +03:00
Alexey Khit b851041caa Fix concurrent map iteration for Track 2022-08-21 17:51:19 +03:00
Alexey Khit a4acde6d95 Fix two connections to Dahua camera simultaniosly 2022-08-21 17:26:27 +03:00
Alexey Khit 1139d4fcad Fix wrong RTSP Transport responses 2022-08-21 16:58:35 +03:00
Alexey Khit 159ad52277 Fix RTSP Content-Base requests 2022-08-21 16:45:43 +03:00
Alexey Khit 87bc07e404 Update readme 2022-08-21 13:38:42 +03:00
5 changed files with 111 additions and 22 deletions
+64 -15
View File
@@ -5,9 +5,9 @@
- zero-dependency and zero-config small [app for all OS](#installation) (Windows, macOS, Linux, ARM)
- zero-delay for all supported protocols (lowest possible streaming latency)
- zero-load on CPU for supported codecs
- on the fly transcoding for unsupported codecs [via FFmpeg](#source-ffmpeg)
- on the fly transcoding for unsupported codecs via [FFmpeg](#source-ffmpeg)
- multi-source 2-way [codecs negotiation](#codecs-negotiation)
- streaming from private networks via [Ngrok or SSH-tunnels](#module-webrtc)
- streaming from private networks via [Ngrok](#module-webrtc)
**Inspired by:**
@@ -45,7 +45,24 @@ streams:
![](codecs.svg)
## Installation
## Fast start
1. Download [binary](#go2rtc-binary) or use [Docker](#go2rtc-docker) or [Home Assistant Add-on](#go2rtc-home-assistant-add-on)
2. Open web interface [http://localhost:1984/](http://localhost:1984/)
**Optionally:**
- add your [streams](#module-streams) to [config](#configuration) file
- setup [external access](#module-webrtc) to webrtc
- setup [external access](#module-ngrok) to web interface
- install [ffmpeg](#source-ffmpeg) for transcoding
**Developers:**
- write your own [web interface](#module-api)
- integrate [web api](#module-api) into your smart home platform
### go2rtc: Binary
Download binary for your OS from [latest release](https://github.com/AlexxIT/go2rtc/releases/):
@@ -61,6 +78,23 @@ Download binary for your OS from [latest release](https://github.com/AlexxIT/go2
Don't forget to fix the rights `chmod +x go2rtc_linux_xxx` on Linux and Mac.
### go2rtc: Home Assistant Add-on
[![](https://my.home-assistant.io/badges/supervisor_addon.svg)](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
2. Setup [Integration](#module-hass)
**Optionally:**
- create `go2rtc.yaml` in your Home Assistant [config](https://www.home-assistant.io/docs/configuration) folder
### go2rtc: Docker
Container [alexxit/go2rtc](https://hub.docker.com/r/alexxit/go2rtc) with support `amd64`, `386`, `arm64`, `arm`. This container same as [Home Assistant Add-on](#go2rtc-home-assistant-add-on), but can be used separately from the Home Assistant. Container has preinstalled [FFmpeg](#source-ffmpeg) and [Ngrok](#module-ngrok) applications.
## Configuration
Create file `go2rtc.yaml` next to the app.
@@ -76,7 +110,7 @@ Available modules:
- [streams](#module-streams)
- [api](#module-api) - HTTP API (important for WebRTC support)
- [rtsp](#module-rtsp) - RTSP Server (important for FFmpeg support)
- [webrtc](#module-webrtc) - WebRTC Server (important for external access)
- [webrtc](#module-webrtc) - WebRTC Server
- [ngrok](#module-ngrok) - Ngrok integration (external access for private network)
- [ffmpeg](#source-ffmpeg) - FFmpeg integration
- [hass](#module-hass) - Home Assistant integration
@@ -202,7 +236,7 @@ streams:
### Module: API
The HTTP API is the main part for interacting with the application.
The HTTP API is the main part for interacting with the application. Default address: `http://127.0.0.1:1984/`.
- you can use WebRTC only when HTTP API enabled
- you can disable HTTP API with `listen: ""` and use, for example, only RTSP client/server protocol
@@ -212,11 +246,15 @@ The HTTP API is the main part for interacting with the application.
```yaml
api:
listen: ":1984" # HTTP API port ("" - disabled)
base_path: "" # API prefix for serve on suburl
static_dir: "www" # folder for static files ("" - disabled)
listen: ":1984" # HTTP API port ("" - disabled)
base_path: "" # API prefix for serve on suburl
static_dir: "" # folder for static files (custom web interface)
```
**PS. go2rtc** don't provide HTTPS or password protection. Use [Nginx](https://nginx.org/) or [Ngrok](#module-ngrok) or [Home Assistant Add-on](#go2rtc-home-assistant-add-on) for this tasks.
**PS2.** You can access microphone (for 2-way audio) only with HTTPS
### Module: RTSP
You can get any stream as RTSP-stream with codecs filter:
@@ -353,14 +391,25 @@ tunnels:
### Module: Hass
go2rtc compatible with Home Assistant [RTSPtoWebRTC](https://www.home-assistant.io/integrations/rtsp_to_webrtc/) integration API.
**go2rtc** compatible with Home Assistant [RTSPtoWebRTC](https://www.home-assistant.io/integrations/rtsp_to_webrtc/) integration.
- add integration with link to go2rtc HTTP API:
- Hass > Settings > Integrations > Add Integration > RTSPtoWebRTC > `http://192.168.1.123:1984/`
- add generic camera with RTSP link:
- Hass > Settings > Integrations > Add Integration > Generic Camera > `rtsp://...`
- use Picture Entity or Picture Glance lovelace card
- open full screen card - this is should be WebRTC stream
If you install **go2rtc** as [Hass Add-on](#go2rtc-home-assistant-add-on) - you need to use localhost IP-address, example:
- `http://127.0.0.1:1984/` to web interface
- `rtsp://127.0.0.1:8554/camera1` to RTSP streams
In other cases you need to use IP-address of server with **go2rtc** application.
1. Add integration with link to go2rtc HTTP API:
- Hass > Settings > Integrations > Add Integration > [RTSPtoWebRTC](https://my.home-assistant.io/redirect/config_flow_start/?domain=rtsp_to_webrtc) > `http://127.0.0.1:1984/`
2. Add generic camera with RTSP link:
- Hass > Settings > Integrations > Add Integration > [Generic Camera](https://my.home-assistant.io/redirect/config_flow_start/?domain=generic) > `rtsp://...` or `rtmp://...`
3. Use Picture Entity or Picture Glance lovelace card
4. Open full screen card - this is should be WebRTC stream
- you can use either direct RTSP links to cameras or take RTSP streams from **go2rtc**
PS. Default Home Assistant lovelace cards don't support 2-way audio. You can use 2-way audio from [Add-on Web UI](https://my.home-assistant.io/redirect/supervisor_addon/?addon=a889bffc_go2rtc&repository_url=https%3A%2F%2Fgithub.com%2FAlexxIT%2Fhassio-addons). But you need use HTTPS to access the microphone. This is a browser restriction and cannot be avoided.
### Module: Log
+5 -1
View File
@@ -61,6 +61,10 @@ func (s *Stream) AddConsumer(cons streamer.Consumer) (err error) {
// Step 4. Get producer track
prodTrack := prod.GetTrack(prodMedia, prodCodec)
if prodTrack == nil {
log.Warn().Msg("[stream] can't get track")
continue
}
// Step 5. Add track to consumer and get new track
consTrack := consumer.element.AddTrack(consMedia, prodTrack)
@@ -121,7 +125,7 @@ func (s *Stream) RemoveProducer(prod streamer.Producer) {
}
func (s *Stream) Active() bool {
if len(s.consumers) > 0{
if len(s.consumers) > 0 {
return true
}
+31 -5
View File
@@ -189,7 +189,7 @@ func (c *Conn) Do(req *tcp.Request) (*tcp.Response, error) {
}
if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("wrong response on %s", req.Method)
return res, fmt.Errorf("wrong response on %s", req.Method)
}
return res, nil
@@ -261,7 +261,21 @@ func (c *Conn) Describe() error {
res, err := c.Do(req)
if err != nil {
return err
if res != nil {
// if we have answer - give second chanse without onvif header
req.Header.Del("Require")
res, err = c.Do(req)
}
if err != nil {
return err
}
}
if val := res.Header.Get("Content-Base"); val != "" {
c.URL, err = url.Parse(val)
if err != nil {
return err
}
}
// fix bug in Sonoff camera SDP "o=- 1 1 IN IP4 rom t_rtsplin"
@@ -355,10 +369,22 @@ func (c *Conn) SetupMedia(
// we send our `interleaved`, but camera can answer with another
// Transport: RTP/AVP/TCP;unicast;interleaved=10-11;ssrc=10117CB7
// Transport: RTP/AVP/TCP;unicast;destination=192.168.1.123;source=192.168.10.12;interleaved=0
s := res.Header.Get("Transport")
s, ok1, ok2 := between(s, "RTP/AVP/TCP;unicast;interleaved=", "-")
if !ok1 || !ok2 {
panic("wrong response")
// TODO: rewrite
if !strings.HasPrefix(s, "RTP/AVP/TCP;unicast") {
return nil, fmt.Errorf("wrong transport: %s", s)
}
i := strings.Index(s, "interleaved=")
if i < 0 {
return nil, fmt.Errorf("wrong transport: %s", s)
}
s = s[i+len("interleaved="):]
i = strings.IndexAny(s, "-;")
if i > 0 {
s = s[:i]
}
ch, err = strconv.Atoi(s)
+8
View File
@@ -3,6 +3,7 @@ package streamer
import (
"fmt"
"github.com/pion/rtp"
"sync"
)
type WriterFunc func(packet *rtp.Packet) error
@@ -12,6 +13,7 @@ type Track struct {
Codec *Codec
Direction string
Sink map[*Track]WriterFunc
mx sync.Mutex
}
func (t *Track) String() string {
@@ -21,9 +23,11 @@ func (t *Track) String() string {
}
func (t *Track) WriteRTP(p *rtp.Packet) error {
t.mx.Lock()
for _, f := range t.Sink {
_ = f(p)
}
t.mx.Unlock()
return nil
}
@@ -35,10 +39,14 @@ func (t *Track) Bind(w WriterFunc) *Track {
clone := &Track{
Codec: t.Codec, Direction: t.Direction, Sink: t.Sink,
}
t.mx.Lock()
t.Sink[clone] = w
t.mx.Unlock()
return clone
}
func (t *Track) Unbind() {
t.mx.Lock()
delete(t.Sink, t)
t.mx.Unlock()
}
+3 -1
View File
@@ -130,7 +130,9 @@ func (c *Conn) GetCompleteAnswer() (answer string, err error) {
func (c *Conn) remote() string {
for _, trans := range c.Conn.GetTransceivers() {
pair, _ := trans.Receiver().Transport().ICETransport().GetSelectedCandidatePair()
return pair.Remote.String()
if pair.Remote != nil {
return pair.Remote.String()
}
}
return ""
}