增加视频裸流录制功能

This commit is contained in:
dexter
2022-06-12 12:37:38 +08:00
parent f838166f51
commit 8f9b236010
6 changed files with 88 additions and 9 deletions

View File

@@ -1,6 +1,6 @@
# RECORD插件 # RECORD插件
对流进行录制的功能插件提供Flv、fmp4、hls格式的录制功能。 对流进行录制的功能插件提供Flv、fmp4、hls、裸流格式的录制功能。
## 插件地址 ## 插件地址
@@ -43,6 +43,12 @@ record:
autorecord: false autorecord: false
filter: "" filter: ""
fragment: 0 fragment: 0
raw:
ext: .
path: ./raw
autorecord: false
filter: ""
fragment: 0
``` ```
## API ## API
@@ -55,7 +61,7 @@ record:
## 点播功能 ## 点播功能
访问格式: 访问格式:
[http/https]://[host]:[port]/record/[streamPath].[flv/mp4] [http/https]://[host]:[port]/record/[streamPath].[flv|mp4|m3u8|h264|h265]
例如: 例如:
- `http://localhost:8080/record/live/test.flv` 将会读取对应的flv文件 - `http://localhost:8080/record/live/test.flv` 将会读取对应的flv文件

8
go.mod
View File

@@ -4,7 +4,9 @@ go 1.18
require ( require (
github.com/edgeware/mp4ff v0.27.0 github.com/edgeware/mp4ff v0.27.0
m7s.live/engine/v4 v4.0.0-beta1 go.uber.org/zap v1.21.0
m7s.live/engine/v4 v4.2.0
m7s.live/plugin/hls/v4 v4.0.0-20220526032106-b2c401b1cbb5
) )
require ( require (
@@ -18,16 +20,16 @@ require (
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/pion/randutil v0.1.0 // indirect github.com/pion/randutil v0.1.0 // indirect
github.com/pion/rtp/v2 v2.0.0-20220302185659-b3d10fc096b0 // indirect github.com/pion/rtp v1.6.2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/q191201771/naza v0.19.1 // indirect github.com/q191201771/naza v0.19.1 // indirect
github.com/quangngotan95/go-m3u8 v0.1.0 // indirect
github.com/shirou/gopsutil/v3 v3.22.1 // indirect github.com/shirou/gopsutil/v3 v3.22.1 // indirect
github.com/tklauser/go-sysconf v0.3.9 // indirect github.com/tklauser/go-sysconf v0.3.9 // indirect
github.com/tklauser/numcpus v0.3.0 // indirect github.com/tklauser/numcpus v0.3.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.uber.org/atomic v1.7.0 // indirect go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.21.0 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 // indirect golang.org/x/sys v0.0.0-20220111092808-5a964db01320 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect

13
go.sum
View File

@@ -9,6 +9,7 @@ github.com/cnotch/queue v0.0.0-20200326024423-6e88bdbf2ad4/go.mod h1:zOssjAlNusO
github.com/cnotch/queue v0.0.0-20201224060551-4191569ce8f6/go.mod h1:zOssjAlNusOxvtaqT+EMA+Iyi8rrtKr4/XfzN1Fgoeg= github.com/cnotch/queue v0.0.0-20201224060551-4191569ce8f6/go.mod h1:zOssjAlNusOxvtaqT+EMA+Iyi8rrtKr4/XfzN1Fgoeg=
github.com/cnotch/scheduler v0.0.0-20200522024700-1d2da93eefc5/go.mod h1:F4GE3SZkJZ8an1Y0ZCqvSM3jeozNuKzoC67erG1PhIo= github.com/cnotch/scheduler v0.0.0-20200522024700-1d2da93eefc5/go.mod h1:F4GE3SZkJZ8an1Y0ZCqvSM3jeozNuKzoC67erG1PhIo=
github.com/cnotch/xlog v0.0.0-20201208005456-cfda439cd3a0/go.mod h1:RW9oHsR79ffl3sR3yMGgxYupMn2btzdtJUwoxFPUE5E= github.com/cnotch/xlog v0.0.0-20201208005456-cfda439cd3a0/go.mod h1:RW9oHsR79ffl3sR3yMGgxYupMn2btzdtJUwoxFPUE5E=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -42,6 +43,7 @@ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
@@ -51,9 +53,8 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
github.com/pion/rtp v1.6.2 h1:iGBerLX6JiDjB9NXuaPzHyxHFG9JsIEdgwTC0lp5n/U=
github.com/pion/rtp v1.6.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= github.com/pion/rtp v1.6.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
github.com/pion/rtp/v2 v2.0.0-20220302185659-b3d10fc096b0 h1:zyOGxHutZ6IhksQSMtwf3OFXB29W5R18yFQWOQJYWjU=
github.com/pion/rtp/v2 v2.0.0-20220302185659-b3d10fc096b0/go.mod h1:Vj+rrFbJCT3yxqE/VSwaOo9DQ2pMKGPxuE7hplGOlOs=
github.com/pixelbender/go-sdp v1.1.0/go.mod h1:6IBlz9+BrUHoFTea7gcp4S54khtOhjCW/nVDLhmZBAs= github.com/pixelbender/go-sdp v1.1.0/go.mod h1:6IBlz9+BrUHoFTea7gcp4S54khtOhjCW/nVDLhmZBAs=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -63,6 +64,8 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/q191201771/naza v0.19.1 h1:4KLcxT2CHztO+7miPRtBG3FFgadSQYQw1gPPPKN7rnY= github.com/q191201771/naza v0.19.1 h1:4KLcxT2CHztO+7miPRtBG3FFgadSQYQw1gPPPKN7rnY=
github.com/q191201771/naza v0.19.1/go.mod h1:5LeGupZZFtYP1g/S203n9vXoUNVdlRnPIfM6rExjqt0= github.com/q191201771/naza v0.19.1/go.mod h1:5LeGupZZFtYP1g/S203n9vXoUNVdlRnPIfM6rExjqt0=
github.com/quangngotan95/go-m3u8 v0.1.0 h1:8oseBjJn5IKHQKdRZwSNskkua3NLrRtlvXXtoVgBzMk=
github.com/quangngotan95/go-m3u8 v0.1.0/go.mod h1:smzfWHlYpBATVNu1GapKLYiCtEo5JxridIgvvudZ+Wc=
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
github.com/shirou/gopsutil/v3 v3.22.1 h1:33y31Q8J32+KstqPfscvFwBlNJ6xLaBy4xqBXzlYV5w= github.com/shirou/gopsutil/v3 v3.22.1 h1:33y31Q8J32+KstqPfscvFwBlNJ6xLaBy4xqBXzlYV5w=
github.com/shirou/gopsutil/v3 v3.22.1/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY= github.com/shirou/gopsutil/v3 v3.22.1/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY=
@@ -141,5 +144,7 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
m7s.live/engine/v4 v4.0.0-beta1 h1:a7uVCoT2zxJGHSLjLWTmzgY/ptyCEjl3o4IAE1rBXy0= m7s.live/engine/v4 v4.2.0 h1:8t19PmVHoiLxvfogs6pgh/MeEeYm4EBca8U1wmLFqR8=
m7s.live/engine/v4 v4.0.0-beta1/go.mod h1:Ez870pCfemZCUQQYP88jIHsgbRCb9ELjtCau14YTl7E= m7s.live/engine/v4 v4.2.0/go.mod h1:rliHP5yJnSyr40ha6q8OhUResRn8fo26TxmmBbR2X4M=
m7s.live/plugin/hls/v4 v4.0.0-20220526032106-b2c401b1cbb5 h1:URhjSOLn5QQgVsuCpObtHljNJ5dFPDgD8FzLf5pijyg=
m7s.live/plugin/hls/v4 v4.0.0-20220526032106-b2c401b1cbb5/go.mod h1:Qn4dDz5xlyBJwO+eZ3w8CUQ8Hl6KN1nmv0a3IsOjJvw=

18
main.go
View File

@@ -17,6 +17,7 @@ type RecordConfig struct {
Flv Record Flv Record
Mp4 Record Mp4 Record
Hls Record Hls Record
Raw Record
recordings sync.Map recordings sync.Map
} }
@@ -34,6 +35,10 @@ var recordConfig = &RecordConfig{
Path: "./hls", Path: "./hls",
Ext: ".m3u8", Ext: ".m3u8",
}, },
Raw :Record{
Path: "./raw",
Ext: ".", // 默认h264扩展名为.h264,h265扩展名为.h265
},
} }
var plugin = InstallPlugin(recordConfig) var plugin = InstallPlugin(recordConfig)
@@ -44,6 +49,7 @@ func (conf *RecordConfig) OnEvent(event any) {
conf.Flv.Init() conf.Flv.Init()
conf.Mp4.Init() conf.Mp4.Init()
conf.Hls.Init() conf.Hls.Init()
conf.Raw.Init()
case SEpublish: case SEpublish:
if conf.Flv.NeedRecord(v.Stream.Path) { if conf.Flv.NeedRecord(v.Stream.Path) {
var flv FLVRecorder var flv FLVRecorder
@@ -60,6 +66,11 @@ func (conf *RecordConfig) OnEvent(event any) {
hls.Record = &conf.Hls hls.Record = &conf.Hls
plugin.Subscribe(v.Stream.Path, &hls) plugin.Subscribe(v.Stream.Path, &hls)
} }
if conf.Raw.NeedRecord(v.Stream.Path) {
var raw RawRecorder
raw.Record = &conf.Raw
plugin.Subscribe(v.Stream.Path, &raw)
}
} }
} }
@@ -74,6 +85,8 @@ func (conf *RecordConfig) API_list(w http.ResponseWriter, r *http.Request) {
recorder = &conf.Mp4 recorder = &conf.Mp4
case "hls": case "hls":
recorder = &conf.Hls recorder = &conf.Hls
case "raw":
recorder = &conf.Raw
} }
if recorder != nil { if recorder != nil {
@@ -119,6 +132,11 @@ func (conf *RecordConfig) API_start(w http.ResponseWriter, r *http.Request) {
recorder := &HLSRecorder{} recorder := &HLSRecorder{}
recorder.Record = &conf.Hls recorder.Record = &conf.Hls
sub = recorder sub = recorder
case "raw":
recorder := &RawRecorder{}
recorder.Record = &conf.Raw
recorder.append = query.Get("append") != "" && util.Exist(filePath)
sub = recorder
default: default:
http.Error(w, "type not supported", http.StatusBadRequest) http.Error(w, "type not supported", http.StatusBadRequest)
} }

46
raw.go Normal file
View File

@@ -0,0 +1,46 @@
package record
import (
"path/filepath"
"strconv"
"time"
. "m7s.live/engine/v4"
"m7s.live/engine/v4/codec"
"m7s.live/engine/v4/track"
)
type RawRecorder struct {
Recorder
}
func (r *RawRecorder) OnEvent(event any) {
r.Recorder.OnEvent(event)
switch v := event.(type) {
case *track.Video:
if r.Ext == "." {
if v.CodecID == codec.CodecID_H264 {
r.Ext = ".h264"
} else {
r.Ext = ".h265"
}
}
case VideoDeConf:
annexB := v.GetAnnexB()
annexB.WriteTo(r)
case *VideoFrame:
if r.Fragment != 0 && r.newFile {
r.newFile = false
r.Close()
if file, err := r.CreateFileFn(filepath.Join(r.Stream.Path, strconv.FormatInt(time.Now().Unix(), 10)+r.Ext), false); err == nil {
r.SetIO(file)
if r.Video.Track != nil {
annexB := VideoDeConf(r.Video.Track.DecoderConfiguration).GetAnnexB()
annexB.WriteTo(r)
}
}
}
annexB := v.GetAnnexB()
annexB.WriteTo(r)
}
}

2
vod.go
View File

@@ -25,5 +25,7 @@ func (conf *RecordConfig) ServeHTTP(w http.ResponseWriter, r *http.Request) {
conf.Mp4.ServeHTTP(w, r) conf.Mp4.ServeHTTP(w, r)
case ".m3u8", ".ts": case ".m3u8", ".ts":
conf.Hls.ServeHTTP(w, r) conf.Hls.ServeHTTP(w, r)
case ".h264", ".h265":
conf.Raw.ServeHTTP(w, r)
} }
} }