mirror of
https://github.com/gowvp/gb28181.git
synced 2026-04-22 23:17:19 +08:00
support lalmax-pro
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gowvp/gb28181/pkg/lalmax"
|
||||
@@ -25,6 +26,7 @@ type LalmaxDriver struct {
|
||||
// GetStreamLiveAddr implements Driver.
|
||||
func (l *LalmaxDriver) GetStreamLiveAddr(ctx context.Context, ms *MediaServer, httpPrefix string, host string, app string, stream string) StreamLiveAddr {
|
||||
var out StreamLiveAddr
|
||||
out.Label = "StreamSVR"
|
||||
wsPrefix := strings.Replace(strings.Replace(httpPrefix, "https", "wss", 1), "http", "ws", 1)
|
||||
out.WSFLV = fmt.Sprintf("%s/proxy/sms/%s.flv", wsPrefix, stream)
|
||||
out.HTTPFLV = fmt.Sprintf("%s/proxy/sms/%s.flv", httpPrefix, stream)
|
||||
@@ -101,11 +103,12 @@ func (l *LalmaxDriver) GetSnapshot(ctx context.Context, ms *MediaServer, req *Ge
|
||||
// OpenRTPServer implements Driver.
|
||||
func (l *LalmaxDriver) OpenRTPServer(ctx context.Context, ms *MediaServer, req *zlm.OpenRTPServerRequest) (*zlm.OpenRTPServerResponse, error) {
|
||||
engine := l.withConfig(ms)
|
||||
|
||||
resp, err := engine.ApiCtrlStartRtpPub(ctx, lalmax.ApiCtrlStartRtpPubReq{
|
||||
StreamName: req.StreamID,
|
||||
Port: req.Port,
|
||||
TimeoutMs: PullTimeoutMs,
|
||||
IsTcpFlag: 0,
|
||||
IsTcpFlag: int(req.TCPMode),
|
||||
IsWaitKeyFrame: 0,
|
||||
IsTcpActive: false,
|
||||
DebugDumpPacket: "",
|
||||
@@ -131,6 +134,13 @@ func (l *LalmaxDriver) Protocol() string {
|
||||
// Setup implements Driver.
|
||||
func (l *LalmaxDriver) Setup(ctx context.Context, ms *MediaServer, webhookURL string) error {
|
||||
engine := l.withConfig(ms)
|
||||
|
||||
ports := strings.Split(ms.RTPPortRange, "-")
|
||||
var minPort, maxPort int
|
||||
if len(ports) == 2 {
|
||||
minPort, _ = strconv.Atoi(ports[0])
|
||||
maxPort, _ = strconv.Atoi(ports[1])
|
||||
}
|
||||
if err := engine.SetHttpNotifyConfig(ctx, lalmax.HttpNotifyConfig{
|
||||
Enable: true,
|
||||
// OnPubStart: webhookURL,
|
||||
@@ -138,6 +148,9 @@ func (l *LalmaxDriver) Setup(ctx context.Context, ms *MediaServer, webhookURL st
|
||||
OnSubStartWithoutStream: fmt.Sprintf("%s/on_stream_not_found", webhookURL),
|
||||
OnStreamChanged: fmt.Sprintf("%s/on_stream_changed", webhookURL),
|
||||
ClientSize: 50,
|
||||
}, lalmax.MediaConfig{
|
||||
ListenPort: minPort,
|
||||
MultiPortMaxIncrement: maxPort - minPort,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ type ZLMDriver struct {
|
||||
// GetStreamLiveAddr implements Driver.
|
||||
func (d *ZLMDriver) GetStreamLiveAddr(ctx context.Context, ms *MediaServer, httpPrefix, host, app, stream string) StreamLiveAddr {
|
||||
var out StreamLiveAddr
|
||||
out.Label = "ZLM"
|
||||
wsPrefix := strings.Replace(strings.Replace(httpPrefix, "https", "wss", 1), "http", "ws", 1)
|
||||
out.WSFLV = fmt.Sprintf("%s/proxy/sms/%s.live.flv", wsPrefix, stream)
|
||||
out.HTTPFLV = fmt.Sprintf("%s/proxy/sms/%s.live.flv", httpPrefix, stream)
|
||||
|
||||
@@ -37,6 +37,7 @@ type EditMediaServerInput struct {
|
||||
// Ports MediaServerPorts `json:"ports"`
|
||||
// AutoConfig bool `json:"auto_config"`
|
||||
Secret string `json:"secret"`
|
||||
Type string `json:"type"` // lalmax/zlm
|
||||
// HookAliveInterval int `json:"hook_alive_interval"`
|
||||
// RTPEnable bool `json:"rtpenable"`
|
||||
// Status bool `json:"status"`
|
||||
|
||||
@@ -64,6 +64,7 @@ func (a SmsAPI) editMediaServer(c *gin.Context, in *sms.EditMediaServerInput) (a
|
||||
a.uc.Conf.Media.SDPIP = out.SDPIP
|
||||
a.uc.Conf.Media.Secret = out.Secret
|
||||
a.uc.Conf.Media.WebHookIP = out.HookIP
|
||||
a.uc.Conf.Media.Type = out.Type
|
||||
if err := conf.WriteConfig(a.uc.Conf, a.uc.Conf.ConfigPath); err != nil {
|
||||
return nil, reason.ErrServer.SetMsg(err.Error())
|
||||
}
|
||||
|
||||
@@ -404,10 +404,14 @@ type SetServerConfigResponse struct {
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
func (e *Engine) SetHttpNotifyConfig(ctx context.Context, config HttpNotifyConfig) error {
|
||||
func (e *Engine) SetHttpNotifyConfig(ctx context.Context, config HttpNotifyConfig, gb28181 MediaConfig) error {
|
||||
// 使用合并模式,只更新 http_notify 配置
|
||||
data := map[string]any{
|
||||
"http_notify": config,
|
||||
"gb28181": map[string]any{
|
||||
"enable": false,
|
||||
"media_config": gb28181,
|
||||
},
|
||||
}
|
||||
return e.setServerConfig(ctx, data, true)
|
||||
}
|
||||
|
||||
@@ -105,7 +105,10 @@ func TestSetHttpNotifyConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置配置
|
||||
err := engine.SetHttpNotifyConfig(ctx, notifyConfig)
|
||||
err := engine.SetHttpNotifyConfig(ctx, notifyConfig, MediaConfig{
|
||||
ListenPort: 8080,
|
||||
MultiPortMaxIncrement: 10,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("SetHttpNotifyConfig 调用失败: %v", err)
|
||||
}
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ package lalmax
|
||||
|
||||
import "context"
|
||||
|
||||
const ctrlStartRtpPub = "/api/ctrl/startRtpPub"
|
||||
const ctrlStartRtpPub = "/api/ctrl/start_rtp_pub"
|
||||
|
||||
type ApiCtrlStartRtpPubReq struct {
|
||||
StreamName string `json:"stream_name"`
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package lalmax
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestApiCtrlStartRtpPub 测试启动 RTP 发布
|
||||
// 用法示例:go test -v -run TestApiCtrlStartRtpPub ./pkg/lalmax/
|
||||
// 前提条件:需要 lalmax 服务运行在 http://localhost:8080
|
||||
func TestApiCtrlStartRtpPub(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// 创建 Engine 实例
|
||||
engine := NewEngine()
|
||||
engine = engine.SetConfig(Config{
|
||||
URL: "http://localhost:8080",
|
||||
Secret: "", // 如果需要密钥,请填写
|
||||
})
|
||||
|
||||
// 构造请求参数
|
||||
// 注意:实际使用中可能需要确保流名称对应的流存在或符合预期,
|
||||
// 这里仅测试接口调用的连通性和基本参数传递。
|
||||
req := ApiCtrlStartRtpPubReq{
|
||||
StreamName: "test110", // 测试流名称
|
||||
Port: 0, // 0 表示让服务器自动分配端口
|
||||
PeerPort: 0, // 如不涉及对端被动接收,可填0或按需填写
|
||||
TimeoutMs: 10000, // 超时时间
|
||||
IsTcpFlag: 0, // 0: UDP, 1: TCP
|
||||
IsWaitKeyFrame: 1, // 是否等待关键帧
|
||||
DebugDumpPacket: "", // 调试抓包文件路径
|
||||
IsTcpActive: false, // 是否为 TCP 主动模式
|
||||
}
|
||||
|
||||
// 调用 ApiCtrlStartRtpPub 方法
|
||||
resp, err := engine.ApiCtrlStartRtpPub(ctx, req)
|
||||
if err != nil {
|
||||
t.Fatalf("ApiCtrlStartRtpPub 调用失败: %v", err)
|
||||
}
|
||||
|
||||
// 验证返回结果不为空
|
||||
if resp == nil {
|
||||
t.Fatal("ApiCtrlStartRtpPub 返回 nil")
|
||||
}
|
||||
|
||||
// 打印返回结果,用于调试
|
||||
t.Logf("响应代码 (Code): %d", resp.Code)
|
||||
t.Logf("响应描述 (Msg): %s", resp.Msg)
|
||||
t.Logf("流名称 (StreamName): %s", resp.Data.StreamName)
|
||||
t.Logf("会话 ID (SessionId): %s", resp.Data.SessionId)
|
||||
t.Logf("端口 (Port): %d", resp.Data.Port)
|
||||
|
||||
// 简单的校验,确保请求的流名称和返回的一致(如果成功的话)
|
||||
if resp.Code == 0 {
|
||||
if resp.Data.StreamName != req.StreamName {
|
||||
t.Errorf("期望流名称 %s, 实际返回 %s", req.StreamName, resp.Data.StreamName)
|
||||
}
|
||||
if resp.Data.Port == 0 && req.Port != 0 {
|
||||
// 如果请求指定了端口,期望返回该端口(视具体 lal 实现而定,这里仅作一般性检查)
|
||||
t.Logf("注意:返回端口为 0")
|
||||
}
|
||||
} else {
|
||||
t.Logf("注意:接口返回了非 0 错误码,这在没有实际流的情况下可能是预期的。")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user