mirror of
https://github.com/gowvp/gb28181.git
synced 2026-04-22 23:17:19 +08:00
support onvif
This commit is contained in:
+28
-112
@@ -1,33 +1,32 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gowvp/gb28181/internal/conf"
|
||||
"github.com/gowvp/gb28181/internal/core/bz"
|
||||
gb28181 "github.com/gowvp/gb28181/internal/core/ipc"
|
||||
"github.com/gowvp/gb28181/internal/core/ipc"
|
||||
"github.com/gowvp/gb28181/internal/core/push"
|
||||
"github.com/gowvp/gb28181/internal/core/sms"
|
||||
"github.com/gowvp/gb28181/pkg/gbs"
|
||||
"github.com/gowvp/gb28181/pkg/zlm"
|
||||
"github.com/ixugo/goddd/pkg/web"
|
||||
)
|
||||
|
||||
type WebHookAPI struct {
|
||||
smsCore sms.Core
|
||||
mediaCore push.Core
|
||||
gb28181Core gb28181.Core
|
||||
gb28181Core ipc.Core
|
||||
conf *conf.Bootstrap
|
||||
log *slog.Logger
|
||||
gbs *gbs.Server
|
||||
uc *Usecase
|
||||
|
||||
protocols map[string]ipc.Protocoler
|
||||
}
|
||||
|
||||
func NewWebHookAPI(core sms.Core, mediaCore push.Core, conf *conf.Bootstrap, gbs *gbs.Server, gb28181 gb28181.Core) WebHookAPI {
|
||||
func NewWebHookAPI(core sms.Core, mediaCore push.Core, conf *conf.Bootstrap, gbs *gbs.Server, gb28181 ipc.Core, protocols map[string]ipc.Protocoler) WebHookAPI {
|
||||
return WebHookAPI{
|
||||
smsCore: core,
|
||||
mediaCore: mediaCore,
|
||||
@@ -35,6 +34,7 @@ func NewWebHookAPI(core sms.Core, mediaCore push.Core, conf *conf.Bootstrap, gbs
|
||||
log: slog.With("hook", "zlm"),
|
||||
gbs: gbs,
|
||||
gb28181Core: gb28181,
|
||||
protocols: protocols,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,29 +88,23 @@ func (w WebHookAPI) onPublish(c *gin.Context, in *onPublishInput) (*onPublishOut
|
||||
// https://docs.zlmediakit.com/zh/guide/media_server/web_hook_api.html#_12%E3%80%81on-stream-changed
|
||||
func (w WebHookAPI) onStreamChanged(c *gin.Context, in *onStreamChangedInput) (DefaultOutput, error) {
|
||||
w.log.InfoContext(c.Request.Context(), "webhook onStreamChanged", "app", in.App, "stream", in.Stream, "schema", in.Schema, "mediaServerID", in.MediaServerID, "regist", in.Regist)
|
||||
if in.App == "rtp" {
|
||||
// 防止多次触发
|
||||
if in.Schema == "rtmp" && !in.Regist {
|
||||
ch, err := w.gb28181Core.GetChannel(c.Request.Context(), in.Stream)
|
||||
if err != nil {
|
||||
w.log.WarnContext(c.Request.Context(), "webhook onStreamChanged", "err", err)
|
||||
return newDefaultOutputOK(), nil
|
||||
}
|
||||
w.gbs.StopPlay(&gbs.StopPlayInput{Channel: ch})
|
||||
if in.Regist || in.Schema != "rtmp" {
|
||||
return newDefaultOutputOK(), nil
|
||||
}
|
||||
|
||||
// TODO: 待重构
|
||||
if bz.IsRTMP(in.Stream) {
|
||||
if err := w.mediaCore.UnPublish(c.Request.Context(), in.App, in.Stream); err != nil {
|
||||
w.log.ErrorContext(c.Request.Context(), "webhook onStreamChanged", "err", err)
|
||||
}
|
||||
return newDefaultOutputOK(), nil
|
||||
}
|
||||
|
||||
if strings.HasPrefix(in.Stream, bz.IDPrefixRTSP) {
|
||||
return newDefaultOutputOK(), nil
|
||||
}
|
||||
|
||||
switch in.Schema {
|
||||
case "rtmp":
|
||||
if !in.Regist {
|
||||
if err := w.mediaCore.UnPublish(c.Request.Context(), in.App, in.Stream); err != nil {
|
||||
w.log.ErrorContext(c.Request.Context(), "webhook onStreamChanged", "err", err)
|
||||
}
|
||||
r := ipc.GetType(in.Stream)
|
||||
protocol, ok := w.protocols[r]
|
||||
if ok {
|
||||
if err := protocol.OnStreamChanged(c.Request.Context(), in.Stream); err != nil {
|
||||
slog.ErrorContext(c.Request.Context(), "webhook onStreamChanged", "err", err)
|
||||
}
|
||||
}
|
||||
return newDefaultOutputOK(), nil
|
||||
@@ -155,16 +149,6 @@ func (w WebHookAPI) onPlay(c *gin.Context, in *onPublishInput) (DefaultOutput, e
|
||||
func (w WebHookAPI) onStreamNoneReader(c *gin.Context, in *onStreamNoneReaderInput) (onStreamNoneReaderOutput, error) {
|
||||
// rtmp 无人观看时,也允许推流
|
||||
w.log.InfoContext(c.Request.Context(), "webhook onStreamNoneReader", "app", in.App, "stream", in.Stream, "mediaServerID", in.MediaServerID)
|
||||
|
||||
if in.App == "rtp" {
|
||||
ch, err := w.gb28181Core.GetChannel(c.Request.Context(), in.Stream)
|
||||
if err != nil {
|
||||
w.log.WarnContext(c.Request.Context(), "webhook onStreamNoneReader", "err", err)
|
||||
return onStreamNoneReaderOutput{Close: true}, nil
|
||||
}
|
||||
_ = w.gbs.StopPlay(&gbs.StopPlayInput{Channel: ch})
|
||||
} else if strings.HasPrefix(in.Stream, bz.IDPrefixRTSP) {
|
||||
}
|
||||
// 存在录像计划时,不关闭流
|
||||
return onStreamNoneReaderOutput{Close: true}, nil
|
||||
}
|
||||
@@ -179,86 +163,18 @@ func (w WebHookAPI) onRTPServerTimeout(c *gin.Context, in *onRTPServerTimeoutInp
|
||||
|
||||
func (w WebHookAPI) onStreamNotFound(c *gin.Context, in *onStreamNotFoundInput) (DefaultOutput, error) {
|
||||
w.log.InfoContext(c.Request.Context(), "webhook onStreamNotFound", "app", in.App, "stream", in.Stream, "schema", in.Schema, "mediaServerID", in.MediaServerID)
|
||||
// 防止重复触发
|
||||
if in.Schema != "rtmp" {
|
||||
return newDefaultOutputOK(), nil
|
||||
}
|
||||
|
||||
// 国标流处理
|
||||
if in.App == "rtp" {
|
||||
// 防止重复触发
|
||||
if in.Schema != "rtmp" {
|
||||
return newDefaultOutputOK(), nil
|
||||
}
|
||||
v := RTPStream{uc: w.uc}
|
||||
if err := v.onStreamNotFound(c.Request.Context(), in); err != nil {
|
||||
slog.ErrorContext(c.Request.Context(), "webhook onStreamNotFound", "err", err)
|
||||
}
|
||||
} else if strings.HasPrefix(in.Stream, bz.IDPrefixRTSP) {
|
||||
v := RTSPStream{uc: w.uc}
|
||||
if err := v.onStreamNotFound(c.Request.Context(), in); err != nil {
|
||||
r := ipc.GetType(in.Stream)
|
||||
protocol, ok := w.protocols[r]
|
||||
if ok {
|
||||
if err := protocol.OnStreamNotFound(c.Request.Context(), in.App, in.Stream); err != nil {
|
||||
slog.ErrorContext(c.Request.Context(), "webhook onStreamNotFound", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
return newDefaultOutputOK(), nil
|
||||
}
|
||||
|
||||
type RTPStream struct {
|
||||
uc *Usecase
|
||||
}
|
||||
|
||||
func (r RTPStream) onStreamNotFound(ctx context.Context, in *onStreamNotFoundInput) error {
|
||||
ch, err := r.uc.GB28181API.ipc.GetChannel(ctx, in.Stream)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dev, err := r.uc.GB28181API.ipc.GetDevice(ctx, ch.DID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
svr, err := r.uc.SMSAPI.smsCore.GetMediaServer(ctx, sms.DefaultMediaServerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return r.uc.WebHookAPI.gbs.Play(&gbs.PlayInput{
|
||||
Channel: ch,
|
||||
StreamMode: dev.StreamMode,
|
||||
SMS: svr,
|
||||
})
|
||||
}
|
||||
|
||||
type RTSPStream struct {
|
||||
uc *Usecase
|
||||
}
|
||||
|
||||
func (r RTSPStream) onStreamNotFound(ctx context.Context, in *onStreamNotFoundInput) error {
|
||||
proxy, err := r.uc.ProxyAPI.proxyCore.GetStreamProxy(ctx, in.Stream)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
svr, err := r.uc.SMSAPI.smsCore.GetMediaServer(ctx, sms.DefaultMediaServerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := r.uc.SMSAPI.smsCore.AddStreamProxy(svr, zlm.AddStreamProxyRequest{
|
||||
Vhost: "__defaultVhost__",
|
||||
App: proxy.App,
|
||||
Stream: proxy.Stream,
|
||||
URL: proxy.SourceURL,
|
||||
RetryCount: 3,
|
||||
RTPType: proxy.Transport,
|
||||
TimeoutSec: 10,
|
||||
EnableHLSFMP4: zlm.NewBool(true),
|
||||
EnableAudio: zlm.NewBool(true),
|
||||
EnableRTSP: zlm.NewBool(true),
|
||||
EnableRTMP: zlm.NewBool(true),
|
||||
AddMuteAudio: zlm.NewBool(true),
|
||||
AutoClose: zlm.NewBool(true),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 用于关闭
|
||||
r.uc.ProxyAPI.proxyCore.EditStreamProxyKey(ctx, resp.Data.Key, proxy.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user