Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 18d7b9075b | |||
| 7c4497f856 | |||
| befa4ca1e6 | |||
| dd3b326f7a | |||
| e36123bb19 | |||
| 9310343ad3 | |||
| e2d4fa3393 | |||
| 5fea2932c1 | |||
| 1fd110b70d | |||
| 8377cf2655 | |||
| 8f01b08d42 | |||
| 97ce4c3114 | |||
| 4813a64d9d | |||
| 7923ec74a8 | |||
| 1f0a5fb880 | |||
| c6a3ee65b8 |
@@ -1,6 +1,6 @@
|
|||||||
# go2rtc
|
# go2rtc
|
||||||
|
|
||||||
**go2rtc** - ultimate camera streaming application with support RTSP, WebRTC, FFmpeg, RTMP, etc.
|
Ultimate camera streaming application with support RTSP, WebRTC, FFmpeg, RTMP, etc.
|
||||||
|
|
||||||
- zero-dependency and zero-config small [app for all OS](#go2rtc-binary) (Windows, macOS, Linux, ARM)
|
- zero-dependency and zero-config small [app for all OS](#go2rtc-binary) (Windows, macOS, Linux, ARM)
|
||||||
- zero-delay for all supported protocols (lowest possible streaming latency)
|
- zero-delay for all supported protocols (lowest possible streaming latency)
|
||||||
@@ -95,6 +95,16 @@ Don't forget to fix the rights `chmod +x go2rtc_xxx_xxx` on Linux and Mac.
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
go2rtc:
|
||||||
|
image: alexxit/go2rtc
|
||||||
|
network_mode: host
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- "~/go2rtc.yaml:/config/go2rtc.yaml"
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Create file `go2rtc.yaml` next to the app.
|
Create file `go2rtc.yaml` next to the app.
|
||||||
@@ -118,7 +128,7 @@ Available modules:
|
|||||||
|
|
||||||
### Module: Streams
|
### Module: Streams
|
||||||
|
|
||||||
**go2rtc** support different stream source types. You can config one or multiple link as stream source.
|
**go2rtc** support different stream source types. You can config one or multiple links of any type as stream source.
|
||||||
|
|
||||||
Available source types:
|
Available source types:
|
||||||
|
|
||||||
@@ -135,7 +145,7 @@ Available source types:
|
|||||||
- Support **RTSP and RTSPS** links with multiple video and audio tracks
|
- Support **RTSP and RTSPS** links with multiple video and audio tracks
|
||||||
- Support **2-way audio** ONLY for [ONVIF Profile T](https://www.onvif.org/specs/stream/ONVIF-Streaming-Spec.pdf) cameras (back channel connection)
|
- Support **2-way audio** ONLY for [ONVIF Profile T](https://www.onvif.org/specs/stream/ONVIF-Streaming-Spec.pdf) cameras (back channel connection)
|
||||||
|
|
||||||
**Attention:** proprietary 2-way audio standards are not supported!
|
**Attention:** other 2-way audio standards are not supported! ONVIF without Profile T is not supported!
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
streams:
|
streams:
|
||||||
@@ -189,28 +199,15 @@ streams:
|
|||||||
rtsp: ffmpeg:rtsp://rtsp:12345678@192.168.1.123/av_stream/ch0#video=copy#audio=copy
|
rtsp: ffmpeg:rtsp://rtsp:12345678@192.168.1.123/av_stream/ch0#video=copy#audio=copy
|
||||||
```
|
```
|
||||||
|
|
||||||
All trascoding formats has built-in templates. But you can override them via YAML config. You can also add your own formats to config and use them with source params.
|
All trascoding formats has [built-in templates](https://github.com/AlexxIT/go2rtc/blob/master/cmd/ffmpeg/ffmpeg.go): `h264`, `h264/ultra`, `h264/high`, `h265`, `opus`, `pcmu`, `pcmu/16000`, `pcmu/48000`, `pcma`, `pcma/16000`, `pcma/48000`, `aac/16000`.
|
||||||
|
|
||||||
|
But you can override them via YAML config. You can also add your own formats to config and use them with source params.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
ffmpeg:
|
ffmpeg:
|
||||||
bin: ffmpeg # path to ffmpeg binary
|
bin: ffmpeg # path to ffmpeg binary
|
||||||
link: -hide_banner -i {input} # if input is link
|
h264: "-codec:v libx264 -g 30 -preset superfast -tune zerolatency -profile main -level 4.1"
|
||||||
file: -hide_banner -re -stream_loop -1 -i {input} # if input not link
|
mycodec: "-any args that support ffmpeg..."
|
||||||
rtsp: -hide_banner -fflags nobuffer -flags low_delay -rtsp_transport tcp -i {input} # if input is RTSP link
|
|
||||||
output: -rtsp_transport tcp -f rtsp {output} # output
|
|
||||||
|
|
||||||
h264: "-codec:v libx264 -g 30 -preset superfast -tune zerolatency -profile main -level 4.1"
|
|
||||||
h264/ultra: "-codec:v libx264 -g 30 -preset ultrafast -tune zerolatency"
|
|
||||||
h264/high: "-codec:v libx264 -g 30 -preset superfast -tune zerolatency"
|
|
||||||
h265: "-codec:v libx265 -g 30 -preset ultrafast -tune zerolatency"
|
|
||||||
opus: "-codec:a libopus -ar 48000 -ac 2"
|
|
||||||
pcmu: "-codec:a pcm_mulaw -ar 8000 -ac 1"
|
|
||||||
pcmu/16000: "-codec:a pcm_mulaw -ar 16000 -ac 1"
|
|
||||||
pcmu/48000: "-codec:a pcm_mulaw -ar 48000 -ac 1"
|
|
||||||
pcma: "-codec:a pcm_alaw -ar 8000 -ac 1"
|
|
||||||
pcma/16000: "-codec:a pcm_alaw -ar 16000 -ac 1"
|
|
||||||
pcma/48000: "-codec:a pcm_alaw -ar 48000 -ac 1"
|
|
||||||
aac/16000: "-codec:a aac -ar 16000 -ac 1"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Source: Exec
|
#### Source: Exec
|
||||||
@@ -426,3 +423,29 @@ log:
|
|||||||
streams: error
|
streams: error
|
||||||
webrtc: fatal
|
webrtc: fatal
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
By default `go2rtc` start Web interface on port `1984` and RTSP on port `8554`. Both 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 port
|
||||||
|
```
|
||||||
|
|
||||||
|
- local access to RTSP is not a problem for [FFmpeg](#source-ffmpeg) integration, because it runs locally on your server
|
||||||
|
- local access to API is not a problem for [Home Assistant Add-on](#go2rtc-home-assistant-add-on), because Hass runs locally on same server and Add-on Web UI protected with Hass authorization ([Ingress feature](https://www.home-assistant.io/blog/2019/04/15/hassio-ingress/))
|
||||||
|
- external access to WebRTC TCP port is not a problem, because it used only for transmit encrypted media data
|
||||||
|
- anyway you need to open this port to your local network and to the Internet in order for WebRTC to work
|
||||||
|
|
||||||
|
If you need Web interface protection without Home Assistant Add-on - you need to use reverse proxy, like [Nginx](https://nginx.org/), [Caddy](https://caddyserver.com/), [Ngrok](https://ngrok.com/), etc.
|
||||||
|
|
||||||
|
PS. Additionally WebRTC opens a lot of random UDP ports for transmit encrypted media. They work without problems on the local network. And sometimes work for external access, even if you haven't opened ports on your router. But for stable external WebRTC access, you need to configure the TCP port.
|
||||||
|
|||||||
@@ -5,16 +5,18 @@ RUN apk add --no-cache git go ffmpeg
|
|||||||
|
|
||||||
ARG BUILD_ARCH
|
ARG BUILD_ARCH
|
||||||
|
|
||||||
WORKDIR app
|
RUN git clone https://github.com/AlexxIT/go2rtc \
|
||||||
|
&& cd go2rtc \
|
||||||
RUN git clone https://github.com/AlexxIT/go2rtc .
|
&& CGO_ENABLED=0 go build -ldflags "-s -w" -trimpath -o /usr/local/bin
|
||||||
RUN CGO_ENABLED=0 go build -ldflags "-s -w" -trimpath
|
|
||||||
|
|
||||||
# https://github.com/home-assistant/docker-base/blob/master/alpine/Dockerfile
|
# https://github.com/home-assistant/docker-base/blob/master/alpine/Dockerfile
|
||||||
RUN if [ "${BUILD_ARCH}" = "aarch64" ]; then BUILD_ARCH="arm64"; \
|
RUN if [ "${BUILD_ARCH}" = "aarch64" ]; then BUILD_ARCH="arm64"; \
|
||||||
elif [ "${BUILD_ARCH}" = "armv7" ]; then BUILD_ARCH="arm"; fi \
|
elif [ "${BUILD_ARCH}" = "armv7" ]; then BUILD_ARCH="arm"; fi \
|
||||||
|
&& cd go2rtc \
|
||||||
&& curl $(curl -s "https://raw.githubusercontent.com/ngrok/docker-ngrok/main/releases.json" | jq -r ".${BUILD_ARCH}.url") -o ngrok.zip \
|
&& curl $(curl -s "https://raw.githubusercontent.com/ngrok/docker-ngrok/main/releases.json" | jq -r ".${BUILD_ARCH}.url") -o ngrok.zip \
|
||||||
&& unzip ngrok
|
&& unzip ngrok -d /usr/local/bin
|
||||||
|
|
||||||
|
RUN rm -r /go2rtc
|
||||||
|
|
||||||
COPY run.sh /
|
COPY run.sh /
|
||||||
RUN chmod a+x /run.sh
|
RUN chmod a+x /run.sh
|
||||||
|
|||||||
+7
-6
@@ -2,12 +2,13 @@
|
|||||||
|
|
||||||
set +e
|
set +e
|
||||||
|
|
||||||
while true; do
|
# set cwd for go2rtc (for config file, Hass itegration, etc)
|
||||||
if [ -x /config/go2rtc ]; then
|
cd /config
|
||||||
/config/go2rtc -config /config/go2rtc.yaml
|
|
||||||
else
|
|
||||||
/app/go2rtc -config /config/go2rtc.yaml
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
# add the feature to override go2rtc binary from Hass config folder
|
||||||
|
export PATH="/config:$PATH"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
go2rtc
|
||||||
sleep 5
|
sleep 5
|
||||||
done
|
done
|
||||||
+2
-1
@@ -44,6 +44,7 @@ func Init() {
|
|||||||
listener, err := net.Listen("tcp", cfg.Mod.Listen)
|
listener, err := net.Listen("tcp", cfg.Mod.Listen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("[api] listen")
|
log.Fatal().Err(err).Msg("[api] listen")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info().Str("addr", cfg.Mod.Listen).Msg("[api] listen")
|
log.Info().Str("addr", cfg.Mod.Listen).Msg("[api] listen")
|
||||||
@@ -51,7 +52,7 @@ func Init() {
|
|||||||
go func() {
|
go func() {
|
||||||
s := http.Server{}
|
s := http.Server{}
|
||||||
if err = s.Serve(listener); err != nil {
|
if err = s.Serve(listener); err != nil {
|
||||||
log.Fatal().Err(err).Msg("[api] Serve")
|
log.Fatal().Err(err).Msg("[api] serve")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -8,8 +8,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func frameHandler(w http.ResponseWriter, r *http.Request) {
|
func frameHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
url := r.URL.Query().Get("url")
|
src := r.URL.Query().Get("src")
|
||||||
stream := streams.Get(url)
|
stream := streams.Get(src)
|
||||||
if stream == nil {
|
if stream == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-2
@@ -24,7 +24,11 @@ func Init() {
|
|||||||
Mod map[string]string `yaml:"log"`
|
Mod map[string]string `yaml:"log"`
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadConfig(&cfg)
|
if data != nil {
|
||||||
|
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
||||||
|
println("ERROR: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var writer io.Writer = os.Stdout
|
var writer io.Writer = os.Stdout
|
||||||
|
|
||||||
@@ -48,7 +52,9 @@ func Init() {
|
|||||||
|
|
||||||
modules = cfg.Mod
|
modules = cfg.Mod
|
||||||
|
|
||||||
log.Info().Msgf("go2rtc %s/%s", runtime.GOOS, runtime.GOARCH)
|
path, _ := os.Getwd()
|
||||||
|
log.Debug().Str("os", runtime.GOOS).Str("arch", runtime.GOARCH).
|
||||||
|
Str("cwd", path).Int("conf_size", len(data)).Msgf("[app]")
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadConfig(v interface{}) {
|
func LoadConfig(v interface{}) {
|
||||||
|
|||||||
+28
-11
@@ -41,28 +41,45 @@ func Init() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ent := new(entries)
|
storage := new(entries)
|
||||||
if err = json.Unmarshal(data, ent); err != nil {
|
if err = json.Unmarshal(data, storage); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
urls := map[string]string{}
|
urls := map[string]string{}
|
||||||
|
|
||||||
for _, entrie := range ent.Data.Entries {
|
|
||||||
switch entrie.Domain {
|
|
||||||
case "generic":
|
|
||||||
if entrie.Options.StreamSource != "" {
|
|
||||||
urls[entrie.Title] = entrie.Options.StreamSource
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
streams.HandleFunc("hass", func(url string) (streamer.Producer, error) {
|
streams.HandleFunc("hass", func(url string) (streamer.Producer, error) {
|
||||||
if hurl := urls[url[5:]]; hurl != "" {
|
if hurl := urls[url[5:]]; hurl != "" {
|
||||||
return streams.GetProducer(hurl)
|
return streams.GetProducer(hurl)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("can't get url: %s", url)
|
return nil, fmt.Errorf("can't get url: %s", url)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
for _, entrie := range storage.Data.Entries {
|
||||||
|
switch entrie.Domain {
|
||||||
|
case "generic":
|
||||||
|
if entrie.Options.StreamSource == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
urls[entrie.Title] = entrie.Options.StreamSource
|
||||||
|
|
||||||
|
//case "homekit_controller":
|
||||||
|
// if entrie.Data.ClientID == "" {
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// urls[entrie.Title] = fmt.Sprintf(
|
||||||
|
// "homekit://%s:%d?client_id=%s&client_private=%s%s&device_id=%s&device_public=%s",
|
||||||
|
// entrie.Data.DeviceHost, entrie.Data.DevicePort,
|
||||||
|
// entrie.Data.ClientID, entrie.Data.ClientPrivate, entrie.Data.ClientPublic,
|
||||||
|
// entrie.Data.DeviceID, entrie.Data.DevicePublic,
|
||||||
|
// )
|
||||||
|
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
streams.Get("hass:" + entrie.Title)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var log zerolog.Logger
|
var log zerolog.Logger
|
||||||
|
|||||||
+2
-2
@@ -13,8 +13,8 @@ func Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handler(ctx *api.Context, msg *streamer.Message) {
|
func handler(ctx *api.Context, msg *streamer.Message) {
|
||||||
url := ctx.Request.URL.Query().Get("url")
|
src := ctx.Request.URL.Query().Get("src")
|
||||||
stream := streams.Get(url)
|
stream := streams.Get(src)
|
||||||
if stream == nil {
|
if stream == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,13 +63,13 @@ var log zerolog.Logger
|
|||||||
var NewPConn func() (*pion.PeerConnection, error)
|
var NewPConn func() (*pion.PeerConnection, error)
|
||||||
|
|
||||||
func offerHandler(ctx *api.Context, msg *streamer.Message) {
|
func offerHandler(ctx *api.Context, msg *streamer.Message) {
|
||||||
name := ctx.Request.URL.Query().Get("url")
|
src := ctx.Request.URL.Query().Get("src")
|
||||||
stream := streams.Get(name)
|
stream := streams.Get(src)
|
||||||
if stream == nil {
|
if stream == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug().Str("stream", name).Msg("[webrtc] new consumer")
|
log.Debug().Str("src", src).Msg("[webrtc] new consumer")
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -169,6 +169,7 @@ func ExchangeSDP(
|
|||||||
// 2. AddConsumer, so we get new tracks
|
// 2. AddConsumer, so we get new tracks
|
||||||
if err = stream.AddConsumer(conn); err != nil {
|
if err = stream.AddConsumer(conn); err != nil {
|
||||||
log.Warn().Err(err).Msg("[api.webrtc] add consumer")
|
log.Warn().Err(err).Msg("[api.webrtc] add consumer")
|
||||||
|
_ = conn.Conn.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-4
@@ -451,15 +451,17 @@ func (c *Conn) Accept() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.URL == nil {
|
||||||
|
c.URL = req.URL
|
||||||
|
c.UserAgent = req.Header.Get("User-Agent")
|
||||||
|
}
|
||||||
|
|
||||||
c.Fire(req)
|
c.Fire(req)
|
||||||
|
|
||||||
// Receiver: OPTIONS > DESCRIBE > SETUP... > PLAY > TEARDOWN
|
// Receiver: OPTIONS > DESCRIBE > SETUP... > PLAY > TEARDOWN
|
||||||
// Sender: OPTIONS > ANNOUNCE > SETUP... > RECORD > TEARDOWN
|
// Sender: OPTIONS > ANNOUNCE > SETUP... > RECORD > TEARDOWN
|
||||||
switch req.Method {
|
switch req.Method {
|
||||||
case MethodOptions:
|
case MethodOptions:
|
||||||
c.URL = req.URL
|
|
||||||
c.UserAgent = req.Header.Get("User-Agent")
|
|
||||||
|
|
||||||
res := &tcp.Response{
|
res := &tcp.Response{
|
||||||
Header: map[string][]string{
|
Header: map[string][]string{
|
||||||
"Public": {"OPTIONS, SETUP, TEARDOWN, DESCRIBE, PLAY, PAUSE, ANNOUNCE, RECORD"},
|
"Public": {"OPTIONS, SETUP, TEARDOWN, DESCRIBE, PLAY, PAUSE, ANNOUNCE, RECORD"},
|
||||||
@@ -638,7 +640,8 @@ func (c *Conn) Handle() (err error) {
|
|||||||
_ = track.WriteRTP(packet)
|
_ = track.WriteRTP(packet)
|
||||||
//return fmt.Errorf("wrong channelID: %d", channelID)
|
//return fmt.Errorf("wrong channelID: %d", channelID)
|
||||||
} else {
|
} else {
|
||||||
panic("wrong channelID")
|
continue // TODO: maybe fix this
|
||||||
|
//panic("wrong channelID")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
msg := &RTCP{Channel: channelID}
|
msg := &RTCP{Channel: channelID}
|
||||||
|
|||||||
+20
-20
@@ -1,6 +1,7 @@
|
|||||||
package webrtc
|
package webrtc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/pion/ice/v2"
|
||||||
"github.com/pion/interceptor"
|
"github.com/pion/interceptor"
|
||||||
"github.com/pion/webrtc/v3"
|
"github.com/pion/webrtc/v3"
|
||||||
"net"
|
"net"
|
||||||
@@ -21,31 +22,30 @@ func NewAPI(address string) (*webrtc.API, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if address == "" {
|
|
||||||
return webrtc.NewAPI(
|
|
||||||
webrtc.WithMediaEngine(m),
|
|
||||||
webrtc.WithInterceptorRegistry(i),
|
|
||||||
), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ln, err := net.Listen("tcp", address)
|
|
||||||
if err != nil {
|
|
||||||
return webrtc.NewAPI(
|
|
||||||
webrtc.WithMediaEngine(m),
|
|
||||||
webrtc.WithInterceptorRegistry(i),
|
|
||||||
), err
|
|
||||||
}
|
|
||||||
|
|
||||||
s := webrtc.SettingEngine{
|
s := webrtc.SettingEngine{
|
||||||
//LoggerFactory: customLoggerFactory{},
|
//LoggerFactory: customLoggerFactory{},
|
||||||
}
|
}
|
||||||
s.SetNetworkTypes([]webrtc.NetworkType{
|
|
||||||
webrtc.NetworkTypeUDP4, webrtc.NetworkTypeUDP6,
|
// disable listen on Hassio docker interfaces
|
||||||
webrtc.NetworkTypeTCP4, webrtc.NetworkTypeTCP6,
|
s.SetInterfaceFilter(func(name string) bool {
|
||||||
|
return name != "hassio" && name != "docker0"
|
||||||
})
|
})
|
||||||
|
|
||||||
tcpMux := webrtc.NewICETCPMux(nil, ln, 8)
|
// disable mDNS listener
|
||||||
s.SetICETCPMux(tcpMux)
|
s.SetICEMulticastDNSMode(ice.MulticastDNSModeDisabled)
|
||||||
|
|
||||||
|
if address != "" {
|
||||||
|
ln, err := net.Listen("tcp", address)
|
||||||
|
if err == nil {
|
||||||
|
s.SetNetworkTypes([]webrtc.NetworkType{
|
||||||
|
webrtc.NetworkTypeUDP4, webrtc.NetworkTypeUDP6,
|
||||||
|
webrtc.NetworkTypeTCP4, webrtc.NetworkTypeTCP6,
|
||||||
|
})
|
||||||
|
|
||||||
|
tcpMux := webrtc.NewICETCPMux(nil, ln, 8)
|
||||||
|
s.SetICETCPMux(tcpMux)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return webrtc.NewAPI(
|
return webrtc.NewAPI(
|
||||||
webrtc.WithMediaEngine(m),
|
webrtc.WithMediaEngine(m),
|
||||||
|
|||||||
@@ -2,11 +2,18 @@
|
|||||||
|
|
||||||
- UPX-3.96 pack broken bin for `linux_mipsel`
|
- UPX-3.96 pack broken bin for `linux_mipsel`
|
||||||
- UPX-3.95 pack broken bin for `mac_amd64`
|
- UPX-3.95 pack broken bin for `mac_amd64`
|
||||||
|
- UPX windows pack is recognised by anti-viruses as malicious
|
||||||
- `aarch64` = `arm64`
|
- `aarch64` = `arm64`
|
||||||
- `armv7` = `arm`
|
- `armv7` = `arm`
|
||||||
|
|
||||||
|
## Virus
|
||||||
|
|
||||||
|
- https://go.dev/doc/faq#virus
|
||||||
|
- https://groups.google.com/g/golang-nuts/c/lPwiWYaApSU
|
||||||
|
|
||||||
## Useful links
|
## Useful links
|
||||||
|
|
||||||
- https://github.com/golang/go/wiki/GoArm
|
- https://github.com/golang/go/wiki/GoArm
|
||||||
- https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63
|
- https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63
|
||||||
- https://en.wikipedia.org/wiki/AArch64
|
- https://en.wikipedia.org/wiki/AArch64
|
||||||
|
- https://stackoverflow.com/questions/22267189/what-does-the-w-flag-mean-when-passed-in-via-the-ldflags-option-to-the-go-comman
|
||||||
|
|||||||
+4
-4
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
@SET GOOS=windows
|
@SET GOOS=windows
|
||||||
@SET GOARCH=amd64
|
@SET GOARCH=amd64
|
||||||
@SET FILENAME=go2rtc_win64.exe
|
@SET FILENAME=go2rtc_win64.zip
|
||||||
go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx-3.96 %FILENAME%
|
go build -ldflags "-s -w" -trimpath && 7z a -sdel %FILENAME% go2rtc.exe
|
||||||
|
|
||||||
@SET GOOS=windows
|
@SET GOOS=windows
|
||||||
@SET GOARCH=386
|
@SET GOARCH=386
|
||||||
@SET FILENAME=go2rtc_win32.exe
|
@SET FILENAME=go2rtc_win32.zip
|
||||||
go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx-3.96 %FILENAME%
|
go build -ldflags "-s -w" -trimpath && 7z a -sdel %FILENAME% go2rtc.exe
|
||||||
|
|
||||||
@SET GOOS=linux
|
@SET GOOS=linux
|
||||||
@SET GOARCH=amd64
|
@SET GOARCH=amd64
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
@SET GOOS=linux
|
||||||
|
@SET GOARCH=mipsle
|
||||||
|
cd ..
|
||||||
|
go build -ldflags "-s -w" -trimpath && upx-3.95 go2rtc
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@SET GOOS=windows
|
@SET GOOS=windows
|
||||||
@SET GOARCH=amd64
|
@SET GOARCH=amd64
|
||||||
cd ..
|
cd ..
|
||||||
go build -ldflags "-s -w" -trimpath && upx-3.96 go2rtc.exe
|
go build -ldflags "-w -s" -trimpath
|
||||||
+3
-3
@@ -63,9 +63,9 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
const links = [
|
const links = [
|
||||||
'<a href="webrtc.html?url={name}">webrtc</a>',
|
'<a href="webrtc.html?src={name}">webrtc</a>',
|
||||||
'<a href="mse.html?url={name}">mse</a>',
|
'<a href="mse.html?src={name}">mse</a>',
|
||||||
'<a href="api/frame.mp4?url={name}">frame.mp4</a>',
|
'<a href="api/frame.mp4?src={name}">frame.mp4</a>',
|
||||||
'<a href="api/streams?src={name}">info</a>',
|
'<a href="api/streams?src={name}">info</a>',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user