mirror of
https://github.com/gowvp/gb28181.git
synced 2025-09-26 19:41:19 +08:00
重构 main 函数
This commit is contained in:
4
Makefile
4
Makefile
@@ -187,8 +187,8 @@ docker/build/test: build/clean build/linux
|
||||
@docker build --force-rm=true -t $(IMAGE_NAME) -f Dockerfile_full .
|
||||
|
||||
docker/build/full: build/clean build/linux
|
||||
@docker build --force-rm=true --push --platform linux/amd64,linux/arm64 -t $(IMAGE_NAME) -f Dockerfile_full .
|
||||
# @docker build --force-rm=true --push --platform linux/amd64,linux/arm64 -t registry.cn-shanghai.aliyuncs.com/ixugo/homenvr:latest -f Dockerfile_full .
|
||||
#@docker build --force-rm=true --push --platform linux/amd64,linux/arm64 -t $(IMAGE_NAME) -f Dockerfile_full .
|
||||
@docker build --force-rm=true --push --platform linux/amd64,linux/arm64 -t registry.cn-shanghai.aliyuncs.com/ixugo/homenvr:latest -f Dockerfile_full .
|
||||
|
||||
docker/build/gowvp: build/clean build/linux
|
||||
@docker build --force-rm=true --push --platform linux/amd64,linux/arm64 -t registry.cn-shanghai.aliyuncs.com/ixugo/gowvp:latest -f Dockerfile .
|
||||
|
@@ -1,64 +1,64 @@
|
||||
[Server]
|
||||
Debug = false
|
||||
# rtmp 推流秘钥
|
||||
RTMPSecret = '123'
|
||||
Debug = false
|
||||
# rtmp 推流秘钥
|
||||
RTMPSecret = '123'
|
||||
|
||||
# 对外提供的服务,建议由 nginx 代理
|
||||
[Server.HTTP]
|
||||
# http 端口
|
||||
Port = 15123
|
||||
# 请求超时时间
|
||||
Timeout = '1m0s'
|
||||
# jwt 秘钥,空串时,每次启动程序将随机赋值
|
||||
JwtSecret = ''
|
||||
# 对外提供的服务,建议由 nginx 代理
|
||||
[Server.HTTP]
|
||||
# http 端口
|
||||
Port = 15123
|
||||
# 请求超时时间
|
||||
Timeout = '1m0s'
|
||||
# jwt 秘钥,空串时,每次启动程序将随机赋值
|
||||
JwtSecret = ''
|
||||
|
||||
[Server.HTTP.PProf]
|
||||
# 是否启用 pprof, 建议设置为 true
|
||||
Enabled = true
|
||||
# 访问白名单
|
||||
AccessIps = ['::1', '127.0.0.1']
|
||||
[Server.HTTP.PProf]
|
||||
# 是否启用 pprof, 建议设置为 true
|
||||
Enabled = true
|
||||
# 访问白名单
|
||||
AccessIps = ['::1', '127.0.0.1']
|
||||
|
||||
[Data]
|
||||
# 数据库支持 sqlite 和 postgres 两种,使用 sqlite 时 dsn 应当填写文件存储路径
|
||||
[Data.Database]
|
||||
Dsn = './configs/data.db'
|
||||
MaxIdleConns = 1
|
||||
MaxOpenConns = 1
|
||||
ConnMaxLifetime = '6h0m0s'
|
||||
SlowThreshold = '200ms'
|
||||
# 数据库支持 sqlite 和 postgres 两种,使用 sqlite 时 dsn 应当填写文件存储路径
|
||||
[Data.Database]
|
||||
Dsn = './configs/data.db'
|
||||
MaxIdleConns = 1
|
||||
MaxOpenConns = 1
|
||||
ConnMaxLifetime = '6h0m0s'
|
||||
SlowThreshold = '200ms'
|
||||
|
||||
[Log]
|
||||
# 日志存储目录,不能使用特殊符号
|
||||
Dir = './logs'
|
||||
# 记录级别 debug/info/warn/error
|
||||
Level = 'debug'
|
||||
# 保留日志多久,超过时间自动删除
|
||||
MaxAge = '744h0m0s'
|
||||
# 多久时间,分割一个新的日志文件
|
||||
RotationTime = '12h0m0s'
|
||||
# 多大文件,分割一个新的日志文件(MB)
|
||||
RotationSize = 50
|
||||
# 日志存储目录,不能使用特殊符号
|
||||
Dir = './logs'
|
||||
# 记录级别 debug/info/warn/error
|
||||
Level = 'debug'
|
||||
# 保留日志多久,超过时间自动删除
|
||||
MaxAge = '744h0m0s'
|
||||
# 多久时间,分割一个新的日志文件
|
||||
RotationTime = '12h0m0s'
|
||||
# 多大文件,分割一个新的日志文件(MB)
|
||||
RotationSize = 50
|
||||
|
||||
[Sip]
|
||||
# 服务监听的 tcp/udp 端口号
|
||||
Port = 15060
|
||||
# gb/t28181 20 位国标 ID
|
||||
ID = '3402000000200000001'
|
||||
# 域
|
||||
Domain = '3402000000'
|
||||
# 注册密码
|
||||
Password = ''
|
||||
# 服务监听的 tcp/udp 端口号
|
||||
Port = 15060
|
||||
# gb/t28181 20 位国标 ID
|
||||
ID = '3402000000200000001'
|
||||
# 域
|
||||
Domain = '3402000000'
|
||||
# 注册密码
|
||||
Password = ''
|
||||
|
||||
[Media]
|
||||
# 媒体服务器 IP
|
||||
IP = '127.0.0.1'
|
||||
# 媒体服务器 HTTP 端口
|
||||
HTTPPort = 8080
|
||||
# 媒体服务器密钥
|
||||
Secret = 'jvRqCAzEg7AszBi4gm1cfhwXpmnVmJMG'
|
||||
# 用于流媒体 webhook 回调
|
||||
WebHookIP = '192.168.31.180'
|
||||
# 媒体服务器 RTP 端口范围
|
||||
RTPPortRange = '20000-20100'
|
||||
# 媒体服务器 SDP IP
|
||||
SDPIP = '192.168.31.180'
|
||||
# 媒体服务器 IP
|
||||
IP = '127.0.0.1'
|
||||
# 媒体服务器 HTTP 端口
|
||||
HTTPPort = 8080
|
||||
# 媒体服务器密钥
|
||||
Secret = 'jvRqCAzEg7AszBi4gm1cfhwXpmnVmJMG'
|
||||
# 用于流媒体 webhook 回调
|
||||
WebHookIP = '192.168.10.37'
|
||||
# 媒体服务器 RTP 端口范围
|
||||
RTPPortRange = '20000-20100'
|
||||
# 媒体服务器 SDP IP
|
||||
SDPIP = '192.168.10.37'
|
||||
|
@@ -1,8 +1,6 @@
|
||||
package main
|
||||
package app
|
||||
|
||||
import (
|
||||
"expvar"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
@@ -21,75 +19,25 @@ import (
|
||||
"github.com/ixugo/goddd/pkg/system"
|
||||
)
|
||||
|
||||
var (
|
||||
buildVersion = "0.0.1" // 构建版本号
|
||||
gitBranch = "dev" // git 分支
|
||||
gitHash = "debug" // git 提交点哈希值
|
||||
release string // 发布模式 true/false
|
||||
buildTime string // 构建时间戳
|
||||
)
|
||||
|
||||
// 自定义配置目录
|
||||
var configDir = flag.String("conf", "./configs", "config directory, eg: -conf /configs/")
|
||||
|
||||
func getBuildRelease() bool {
|
||||
v, _ := strconv.ParseBool(release)
|
||||
return v
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
func Run(bc *conf.Bootstrap) {
|
||||
// 以可执行文件所在目录为工作目录,防止以服务方式运行时,工作目录切换到其它位置
|
||||
bin, _ := os.Executable()
|
||||
if err := os.Chdir(filepath.Dir(bin)); err != nil {
|
||||
slog.Error("change dir error")
|
||||
}
|
||||
go setupZLM(*configDir)
|
||||
// 初始化配置
|
||||
var bc conf.Bootstrap
|
||||
// 获取配置目录绝对路径
|
||||
fileDir, _ := abs(*configDir)
|
||||
os.MkdirAll(fileDir, 0o755)
|
||||
filePath := filepath.Join(fileDir, "config.toml")
|
||||
configIsNotExistWrite(filePath)
|
||||
if err := conf.SetupConfig(&bc, filePath); err != nil {
|
||||
panic(err)
|
||||
slog.Error("change work dir fail", "err", err)
|
||||
}
|
||||
|
||||
bc.Debug = !getBuildRelease()
|
||||
bc.BuildVersion = buildVersion
|
||||
bc.ConfigDir = fileDir
|
||||
bc.ConfigPath = filePath
|
||||
log, clean := SetupLog(bc)
|
||||
defer clean()
|
||||
|
||||
// 初始化日志
|
||||
logDir := filepath.Join(system.Getwd(), *configDir, bc.Log.Dir)
|
||||
if filepath.IsAbs(bc.Log.Dir) {
|
||||
logDir = bc.Log.Dir
|
||||
}
|
||||
log, clean := logger.SetupSlog(logger.Config{
|
||||
Dir: logDir, // 日志地址
|
||||
Debug: bc.Debug, // 服务级别Debug/Release
|
||||
MaxAge: bc.Log.MaxAge.Duration(), // 日志存储时间
|
||||
RotationTime: bc.Log.RotationTime.Duration(), // 循环时间
|
||||
RotationSize: bc.Log.RotationSize * 1024 * 1024, // 循环大小
|
||||
Level: bc.Log.Level, // 日志级别
|
||||
})
|
||||
{
|
||||
expvar.NewString("version").Set(buildVersion)
|
||||
expvar.NewString("git_branch").Set(gitBranch)
|
||||
expvar.NewString("git_hash").Set(gitHash)
|
||||
expvar.NewString("build_time").Set(buildTime)
|
||||
expvar.Publish("timestamp", expvar.Func(func() any {
|
||||
return time.Now().Format(time.DateTime)
|
||||
}))
|
||||
}
|
||||
|
||||
go setupSecret(&bc)
|
||||
go setupZLM(bc.ConfigDir)
|
||||
|
||||
// TODO: 异步发现 zlm 配置,有概率程序启动了,才找到 zlm 的秘钥,建议提前配置好秘钥
|
||||
go setupSecret(bc)
|
||||
// 如果需要执行表迁移,递增此版本号和表更新说明
|
||||
versionapi.DBVersion = "0.0.10"
|
||||
versionapi.DBRemark = "add stream proxy"
|
||||
handler, cleanUp, err := wireApp(&bc, log)
|
||||
|
||||
handler, cleanUp, err := wireApp(bc, log)
|
||||
if err != nil {
|
||||
slog.Error("程序构建失败", "err", err)
|
||||
panic(err)
|
||||
@@ -116,8 +64,19 @@ func main() {
|
||||
if err := svc.Shutdown(); err != nil {
|
||||
slog.Error(`server.Shutdown()`, "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
defer clean()
|
||||
// SetupLog 初始化日志
|
||||
func SetupLog(bc *conf.Bootstrap) (*slog.Logger, func()) {
|
||||
logDir := filepath.Join(system.Getwd(), bc.Log.Dir)
|
||||
return logger.SetupSlog(logger.Config{
|
||||
Dir: logDir, // 日志地址
|
||||
Debug: bc.Debug, // 服务级别Debug/Release
|
||||
MaxAge: bc.Log.MaxAge.Duration(), // 日志存储时间
|
||||
RotationTime: bc.Log.RotationTime.Duration(), // 循环时间
|
||||
RotationSize: bc.Log.RotationSize * 1024 * 1024, // 循环大小
|
||||
Level: bc.Log.Level, // 日志级别
|
||||
})
|
||||
}
|
||||
|
||||
func abs(path string) (string, error) {
|
||||
@@ -131,14 +90,6 @@ func abs(path string) (string, error) {
|
||||
return filepath.Join(filepath.Dir(bin), path), nil
|
||||
}
|
||||
|
||||
func configIsNotExistWrite(path string) {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
if err := conf.WriteConfig(conf.DefaultConfig(), path); err != nil {
|
||||
system.ErrPrintf("WriteConfig", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 读取 config.ini 文件,通过正则表达式,获取 secret 的值
|
||||
func getSecret(configDir string) (string, error) {
|
||||
for _, file := range []string{"zlm.ini", "config.ini"} {
|
||||
@@ -190,7 +141,7 @@ func setupZLM(dir string) {
|
||||
|
||||
func setupSecret(bc *conf.Bootstrap) {
|
||||
for range 3 {
|
||||
secret, err := getSecret(*configDir)
|
||||
secret, err := getSecret(bc.ConfigDir)
|
||||
if err == nil {
|
||||
slog.Info("发现 zlm 配置,已赋值,未回写配置文件", "secret", secret)
|
||||
bc.Media.Secret = secret
|
@@ -1,7 +1,7 @@
|
||||
//go:build wireinject
|
||||
// +build wireinject
|
||||
|
||||
package main
|
||||
package app
|
||||
|
||||
import (
|
||||
"log/slog"
|
@@ -4,7 +4,7 @@
|
||||
//go:build !wireinject
|
||||
// +build !wireinject
|
||||
|
||||
package main
|
||||
package app
|
||||
|
||||
import (
|
||||
"github.com/gowvp/gb28181/internal/conf"
|
@@ -17,9 +17,10 @@ func SetupConfig(v any, path string) error {
|
||||
|
||||
// WriteConfig 将配置写回文件
|
||||
func WriteConfig(v any, path string) error {
|
||||
b, err := toml.Marshal(v)
|
||||
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(path, b, 0o600)
|
||||
defer f.Close()
|
||||
return toml.NewEncoder(f).SetIndentTables(true).Encode(v)
|
||||
}
|
||||
|
@@ -80,6 +80,7 @@ func (a ConfigAPI) editSIP(_ *gin.Context, in *conf.SIP) (gin.H, error) {
|
||||
if err := copier.Copy(&sip, in); err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(err.Error())
|
||||
}
|
||||
|
||||
if err := conf.WriteConfig(a.conf, a.conf.ConfigPath); err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(err.Error())
|
||||
}
|
||||
|
68
main.go
Normal file
68
main.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"expvar"
|
||||
"flag"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gowvp/gb28181/internal/app"
|
||||
"github.com/gowvp/gb28181/internal/conf"
|
||||
"github.com/ixugo/goddd/pkg/system"
|
||||
)
|
||||
|
||||
var (
|
||||
buildVersion = "0.0.1" // 构建版本号
|
||||
gitBranch = "dev" // git 分支
|
||||
gitHash = "debug" // git 提交点哈希值
|
||||
release string // 发布模式 true/false
|
||||
buildTime string // 构建时间戳
|
||||
)
|
||||
|
||||
// 自定义配置目录
|
||||
var configDir = flag.String("conf", "./configs", "config directory, eg: -conf /configs/")
|
||||
|
||||
func getBuildRelease() bool {
|
||||
v, _ := strconv.ParseBool(release)
|
||||
return v
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
// 初始化配置
|
||||
var bc conf.Bootstrap
|
||||
filedir, _ := system.Abs(*configDir)
|
||||
_ = os.MkdirAll(filedir, 0o755)
|
||||
filePath := filepath.Join(filedir, "config.toml")
|
||||
|
||||
configIsNotExistWrite(filePath)
|
||||
if err := conf.SetupConfig(&bc, filePath); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
bc.Debug = !getBuildRelease()
|
||||
bc.BuildVersion = buildVersion
|
||||
|
||||
{
|
||||
expvar.NewString("version").Set(buildVersion)
|
||||
expvar.NewString("git_branch").Set(gitBranch)
|
||||
expvar.NewString("git_hash").Set(gitHash)
|
||||
expvar.NewString("build_time").Set(buildTime)
|
||||
expvar.Publish("timestamp", expvar.Func(func() any {
|
||||
return time.Now().Format(time.DateTime)
|
||||
}))
|
||||
}
|
||||
|
||||
app.Run(&bc)
|
||||
}
|
||||
|
||||
// configIsNotExistWrite 配置文件不存在时,回写配置
|
||||
func configIsNotExistWrite(path string) {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
if err := conf.WriteConfig(conf.DefaultConfig(), path); err != nil {
|
||||
system.ErrPrintf("WriteConfig", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
@@ -66,7 +66,13 @@ func (g *GB28181API) Play(in *PlayInput) error {
|
||||
key := "play:" + in.Channel.DeviceID + ":" + in.Channel.ChannelID
|
||||
stream, ok := g.streams.LoadOrStore(key, &Streams{})
|
||||
if ok {
|
||||
return nil
|
||||
// TODO: 临时解决方案,每次播放,先停止再播放
|
||||
// https://github.com/gowvp/gb28181/issues/16
|
||||
if err := g.StopPlay(&StopPlayInput{
|
||||
Channel: in.Channel,
|
||||
}); err != nil {
|
||||
slog.Error("stop play failed", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 开启RTP服务器等待接收视频流
|
||||
|
Reference in New Issue
Block a user