Merge commit '6bd7fac875d9e9009915053d8a590abb372c5679' into feature/livekit-upgrade-1.13.1

This commit is contained in:
2026-06-25 23:54:33 +09:00
291 changed files with 37631 additions and 15381 deletions
+52 -29
View File
@@ -15,6 +15,7 @@
package main
import (
"context"
"fmt"
"os"
"strconv"
@@ -23,10 +24,12 @@ import (
"github.com/dustin/go-humanize"
"github.com/olekukonko/tablewriter"
"github.com/urfave/cli/v2"
"github.com/olekukonko/tablewriter/tw"
"github.com/urfave/cli/v3"
"gopkg.in/yaml.v3"
"github.com/livekit/protocol/auth"
"github.com/livekit/protocol/livekit"
"github.com/livekit/protocol/utils"
"github.com/livekit/protocol/utils/guid"
@@ -35,7 +38,7 @@ import (
"github.com/livekit/livekit-server/pkg/service"
)
func generateKeys(_ *cli.Context) error {
func generateKeys(_ context.Context, _ *cli.Command) error {
apiKey := guid.New(utils.APIKeyPrefix)
secret := utils.RandomSecret()
fmt.Println("API Key: ", apiKey)
@@ -43,7 +46,7 @@ func generateKeys(_ *cli.Context) error {
return nil
}
func printPorts(c *cli.Context) error {
func printPorts(_ context.Context, c *cli.Command) error {
conf, err := getConfig(c)
if err != nil {
return err
@@ -84,17 +87,21 @@ func printPorts(c *cli.Context) error {
return nil
}
func helpVerbose(c *cli.Context) error {
func helpVerbose(_ context.Context, c *cli.Command) error {
generatedFlags, err := config.GenerateCLIFlags(baseFlags, false)
if err != nil {
return err
}
c.App.Flags = append(baseFlags, generatedFlags...)
flags := append([]cli.Flag{}, baseFlags...)
flags = append(flags, generatedFlags...)
root := c.Root()
root.Flags = flags
c.Flags = flags
return cli.ShowAppHelp(c)
}
func createToken(c *cli.Context) error {
func createToken(_ context.Context, c *cli.Command) error {
room := c.String("room")
identity := c.String("identity")
@@ -160,7 +167,7 @@ func createToken(c *cli.Context) error {
return nil
}
func listNodes(c *cli.Context) error {
func listNodes(_ context.Context, c *cli.Command) error {
conf, err := getConfig(c)
if err != nil {
return err
@@ -181,10 +188,27 @@ func listNodes(c *cli.Context) error {
return err
}
table := tablewriter.NewWriter(os.Stdout)
table.SetRowLine(true)
table.SetAutoWrapText(false)
table.SetHeader([]string{
table := tablewriter.NewTable(os.Stdout,
tablewriter.WithHeaderAutoFormat(tw.Off),
tablewriter.WithRowAutoWrap(0),
tablewriter.WithRendition(tw.Rendition{
Settings: tw.Settings{
Separators: tw.Separators{BetweenRows: tw.On},
},
}),
tablewriter.WithRowAlignmentConfig(tw.CellAlignment{
PerColumn: []tw.Align{
tw.AlignCenter, tw.AlignCenter, tw.AlignCenter,
tw.AlignRight, tw.AlignRight,
tw.AlignRight,
tw.AlignRight, tw.AlignRight,
tw.AlignRight, tw.AlignRight, tw.AlignRight,
tw.AlignRight, tw.AlignRight,
tw.AlignCenter,
},
}),
)
table.Header(
"ID", "IP Address", "Region",
"CPUs", "CPU Usage\nLoad Avg",
"Memory Used/Total",
@@ -192,19 +216,14 @@ func listNodes(c *cli.Context) error {
"Bytes/s In/Out\nBytes Total", "Packets/s In/Out\nPackets Total", "System Dropped Pkts/s\nPkts/s Out/Dropped",
"Nack/s\nNack Total", "Retrans/s\nRetrans Total",
"Started At\nUpdated At",
})
table.SetColumnAlignment([]int{
tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER,
tablewriter.ALIGN_RIGHT, tablewriter.ALIGN_RIGHT,
tablewriter.ALIGN_RIGHT,
tablewriter.ALIGN_RIGHT, tablewriter.ALIGN_RIGHT,
tablewriter.ALIGN_RIGHT, tablewriter.ALIGN_RIGHT, tablewriter.ALIGN_RIGHT,
tablewriter.ALIGN_RIGHT, tablewriter.ALIGN_RIGHT,
tablewriter.ALIGN_CENTER,
})
)
for _, node := range nodes {
stats := node.Stats
rate := &livekit.NodeStatsRate{}
if len(stats.Rates) > 0 {
rate = stats.Rates[0]
}
// Id and state
idAndState := fmt.Sprintf("%s\n(%s)", node.Id, node.State.Enum().String())
@@ -220,19 +239,23 @@ func listNodes(c *cli.Context) error {
clientsAndTracks := fmt.Sprintf("%d\n%d / %d", stats.NumClients, stats.NumTracksIn, stats.NumTracksOut)
// Packet stats
bytes := fmt.Sprintf("%sps / %sps\n%s / %s", humanize.Bytes(uint64(stats.BytesInPerSec)), humanize.Bytes(uint64(stats.BytesOutPerSec)),
bytes := fmt.Sprintf("%sps / %sps\n%s / %s", humanize.Bytes(uint64(rate.BytesIn)), humanize.Bytes(uint64(rate.BytesOut)),
humanize.Bytes(stats.BytesIn), humanize.Bytes(stats.BytesOut))
packets := fmt.Sprintf("%s / %s\n%s / %s", humanize.Comma(int64(stats.PacketsInPerSec)), humanize.Comma(int64(stats.PacketsOutPerSec)),
packets := fmt.Sprintf("%s / %s\n%s / %s", humanize.Comma(int64(rate.PacketsIn)), humanize.Comma(int64(rate.PacketsOut)),
strings.TrimSpace(humanize.SIWithDigits(float64(stats.PacketsIn), 2, "")), strings.TrimSpace(humanize.SIWithDigits(float64(stats.PacketsOut), 2, "")))
sysPackets := fmt.Sprintf("%.2f %%\n%v / %v", stats.SysPacketsDroppedPctPerSec*100, float64(stats.SysPacketsOutPerSec), float64(stats.SysPacketsDroppedPerSec))
nacks := fmt.Sprintf("%.2f\n%s", stats.NackPerSec, strings.TrimSpace(humanize.SIWithDigits(float64(stats.NackTotal), 2, "")))
retransmit := fmt.Sprintf("%.2f\n%s", stats.RetransmitPacketsOutPerSec, strings.TrimSpace(humanize.SIWithDigits(float64(stats.RetransmitPacketsOut), 2, "")))
sysPacketsDroppedPct := float32(0)
if rate.SysPacketsOut+rate.SysPacketsDropped > 0 {
sysPacketsDroppedPct = float32(rate.SysPacketsDropped) / float32(rate.SysPacketsDropped+rate.SysPacketsOut)
}
sysPackets := fmt.Sprintf("%.2f %%\n%v / %v", sysPacketsDroppedPct*100, float64(rate.SysPacketsOut), float64(rate.SysPacketsDropped))
nacks := fmt.Sprintf("%.2f\n%s", rate.NackTotal, strings.TrimSpace(humanize.SIWithDigits(float64(stats.NackTotal), 2, "")))
retransmit := fmt.Sprintf("%.2f\n%s", rate.RetransmitPacketsOut, strings.TrimSpace(humanize.SIWithDigits(float64(stats.RetransmitPacketsOut), 2, "")))
// Date
startedAndUpdated := fmt.Sprintf("%s\n%s", time.Unix(stats.StartedAt, 0).UTC().UTC().Format("2006-01-02 15:04:05"),
time.Unix(stats.UpdatedAt, 0).UTC().Format("2006-01-02 15:04:05"))
table.Append([]string{
table.Append(
idAndState, node.Ip, node.Region,
cpus, cpuUsageAndLoadAvg,
memUsage,
@@ -240,9 +263,9 @@ func listNodes(c *cli.Context) error {
bytes, packets, sysPackets,
nacks, retransmit,
startedAndUpdated,
})
)
}
table.Render()
table.Render() //nolint:errcheck
return nil
}
+46 -22
View File
@@ -15,6 +15,7 @@
package main
import (
"context"
"fmt"
"math/rand"
"net"
@@ -25,15 +26,16 @@ import (
"syscall"
"time"
"github.com/urfave/cli/v2"
"github.com/urfave/cli/v3"
"github.com/livekit/livekit-server/pkg/rtc"
"github.com/livekit/livekit-server/pkg/telemetry/prometheus"
"github.com/livekit/protocol/logger"
"github.com/livekit/protocol/tracer/jaeger"
"github.com/livekit/livekit-server/pkg/config"
"github.com/livekit/livekit-server/pkg/routing"
"github.com/livekit/livekit-server/pkg/rtc"
"github.com/livekit/livekit-server/pkg/service"
"github.com/livekit/livekit-server/pkg/telemetry/prometheus"
"github.com/livekit/livekit-server/version"
)
@@ -49,7 +51,7 @@ var baseFlags = []cli.Flag{
&cli.StringFlag{
Name: "config-body",
Usage: "LiveKit config in YAML, typically passed in as an environment var in a container",
EnvVars: []string{"LIVEKIT_CONFIG"},
Sources: cli.EnvVars("LIVEKIT_CONFIG"),
},
&cli.StringFlag{
Name: "key-file",
@@ -58,44 +60,47 @@ var baseFlags = []cli.Flag{
&cli.StringFlag{
Name: "keys",
Usage: "api keys (key: secret\\n)",
EnvVars: []string{"LIVEKIT_KEYS"},
Sources: cli.EnvVars("LIVEKIT_KEYS"),
},
&cli.StringFlag{
Name: "region",
Usage: "region of the current node. Used by regionaware node selector",
EnvVars: []string{"LIVEKIT_REGION"},
Sources: cli.EnvVars("LIVEKIT_REGION"),
},
&cli.StringFlag{
Name: "node-ip",
Usage: "IP address of the current node, used to advertise to clients. Automatically determined by default",
EnvVars: []string{"NODE_IP"},
Sources: cli.EnvVars("NODE_IP"),
},
&cli.StringFlag{
Name: "udp-port",
Usage: "UDP port(s) to use for WebRTC traffic",
EnvVars: []string{"UDP_PORT"},
Sources: cli.EnvVars("UDP_PORT"),
},
&cli.StringFlag{
Name: "redis-host",
Usage: "host (incl. port) to redis server",
EnvVars: []string{"REDIS_HOST"},
Sources: cli.EnvVars("REDIS_HOST"),
},
&cli.StringFlag{
Name: "redis-password",
Usage: "password to redis",
EnvVars: []string{"REDIS_PASSWORD"},
Sources: cli.EnvVars("REDIS_PASSWORD"),
},
&cli.StringFlag{
Name: "turn-cert",
Usage: "tls cert file for TURN server",
EnvVars: []string{"LIVEKIT_TURN_CERT"},
Sources: cli.EnvVars("LIVEKIT_TURN_CERT"),
},
&cli.StringFlag{
Name: "turn-key",
Usage: "tls key file for TURN server",
EnvVars: []string{"LIVEKIT_TURN_KEY"},
Sources: cli.EnvVars("LIVEKIT_TURN_KEY"),
},
&cli.StringFlag{
Name: "cpuprofile",
Usage: "write CPU profile to `file`",
},
// debugging flags
&cli.StringFlag{
Name: "memprofile",
Usage: "write memory profile to `file`",
@@ -127,7 +132,7 @@ func main() {
fmt.Println(err)
}
app := &cli.App{
cmd := &cli.Command{
Name: "livekit-server",
Usage: "High performance WebRTC server",
Description: "run without subcommands to start the server",
@@ -182,21 +187,18 @@ func main() {
Version: version.Version,
}
if err := app.Run(os.Args); err != nil {
if err := cmd.Run(context.Background(), os.Args); err != nil {
fmt.Println(err)
}
}
func getConfig(c *cli.Context) (*config.Config, error) {
func getConfig(c *cli.Command) (*config.Config, error) {
confString, err := getConfigString(c.String("config"), c.String("config-body"))
if err != nil {
return nil, err
}
strictMode := true
if c.Bool("disable-strict-config") {
strictMode = false
}
strictMode := !c.Bool("disable-strict-config")
conf, err := config.NewConfig(confString, strictMode, c, baseFlags)
if err != nil {
@@ -242,11 +244,14 @@ func getConfig(c *cli.Context) (*config.Config, error) {
return conf, nil
}
func startServer(c *cli.Context) error {
func startServer(ctx context.Context, c *cli.Command) error {
conf, err := getConfig(c)
if err != nil {
return err
}
if url := conf.Trace.JaegerURL; url != "" {
jaeger.Configure(ctx, url, "livekit")
}
// validate API key length
err = conf.ValidateKeys()
@@ -254,6 +259,25 @@ func startServer(c *cli.Context) error {
return err
}
if err = conf.LoadTURNSecrets(); err != nil {
return err
}
if cpuProfile := c.String("cpuprofile"); cpuProfile != "" {
if f, err := os.Create(cpuProfile); err != nil {
return err
} else {
if err := pprof.StartCPUProfile(f); err != nil {
f.Close()
return err
}
defer func() {
pprof.StopCPUProfile()
f.Close()
}()
}
}
if memProfile := c.String("memprofile"); memProfile != "" {
if f, err := os.Create(memProfile); err != nil {
return err
@@ -285,7 +309,7 @@ func startServer(c *cli.Context) error {
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
go func() {
for i := 0; i < 2; i++ {
for i := range 2 {
sig := <-sigChan
force := i > 0
logger.Infow("exit requested, shutting down", "signal", sig, "force", force)