vendor update
This commit is contained in:
1 parent
94d02d8466
commit
c145142a42
864 files changed
+197887
-76437
No files matched your search
+103
-49
@@ -3,17 +3,39 @@ package common
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/alexflint/go-arg"
|
||||
"go.uber.org/zap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type File = ConfigFile
|
||||
type VideoSrc = ConfigVideoSourceStream
|
||||
type AudioSrc = ConfigAudioSourceStream
|
||||
type AudioSink = ConfigAudioSinkStream
|
||||
type Logging = ConfigLogging
|
||||
type Ring = ConfigRing
|
||||
type Http = ConfigHTTP
|
||||
|
||||
type Config struct {
|
||||
VideoSrc ConfigVideoSourceStream
|
||||
AudioSrc ConfigAudioSourceStream
|
||||
AudioSink ConfigAudioSinkStream
|
||||
Logging ConfigLogging
|
||||
Ring ConfigRing
|
||||
Http ConfigHTTP
|
||||
File
|
||||
VideoSrc `yaml:"video-src"`
|
||||
AudioSrc `yaml:"audio-src"`
|
||||
AudioSink `yaml:"audio-sink"`
|
||||
Logging `yaml:"logging"`
|
||||
Ring `yaml:"ring"`
|
||||
Http `yaml:"http"`
|
||||
}
|
||||
|
||||
type Path struct {
|
||||
string
|
||||
}
|
||||
|
||||
func (p Path) String() string {
|
||||
return p.string
|
||||
}
|
||||
|
||||
type ConfigStream struct {
|
||||
@@ -22,59 +44,64 @@ type ConfigStream struct {
|
||||
AudioSink ConfigAudioSinkStream // audio sink for webrtc receive
|
||||
}
|
||||
|
||||
type ConfigFile struct {
|
||||
Path *Path `arg:"--config"`
|
||||
}
|
||||
|
||||
type ConfigLogging struct {
|
||||
Level string `arg:"--log-level,env:LOG_LEVEL" default:"debug"`
|
||||
Level zap.AtomicLevel `arg:"--log-level,env:LOG_LEVEL" yaml:"level" default:"debug"`
|
||||
Development bool `arg:"--log-development,env:LOG_DEVELOPMENT" yaml:"development"`
|
||||
}
|
||||
|
||||
type ConfigRing struct {
|
||||
Device *string `arg:"--input-device,env:INPUT_DEVICE"`
|
||||
Key string `arg:"--ring-key" default:"KEY_F1"`
|
||||
JingleBaseUri *string `arg:"--jingle-base-uri,env:JINGLE_BASE_URI"`
|
||||
JinglePath string `arg:"--jingle-path,env:JINGLE_PATH" default:"audio/ding-dong.wav"`
|
||||
SonosTarget string `arg:"--sonos-target,env:SONOS_TARGET" default:"-"`
|
||||
SonosVolume int `arg:"--sonos-volume,env:SONOS_VOLUME" default:"50"`
|
||||
HomeassistantWebhook *string `arg:"--ha-webhook,env:HA_WEBHOOK"`
|
||||
NoIPv6 bool `arg:"--disable-ipv6,env:NO_IPV6" default:"false"`
|
||||
Device *string `arg:"--input-device,env:INPUT_DEVICE" yaml:"input"`
|
||||
Key string `arg:"--ring-key" default:"KEY_F1" yaml:"key"`
|
||||
JingleBaseUri *string `arg:"--jingle-base-uri,env:JINGLE_BASE_URI" yaml:"jingle-base-uri"`
|
||||
JinglePath Path `arg:"--jingle-path,env:JINGLE_PATH" default:"audio/ding-dong.wav" yaml:"jingle-path"`
|
||||
SonosTarget string `arg:"--sonos-target,env:SONOS_TARGET" yaml:"sonos-target" default:"-"`
|
||||
SonosVolume int `arg:"--sonos-volume,env:SONOS_VOLUME" yaml:"sonos-volume" default:"50"`
|
||||
HomeassistantWebhook *string `arg:"--ha-webhook,env:HA_WEBHOOK" yaml:"ha-webhook"`
|
||||
NoIPv6 bool `arg:"--disable-ipv6,env:NO_IPV6" yaml:"no-ipv6"`
|
||||
}
|
||||
|
||||
type ConfigHTTP struct {
|
||||
Host string `arg:"--http-host,env:HTTP_HOST" default:"0.0.0.0"`
|
||||
Port uint `arg:"--http-port,env:HTTP_PORT" default:"8080"`
|
||||
Tls bool `arg:"--http-tls,env:HTTP_TLS" default:"true"`
|
||||
TlsKey *string `arg:"--http-tls-key,env:HTTP_TLS_KEY"`
|
||||
TlsCert *string `arg:"--http-tls-cert,env:HTTP_TLS_CERT"`
|
||||
PathGetLiveness string `arg:"env:HTTP_PATH_LIVENESS" default:"/healthz"`
|
||||
PathGetReadiness string `arg:"env:HTTP_PATH_READINESS" default:"/readyz"`
|
||||
StaticPath *string `arg:"--http-static,env:HTTP_STATIC"`
|
||||
Host string `arg:"--http-host,env:HTTP_HOST" yaml:"host" default:"0.0.0.0"`
|
||||
Port uint `arg:"--http-port,env:HTTP_PORT" yaml:"port" default:"8080"`
|
||||
Tls bool `arg:"--http-tls,env:HTTP_TLS" yaml:"tls" default:"true"`
|
||||
TlsKey *string `arg:"--http-tls-key,env:HTTP_TLS_KEY" yaml:"tls-key"`
|
||||
TlsCert *string `arg:"--http-tls-cert,env:HTTP_TLS_CERT" yaml:"tls-cert"`
|
||||
PathGetLiveness string `arg:"env:HTTP_PATH_LIVENESS" yaml:"liveness" default:"/healthz"`
|
||||
PathGetReadiness string `arg:"env:HTTP_PATH_READINESS" yaml:"readiness" default:"/readyz"`
|
||||
StaticPath *Path `arg:"--http-static,env:HTTP_STATIC" yaml:"static"`
|
||||
}
|
||||
|
||||
type ConfigVideoSourceStream struct {
|
||||
Source string `arg:"--video-src,env:VIDEO_SRC" default:"v4l2src"`
|
||||
Device string `arg:"--video-src-device,env:VIDEO_SRC_DEVICE" default:"/dev/video0"`
|
||||
Codec StreamCodec `arg:"--video-src-codec,env:VIDEO_SRC_CODEC" default:"vp8"`
|
||||
Height uint `arg:"--video-src-height,env:VIDEO_SRC_HEIGHT" default:"480"`
|
||||
Width uint `arg:"--video-src-width,env:VIDEO_SRC_WIDTH" default:"640"`
|
||||
Framerate uint `arg:"--video-src-fps,env:VIDEO_SRC_FPS" default:"30"`
|
||||
Bitrate uint `arg:"--video-src-bps,env:VIDEO_SRC_BPS" default:"300"`
|
||||
Queue bool `arg:"--video-src-queue,env:VIDEO_SRC_QUEUE" default:"false"`
|
||||
Source string `arg:"--video-src,env:VIDEO_SRC" yaml:"source" default:"v4l2src"`
|
||||
Device string `arg:"--video-src-device,env:VIDEO_SRC_DEVICE" yaml:"device" default:"/dev/video0"`
|
||||
Codec StreamCodec `arg:"--video-src-codec,env:VIDEO_SRC_CODEC" yaml:"codec" default:"vp8"`
|
||||
Height uint `arg:"--video-src-height,env:VIDEO_SRC_HEIGHT" yaml:"height" default:"480"`
|
||||
Width uint `arg:"--video-src-width,env:VIDEO_SRC_WIDTH" yaml:"width" default:"640"`
|
||||
Framerate uint `arg:"--video-src-fps,env:VIDEO_SRC_FPS" yaml:"fps" default:"30"`
|
||||
Bitrate uint `arg:"--video-src-bps,env:VIDEO_SRC_BPS" yaml:"bps" default:"300"`
|
||||
Queue bool `arg:"--video-src-queue,env:VIDEO_SRC_QUEUE" yaml:"queue" default:"false"`
|
||||
}
|
||||
|
||||
type ConfigAudioSourceStream struct {
|
||||
Source string `arg:"--audio-src,env:AUDIO_SRC" default:"alsasrc"`
|
||||
DeviceName string `arg:"--audio-src-device-name,env:AUDIO_SRC_DEVICE_NAME" default:"default"`
|
||||
Device *string `arg:"--audio-src-device,env:AUDIO_SRC_DEVICE"`
|
||||
Codec StreamCodec `arg:"--audio-src-codec,env:AUDIO_SRC_CODEC" default:"opus"`
|
||||
Channels uint `arg:"--audio-src-channels,env:AUDIO_SRC_CHANNELS" default:"1"`
|
||||
Queue bool `arg:"--audio-src-queue,env:AUDIO_SRC_QUEUE" default:"false"`
|
||||
Source string `arg:"--audio-src,env:AUDIO_SRC" yaml:"source" default:"alsasrc"`
|
||||
DeviceName string `arg:"--audio-src-device-name,env:AUDIO_SRC_DEVICE_NAME" yaml:"name" default:"default"`
|
||||
Device *string `arg:"--audio-src-device,env:AUDIO_SRC_DEVICE" yaml:"device"`
|
||||
Codec StreamCodec `arg:"--audio-src-codec,env:AUDIO_SRC_CODEC" yaml:"codec" default:"opus"`
|
||||
Channels uint `arg:"--audio-src-channels,env:AUDIO_SRC_CHANNELS" yaml:"channels" default:"1"`
|
||||
Queue bool `arg:"--audio-src-queue,env:AUDIO_SRC_QUEUE" yaml:"queue" default:"false"`
|
||||
}
|
||||
|
||||
type ConfigAudioSinkStream struct {
|
||||
Sink string `arg:"--audio-sink,env:AUDIO_SINK" default:"alsasink"`
|
||||
DeviceName string `arg:"--audio-sink-device-name,env:AUDIO_SINK_DEVICE_NAME" default:"default"`
|
||||
Device *string `arg:"--audio-sink-device,env:AUDIO_SINK_DEVICE"`
|
||||
Codec string `arg:"--audio-sink-codec,env:AUDIO_SINK_CODEC" default:"opus"`
|
||||
Channels uint `arg:"--audio-sink-channels,env:AUDIO_SINK_CHANNELS" default:"1"`
|
||||
Queue bool `arg:"--audio-sink-queue,env:AUDIO_SINK_QUEUE" default:"false"`
|
||||
Sink string `arg:"--audio-sink,env:AUDIO_SINK" yaml:"sink" default:"alsasink"`
|
||||
DeviceName string `arg:"--audio-sink-device-name,env:AUDIO_SINK_DEVICE_NAME" yaml:"name" default:"default"`
|
||||
Device *string `arg:"--audio-sink-device,env:AUDIO_SINK_DEVICE" yaml:"device"`
|
||||
Codec string `arg:"--audio-sink-codec,env:AUDIO_SINK_CODEC" yaml:"codec" default:"opus"`
|
||||
Channels uint `arg:"--audio-sink-channels,env:AUDIO_SINK_CHANNELS" yaml:"channels" default:"1"`
|
||||
Queue bool `arg:"--audio-sink-queue,env:AUDIO_SINK_QUEUE" yaml:"queue" default:"false"`
|
||||
}
|
||||
|
||||
func (c *Config) Stream() *ConfigStream {
|
||||
@@ -89,11 +116,38 @@ func (c *ConfigHTTP) Address() string {
|
||||
return net.JoinHostPort(c.Host, fmt.Sprint(c.Port))
|
||||
}
|
||||
|
||||
func (p *Path) UnmarshalText(b []byte) error {
|
||||
p.string = string(b)
|
||||
|
||||
if sc, had := strings.CutPrefix(p.string, "~/"); had {
|
||||
dir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.string = filepath.Join(dir, sc)
|
||||
}
|
||||
|
||||
p.string = os.ExpandEnv(p.string)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) MustParse() {
|
||||
arg.MustParse(&c.VideoSrc)
|
||||
arg.MustParse(&c.AudioSrc)
|
||||
arg.MustParse(&c.AudioSink)
|
||||
arg.MustParse(&c.Logging)
|
||||
arg.MustParse(&c.Http)
|
||||
arg.MustParse(&c.Ring)
|
||||
// first parse just the config file flag
|
||||
arg.MustParse(&c.File)
|
||||
|
||||
if c.File.Path != nil {
|
||||
if _, err := os.Stat(c.File.Path.String()); err == nil {
|
||||
if data, err := os.ReadFile(c.File.Path.String()); err == nil {
|
||||
err := yaml.Unmarshal(data, c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse the rest
|
||||
arg.MustParse(c)
|
||||
}
|
||||
@@ -9,12 +9,13 @@ import (
|
||||
|
||||
func NewLogger(cfg *ConfigLogging) (*zap.Logger, error) {
|
||||
var c zap.Config
|
||||
if cfg.Level == "debug" {
|
||||
if cfg.Level.Level().CapitalString() == "DEBUG" {
|
||||
c = zap.NewDevelopmentConfig()
|
||||
} else {
|
||||
c = zap.NewProductionConfig()
|
||||
}
|
||||
|
||||
c.Level = cfg.Level
|
||||
c.EncoderConfig.TimeKey = "time"
|
||||
c.EncoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout(time.RFC3339)
|
||||
|
||||
|
||||
+13
-7
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
type PlayHandler interface {
|
||||
Play(*url.URL) error
|
||||
Play(context.Context, *url.URL) error
|
||||
Watch(context.Context) error
|
||||
}
|
||||
|
||||
@@ -24,16 +24,22 @@ type RingHandler struct {
|
||||
playHandlers []PlayHandler
|
||||
}
|
||||
|
||||
func NewRingHandler(lg *zap.Logger, cfg *common.ConfigRing) (*RingHandler, error) {
|
||||
func NewRingHandler(ctx context.Context, lg *zap.Logger, cfg *common.ConfigRing) error {
|
||||
spl, err := sonos.NewSonosHandler(lg.With(zap.String("context", "sonos")), cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
return &RingHandler{lg, cfg, []PlayHandler{spl}}, nil
|
||||
rh := &RingHandler{lg, cfg, []PlayHandler{spl}}
|
||||
|
||||
if err = rh.watch(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *RingHandler) Watch(ctx context.Context) error {
|
||||
func (h *RingHandler) watch(ctx context.Context) error {
|
||||
if h.cfg.Device == nil {
|
||||
h.lg.Warn("nothing to watch for key press")
|
||||
return nil
|
||||
@@ -75,9 +81,9 @@ func (h *RingHandler) Watch(ctx context.Context) error {
|
||||
e, err := d.ReadOne()
|
||||
if err == nil && e.Code == key && e.Value == 0 {
|
||||
// run all players
|
||||
tu := bu.JoinPath(h.cfg.JinglePath)
|
||||
tu := bu.JoinPath(h.cfg.JinglePath.String())
|
||||
for _, p := range h.playHandlers {
|
||||
if err := p.Play(tu); err != nil {
|
||||
if err := p.Play(ctx, tu); err != nil {
|
||||
h.lg.Error("failed to play", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,8 +72,8 @@ func NewSonosHandler(lg *zap.Logger, cfg *common.ConfigRing) (*SonosHandler, err
|
||||
return &SonosHandler{lg, cfg, make(map[string]*SonosPlayer)}, nil
|
||||
}
|
||||
|
||||
func (p *SonosPlayer) init() error {
|
||||
req, err := http.NewRequest(http.MethodGet, p.address.JoinPath("api/v1/players/local/info").String(), nil)
|
||||
func (p *SonosPlayer) init(ctx context.Context) error {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, p.address.JoinPath("api/v1/players/local/info").String(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -105,7 +105,7 @@ func (p *SonosPlayer) init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *SonosPlayer) Play(uri *url.URL, volume int) error {
|
||||
func (p *SonosPlayer) Play(ctx context.Context, uri *url.URL, volume int) error {
|
||||
sab := sonosAudioClip{
|
||||
Name: "Pull Bell",
|
||||
AppId: "com.acme.app",
|
||||
@@ -119,7 +119,7 @@ func (p *SonosPlayer) Play(uri *url.URL, volume int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, p.address.JoinPath(fmt.Sprintf("api/v1/players/%s/audioClip", p.info.PlayerId)).String(), bytes.NewBuffer(b))
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, p.address.JoinPath(fmt.Sprintf("api/v1/players/%s/audioClip", p.info.PlayerId)).String(), bytes.NewBuffer(b))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -161,7 +161,7 @@ func (h *SonosHandler) Watch(ctx context.Context) error {
|
||||
h.lg.Error("failed to create player", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
if err := p.init(); err != nil {
|
||||
if err := p.init(ctx); err != nil {
|
||||
h.lg.Error("failed to init player", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
@@ -188,10 +188,10 @@ func (h *SonosHandler) Watch(ctx context.Context) error {
|
||||
return mdns.Query(params)
|
||||
}
|
||||
|
||||
func (h *SonosHandler) Play(uri *url.URL) error {
|
||||
func (h *SonosHandler) Play(ctx context.Context, uri *url.URL) error {
|
||||
for _, p := range h.players {
|
||||
h.lg.Info("playing clip", zap.String("target", p.address.String()), zap.String("clip", uri.String()))
|
||||
if err := p.Play(uri, h.cfg.SonosVolume); err != nil {
|
||||
if err := p.Play(ctx, uri, h.cfg.SonosVolume); err != nil {
|
||||
h.lg.Error("failed to play", zap.String("address", p.address.String()), zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
+3
-5
@@ -56,9 +56,10 @@ func NewHttpServer(lg *zap.Logger, cfg *common.Config) *HttpServer {
|
||||
}
|
||||
|
||||
func (h *HttpServer) ListenAndServe(ctx context.Context) error {
|
||||
// set the configured address
|
||||
h.Addr = h.cfg.Http.Address()
|
||||
|
||||
if h.cfg.Http.Tls {
|
||||
// set the configured address
|
||||
h.Addr = h.cfg.Http.Address()
|
||||
|
||||
if h.cfg.Http.TlsCert != nil && h.cfg.Http.TlsKey != nil {
|
||||
cert, err := tls.LoadX509KeyPair(*h.cfg.Http.TlsCert, *h.cfg.Http.TlsKey)
|
||||
@@ -92,9 +93,6 @@ func (h *HttpServer) ListenAndServe(ctx context.Context) error {
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
// set the configured address
|
||||
h.Addr = h.cfg.Http.Address()
|
||||
|
||||
go func() {
|
||||
// and listen
|
||||
if err := h.Server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
|
||||
@@ -52,7 +52,7 @@ func CreateVideoPipelineSinkWithLaunch(lg *zap.Logger, s StreamElement) (*gst.Pi
|
||||
switch s.Codec {
|
||||
case common.VP8:
|
||||
pb.AddWithProperties("vp8enc", map[string]any{
|
||||
"bitrate": s.Bitrate,
|
||||
"target-bitrate": s.Bitrate,
|
||||
"error-resilient": "partitions",
|
||||
"keyframe-max-dist": int(10),
|
||||
"cpu-used": int(5),
|
||||
|
||||
Reference in new issue
Block a user