使用 URL 参数将 RTSP 流转换为 WebRTC

问题描述 投票:0回答:1

我想将给定的 RTSP 流 URL 从 IP 摄像机转换为 WebRTC 并在浏览器中显示。我完成了那部分,我想更改代码,可以使用 URL 参数(如 ?camera=camera01、?camera=camera02 等)更改 IP 摄像机。 RTSP URL 是硬编码的,无需担心。

Curranty 我像这样更改相机:http://127.0.0.1:8083/stream/player/Camera01 我想像这样更改相机:http://127.0.0.1:8088/stream/player?camera=Camera01

我该如何改变?

package main

import (
    "encoding/json"
    "log"
    "net/http"
    "os"
    "sort"
    "time"

    "github.com/deepch/vdk/av"

    webrtc "github.com/deepch/vdk/format/webrtcv3"
    "github.com/gin-gonic/gin"
)

type JCodec struct {
    Type string
}

func serveHTTP() {
    gin.SetMode(gin.ReleaseMode)

    router := gin.Default()
    router.Use(CORSMiddleware())

    if _, err := os.Stat("./web"); !os.IsNotExist(err) {
        router.LoadHTMLGlob("web/templates/*")
        router.GET("/", HTTPAPIServerIndex)
        router.GET("/stream/player/:uuid", HTTPAPIServerStreamPlayer)
    }
    router.POST("/stream/receiver/:uuid", HTTPAPIServerStreamWebRTC)
    router.GET("/stream/codec/:uuid", HTTPAPIServerStreamCodec)
    router.POST("/stream", HTTPAPIServerStreamWebRTC2)

    router.StaticFS("/static", http.Dir("web/static"))
    err := router.Run(Config.Server.HTTPPort)
    if err != nil {
        log.Fatalln("Start HTTP Server error", err)
    }
}

// HTTPAPIServerIndex  index
func HTTPAPIServerIndex(c *gin.Context) {
    _, all := Config.list()
    if len(all) > 0 {
        c.Header("Cache-Control", "no-cache, max-age=0, must-revalidate, no-store")
        c.Header("Access-Control-Allow-Origin", "*")
        c.Redirect(http.StatusMovedPermanently, "stream/player/"+all[0])
    } else {
        c.HTML(http.StatusOK, "index.tmpl", gin.H{
            "port":    Config.Server.HTTPPort,
            "version": time.Now().String(),
        })
    }
}

// HTTPAPIServerStreamPlayer stream player
func HTTPAPIServerStreamPlayer(c *gin.Context) {
    _, all := Config.list()
    sort.Strings(all)
    c.HTML(http.StatusOK, "player.tmpl", gin.H{
        "port":     Config.Server.HTTPPort,
        "suuid":    c.Param("uuid"),
        "suuidMap": all,
        "version":  time.Now().String(),
    })
}

// HTTPAPIServerStreamCodec stream codec
func HTTPAPIServerStreamCodec(c *gin.Context) {
    if Config.ext(c.Param("uuid")) {
        Config.RunIFNotRun(c.Param("uuid"))
        codecs := Config.coGe(c.Param("uuid"))
        if codecs == nil {
            return
        }
        var tmpCodec []JCodec
        for _, codec := range codecs {
            if codec.Type() != av.H264 && codec.Type() != av.PCM_ALAW && codec.Type() != av.PCM_MULAW && codec.Type() != av.OPUS {
                log.Println("Codec Not Supported WebRTC ignore this track", codec.Type())
                continue
            }
            if codec.Type().IsVideo() {
                tmpCodec = append(tmpCodec, JCodec{Type: "video"})
            } else {
                tmpCodec = append(tmpCodec, JCodec{Type: "audio"})
            }
        }
        b, err := json.Marshal(tmpCodec)
        if err == nil {
            _, err = c.Writer.Write(b)
            if err != nil {
                log.Println("Write Codec Info error", err)
                return
            }
        }
    }
}

