Merge branch 'AlexxIT:master' into documentation-site

This commit is contained in:
Sergey Krashevich
2026-01-26 04:22:35 +03:00
committed by GitHub
8 changed files with 49 additions and 48 deletions
+2 -2
View File
@@ -11,7 +11,7 @@ import (
"github.com/AlexxIT/go2rtc/internal/api" "github.com/AlexxIT/go2rtc/internal/api"
"github.com/AlexxIT/go2rtc/internal/app" "github.com/AlexxIT/go2rtc/internal/app"
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/creds"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/rs/zerolog" "github.com/rs/zerolog"
) )
@@ -133,7 +133,7 @@ func apiWS(w http.ResponseWriter, r *http.Request) {
if handler := wsHandlers[msg.Type]; handler != nil { if handler := wsHandlers[msg.Type]; handler != nil {
go func() { go func() {
if err = handler(tr, msg); err != nil { if err = handler(tr, msg); err != nil {
errMsg := core.StripUserinfo(err.Error()) errMsg := creds.SecretString(err.Error())
tr.Write(&Message{Type: "error", Value: msg.Type + ": " + errMsg}) tr.Write(&Message{Type: "error", Value: msg.Type + ": " + errMsg})
} }
}() }()
+1 -1
View File
@@ -35,7 +35,7 @@ rtsp:
Editors like [GoLand](https://www.jetbrains.com/go/) and [VS Code](https://code.visualstudio.com/) supports autocomplete and syntax validation. Editors like [GoLand](https://www.jetbrains.com/go/) and [VS Code](https://code.visualstudio.com/) supports autocomplete and syntax validation.
```yaml ```yaml
# yaml-language-server: $schema=https://raw.githubusercontent.com/AlexxIT/go2rtc/master/website/schema.json # yaml-language-server: $schema=https://raw.githubusercontent.com/AlexxIT/go2rtc/master/www/schema.json
``` ```
## Defaults ## Defaults
+1 -1
View File
@@ -136,7 +136,7 @@ streams:
"ffmpeg:" + url3 + "#video=copy" "ffmpeg:" + url3 + "#video=copy"
``` ```
## Comparsion ## Comparison
| expr | python | js | | expr | python | js |
|------------------------------|----------------------------|--------------------------------| |------------------------------|----------------------------|--------------------------------|
+2 -2
View File
@@ -47,7 +47,7 @@ Read more [here](https://en.wikipedia.org/wiki/Intel_Quick_Sync_Video#Hardware_d
Linux and Docker: Linux and Docker:
- It may be important to have the latest version of the OS with the latest version of the Linux kernel. For example, on my **Debian 10 (kernel 4.19)** it did not work, but after update to **Debian 11 (kernel 5.10)** all was fine. - It may be important to have the latest version of the OS with the latest version of the Linux kernel. For example, on my **Debian 10 (kernel 4.19)** it did not work, but after update to **Debian 11 (kernel 5.10)** all was fine.
- In case of troube check you have `/dev/dri/` folder on your host. - In case of trouble check you have `/dev/dri/` folder on your host.
Docker users should add `--privileged` option to container for access to Hardware. Docker users should add `--privileged` option to container for access to Hardware.
@@ -79,7 +79,7 @@ Read more [here](https://docs.frigate.video/configuration/hardware_acceleration)
**Supported on:** Linux binary, Docker, Hass Addon. **Supported on:** Linux binary, Docker, Hass Addon.
I don't recommend using transcoding on the Raspberry Pi 3. It's extreamly slow, even with hardware acceleration. Also it may fail when transcoding 2K+ stream. 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 2K+ stream.
## Raspberry Pi 4 ## Raspberry Pi 4
+5 -5
View File
@@ -10,8 +10,8 @@ What you should to know about WebRTC:
If an external connection via STUN is used: If an external connection via STUN is used:
- Uses [UDP hole punching](https://en.wikipedia.org/wiki/UDP_hole_punching) technology to bypass NAT even if you not open your server to the World - Uses [UDP hole punching](https://en.wikipedia.org/wiki/UDP_hole_punching) technology to bypass NAT even if you not open your server to the World
- For about 20% of users, the techology will not work because of the [Symmetric NAT](https://tomchen.github.io/symmetric-nat-test/) - For about 20% of users, the technology will not work because of the [Symmetric NAT](https://tomchen.github.io/symmetric-nat-test/)
- UDP is not suitable for transmitting 2K and 4K high bitrate video over open networks because of the high loss rate: - UDP is not suitable for transmitting 2K and 4K high bit rate video over open networks because of the high loss rate:
- https://habr.com/ru/companies/flashphoner/articles/480006/ - https://habr.com/ru/companies/flashphoner/articles/480006/
- https://www.youtube.com/watch?v=FXVg2ckuKfs - https://www.youtube.com/watch?v=FXVg2ckuKfs
@@ -26,7 +26,7 @@ webrtc:
## Config ## Config
**Important!** This example is not for copypasting! **Important!** This example is not for copy pasting!
```yaml ```yaml
webrtc: webrtc:
@@ -84,7 +84,7 @@ Don't know why, but you can disable TCP port and leave only random UDP ports - `
## Config filters ## Config filters
**Importan!** By default go2rtc exclude all Docker-like candidates (`172.16.0.0/12`). This can not be disabled. **Important!** By default go2rtc exclude all Docker-like candidates (`172.16.0.0/12`). This can not 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. 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.
@@ -106,7 +106,7 @@ webrtc:
candidates: [ 192.168.1.2:8555 ] # add manual host candidate (use docker port forwarding) candidates: [ 192.168.1.2:8555 ] # add manual host candidate (use docker port forwarding)
``` ```
## Userful links ## Useful links
- https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html - https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html
- https://www.ietf.org/id/draft-murillo-whep-01.html - https://www.ietf.org/id/draft-murillo-whep-01.html
-12
View File
@@ -2,7 +2,6 @@ package core
import ( import (
"crypto/rand" "crypto/rand"
"regexp"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
@@ -93,14 +92,3 @@ func Caller() string {
_, file, line, _ := runtime.Caller(1) _, file, line, _ := runtime.Caller(1)
return file + ":" + strconv.Itoa(line) return file + ":" + strconv.Itoa(line)
} }
const (
unreserved = `A-Za-z0-9-._~`
subdelims = `!$&'()*+,;=`
userinfo = unreserved + subdelims + `%:`
)
func StripUserinfo(s string) string {
sanitizer := regexp.MustCompile(`://[` + userinfo + `]+@`)
return sanitizer.ReplaceAllString(s, `://***@`)
}
+30 -19
View File
@@ -3,6 +3,7 @@ package creds
import ( import (
"io" "io"
"net/http" "net/http"
"regexp"
"slices" "slices"
"strings" "strings"
"sync" "sync"
@@ -27,6 +28,7 @@ func AddSecret(value string) {
var secrets []string var secrets []string
var secretsMu sync.Mutex var secretsMu sync.Mutex
var secretsReplacer *strings.Replacer var secretsReplacer *strings.Replacer
var userinfoRegexp *regexp.Regexp
func getReplacer() *strings.Replacer { func getReplacer() *strings.Replacer {
secretsMu.Lock() secretsMu.Lock()
@@ -40,14 +42,33 @@ func getReplacer() *strings.Replacer {
secretsReplacer = strings.NewReplacer(oldnew...) secretsReplacer = strings.NewReplacer(oldnew...)
} }
if userinfoRegexp == nil {
userinfoRegexp = regexp.MustCompile(`://[` + userinfo + `]+@`)
}
return secretsReplacer return secretsReplacer
} }
// Uniform Resource Identifier (URI)
// https://datatracker.ietf.org/doc/html/rfc3986
const (
unreserved = `A-Za-z0-9-._~`
subdelims = `!$&'()*+,;=`
userinfo = unreserved + subdelims + `%:`
)
func SecretString(s string) string { func SecretString(s string) string {
re := getReplacer() re := getReplacer()
s = userinfoRegexp.ReplaceAllString(s, `://***@`)
return re.Replace(s) return re.Replace(s)
} }
func SecretWrite(w io.Writer, s string) (n int, err error) {
re := getReplacer()
s = userinfoRegexp.ReplaceAllString(s, `://***@`)
return re.WriteString(w, s)
}
func SecretWriter(w io.Writer) io.Writer { func SecretWriter(w io.Writer) io.Writer {
return &secretWriter{w} return &secretWriter{w}
} }
@@ -57,27 +78,17 @@ type secretWriter struct {
} }
func (s *secretWriter) Write(b []byte) (int, error) { func (s *secretWriter) Write(b []byte) (int, error) {
re := getReplacer() return SecretWrite(s.w, string(b))
return re.WriteString(s.w, string(b))
}
type secretResponse struct {
w http.ResponseWriter
}
func (s *secretResponse) Header() http.Header {
return s.w.Header()
}
func (s *secretResponse) Write(b []byte) (int, error) {
re := getReplacer()
return re.WriteString(s.w, string(b))
}
func (s *secretResponse) WriteHeader(statusCode int) {
s.w.WriteHeader(statusCode)
} }
func SecretResponse(w http.ResponseWriter) http.ResponseWriter { func SecretResponse(w http.ResponseWriter) http.ResponseWriter {
return &secretResponse{w} return &secretResponse{w}
} }
type secretResponse struct {
http.ResponseWriter
}
func (s *secretResponse) Write(b []byte) (int, error) {
return SecretWrite(s.ResponseWriter, string(b))
}
+5 -3
View File
@@ -36,7 +36,7 @@ func NewClient(rawURL string) (*Client, error) {
} else if model == ModelMijia || model == ModelXiaobai { } else if model == ModelMijia || model == ModelXiaobai {
username = "admin" username = "admin"
password = query.Get("password") password = query.Get("password")
} else if model == ModelXiaofang { } else if model == ModelDafang || model == ModelXiaofang {
username = "admin" username = "admin"
} else { } else {
return nil, fmt.Errorf("xiaomi: unsupported model: %s", model) return nil, fmt.Errorf("xiaomi: unsupported model: %s", model)
@@ -47,7 +47,7 @@ func NewClient(rawURL string) (*Client, error) {
return nil, err return nil, err
} }
if model == ModelXiaofang { if model == ModelDafang || model == ModelXiaofang {
err = xiaofangLogin(conn, query.Get("password")) err = xiaofangLogin(conn, query.Get("password"))
if err != nil { if err != nil {
_ = conn.Close() _ = conn.Close()
@@ -196,7 +196,7 @@ func (c *Client) StartMedia(video, audio string) error {
c.WriteCommandJSON(cmdVideoStart, `{}`), c.WriteCommandJSON(cmdVideoStart, `{}`),
) )
case ModelXiaofang: case ModelDafang, ModelXiaofang:
// 00010000 4943414d 95010400000000000000000600000000000000d20400005a07 - 90k bitrate // 00010000 4943414d 95010400000000000000000600000000000000d20400005a07 - 90k bitrate
// 00010000 4943414d 95010400000000000000000600000000000000d20400001e07 - 30k bitrate // 00010000 4943414d 95010400000000000000000600000000000000d20400001e07 - 30k bitrate
//var b byte //var b byte
@@ -258,6 +258,8 @@ const (
ModelXiaofang = "isa.camera.isc5" ModelXiaofang = "isa.camera.isc5"
// ModelMijia support miss format for new fw and legacy format for old fw // ModelMijia support miss format for new fw and legacy format for old fw
ModelMijia = "chuangmi.camera.v2" ModelMijia = "chuangmi.camera.v2"
// ModelDafang support miss format for new fw and legacy format for old fw
ModelDafang = "isa.camera.df3"
) )
func Supported(model string) bool { func Supported(model string) bool {