// HTTPAPIServerStreamWebRTC stream video over WebRTC
func HTTPAPIServerStreamWebRTC(c *gin.Context) {
    if !Config.ext(c.PostForm("suuid")) {
        log.Println("Stream Not Found")
        return
    }
    Config.RunIFNotRun(c.PostForm("suuid"))
    codecs := Config.coGe(c.PostForm("suuid"))
    if codecs == nil {
        log.Println("Stream Codec Not Found")
        return
    }
    var AudioOnly bool
    if len(codecs) == 1 && codecs[0].Type().IsAudio() {
        AudioOnly = true
    }
    muxerWebRTC := webrtc.NewMuxer(webrtc.Options{ICEServers: Config.GetICEServers(), ICEUsername: Config.GetICEUsername(), ICECredential: Config.GetICECredential(), PortMin: Config.GetWebRTCPortMin(), PortMax: Config.GetWebRTCPortMax()})
    answer, err := muxerWebRTC.WriteHeader(codecs, c.PostForm("data"))
    if err != nil {
        log.Println("WriteHeader", err)
        return
    }
    _, err = c.Writer.Write([]byte(answer))
    if err != nil {
        log.Println("Write", err)
        return
    }
    go func() {
        cid, ch := Config.clAd(c.PostForm("suuid"))
        defer Config.clDe(c.PostForm("suuid"), cid)
        defer muxerWebRTC.Close()
        var videoStart bool
        noVideo := time.NewTimer(10 * time.Second)
        for {
            select {
            case <-noVideo.C:
                log.Println("noVideo")
                return
            case pck := <-ch:
                if pck.IsKeyFrame || AudioOnly {
                    noVideo.Reset(10 * time.Second)
                    videoStart = true
                }
                if !videoStart && !AudioOnly {
                    continue
                }
                err = muxerWebRTC.WritePacket(pck)
                if err != nil {
                    log.Println("WritePacket", err)
                    return
                }
            }
        }
    }()
}

func CORSMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        c.Header("Access-Control-Allow-Origin", "*")
        c.Header("Access-Control-Allow-Credentials", "true")
        c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, x-access-token")
        c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
        c.Header("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")

        if c.Request.Method == "OPTIONS" {
            c.AbortWithStatus(http.StatusNoContent)
            return
        }

        c.Next()
    }
}

type Response struct {
    Tracks []string `json:"tracks"`
    Sdp64  string   `json:"sdp64"`
}

type ResponseError struct {
    Error string `json:"error"`
}

func HTTPAPIServerStreamWebRTC2(c *gin.Context) {
    url := c.PostForm("url")
    if _, ok := Config.Streams[url]; !ok {
        Config.Streams[url] = StreamST{
            URL:      url,
            OnDemand: true,
            Cl:       make(map[string]viewer),
        }
    }

    Config.RunIFNotRun(url)

    codecs := Config.coGe(url)
    if codecs == nil {
        log.Println("Stream Codec Not Found")
        c.JSON(500, ResponseError{Error: Config.LastError.Error()})
        return
    }

    muxerWebRTC := webrtc.NewMuxer(
        webrtc.Options{
            ICEServers: Config.GetICEServers(),
            PortMin:    Config.GetWebRTCPortMin(),
            PortMax:    Config.GetWebRTCPortMax(),
        },
    )

    sdp64 := c.PostForm("sdp64")
    answer, err := muxerWebRTC.WriteHeader(codecs, sdp64)
    if err != nil {
        log.Println("Muxer WriteHeader", err)
        c.JSON(500, ResponseError{Error: err.Error()})
        return
    }

    response := Response{
        Sdp64: answer,
    }

    for _, codec := range codecs {
        if codec.Type() != av.H264 &&
            codec.Type() != av.PCM_ALAW &&
            codec.Type() != av.PCM_MULAW &&
            codec.Type() != av.OPUS {
            log.Println("Codec Not Supported WebRTC ignore this track", codec.Type())
            continue
        }
        if codec.Type().IsVideo() {
            response.Tracks = append(response.Tracks, "video")
        } else {
            response.Tracks = append(response.Tracks, "audio")
        }
    }

    c.JSON(200, response)

    AudioOnly := len(codecs) == 1 && codecs[0].Type().IsAudio()

    go func() {
        cid, ch := Config.clAd(url)
        defer Config.clDe(url, cid)
        defer muxerWebRTC.Close()
        var videoStart bool
        noVideo := time.NewTimer(10 * time.Second)
        for {
            select {
            case <-noVideo.C:
                log.Println("noVideo")
                return
            case pck := <-ch:
                if pck.IsKeyFrame || AudioOnly {
                    noVideo.Reset(10 * time.Second)
                    videoStart = true
                }
                if !videoStart && !AudioOnly {
                    continue
                }
                err = muxerWebRTC.WritePacket(pck)
                if err != nil {
                    log.Println("WritePacket", err)
                    return
                }
            }
        }
    }()
}

go browser webrtc rtsp ip-camera
1个回答
0
投票

/:uuid
中删除
/stream/player/:uuid
并将
c.Param("uuid")
替换为
c.Query("camera")
in HTTPAPIServerStreamPlayer()
功能。

然后点击http://127.0.0.1:8088/stream/player?camera=Camera01希望它能工作

© www.soinside.com 2019 - 2024. All rights reserved.