fix: fmp4 record error

This commit is contained in:
langhuihui
2023-08-13 14:54:07 +08:00
parent 30bb6ed506
commit 8f33e9b802
6 changed files with 43 additions and 33 deletions

View File

@@ -16,7 +16,7 @@ import (
- 配置中的path 表示要保存的文件的根路径,可以使用相对路径或者绝对路径
- filter 代表要过滤的StreamPath正则表达式如果不匹配则表示不录制。为空代表不进行过滤
- fragment表示分片大小0代表不分片
- fragment表示分片大小20s代表20秒1m代表1分钟可以组合0代表不分片
```yaml
record:
@@ -51,7 +51,7 @@ record:
- `/record/api/list/recording` 罗列所有正在录制中的流的信息
- `/record/api/list?type=[flv|mp4|hls|raw]` 罗列所有录制的flv|mp4|m3u8|raw文件
- `/record/api/start?type=flv&streamPath=live/rtc&fileName=xxx&fragment=10s` 开始录制某个流,返回一个字符串用于停止录制用的id(fileName是可选的且只用于非切片情况,fragment用于覆盖配置中的切片时间是可选的)
- `/record/api/start?type=flv&streamPath=live/rtc&fileName=xxx&fragment=10s` 开始录制某个流,返回一个字符串用于停止录制用的id(fileName是可选的且只用于非切片情况,fragment用于覆盖配置中的切片时间是可选的如果fileName和fragment都存在则忽略fileName)
- `/record/api/stop?id=xxx` 停止录制某个流
## 点播功能

16
fmp4.go
View File

@@ -15,7 +15,7 @@ type mediaContext struct {
func (m *mediaContext) push(recoder *FMP4Recorder, dt uint32, dur uint32, data []byte, flags uint32) {
if m.fragment != nil && dt-m.ts > 1000 {
m.fragment.Encode(recoder)
m.fragment.Encode(recoder.File)
m.fragment = nil
}
if m.fragment == nil {
@@ -36,7 +36,7 @@ func (m *mediaContext) push(recoder *FMP4Recorder, dt uint32, dur uint32, data [
type FMP4Recorder struct {
Recorder
*mp4.InitSegment `json:"-" yaml:"-"`
initSegment *mp4.InitSegment `json:"-" yaml:"-"`
video mediaContext
audio mediaContext
seqNumber uint32
@@ -73,10 +73,10 @@ func (r *FMP4Recorder) OnEvent(event any) {
r.Recorder.OnEvent(event)
switch v := event.(type) {
case FileWr:
r.InitSegment = mp4.CreateEmptyInit()
r.Moov.Mvhd.NextTrackID = 1
r.initSegment = mp4.CreateEmptyInit()
r.initSegment.Moov.Mvhd.NextTrackID = 1
if r.VideoReader != nil {
moov := r.Moov
moov := r.initSegment.Moov
trackID := moov.Mvhd.NextTrackID
moov.Mvhd.NextTrackID++
newTrak := mp4.CreateEmptyTrak(trackID, 1000, "video", "chi")
@@ -97,7 +97,7 @@ func (r *FMP4Recorder) OnEvent(event any) {
}
}
if r.AudioReader != nil {
moov := r.Moov
moov := r.initSegment.Moov
trackID := moov.Mvhd.NextTrackID
moov.Mvhd.NextTrackID++
newTrak := mp4.CreateEmptyTrak(trackID, 1000, "audio", "chi")
@@ -128,8 +128,8 @@ func (r *FMP4Recorder) OnEvent(event any) {
stsd.AddChild(pcmu)
}
}
r.ftyp.Encode(r)
r.Moov.Encode(r)
r.ftyp.Encode(v)
r.initSegment.Moov.Encode(v)
r.seqNumber = 0
case AudioFrame:
if r.audio.trackId != 0 {

7
hls.go
View File

@@ -32,7 +32,12 @@ func (h *HLSRecorder) Start(streamPath string) error {
h.ID = streamPath + "/hls"
return h.start(h, streamPath, SUBTYPE_RAW)
}
func (r *HLSRecorder) Close() (err error) {
if r.File != nil {
err = r.File.Close()
}
return
}
func (h *HLSRecorder) OnEvent(event any) {
var err error
defer func() {

7
raw.go
View File

@@ -30,7 +30,12 @@ func (r *RawRecorder) Start(streamPath string) error {
}
return r.start(r, streamPath, SUBTYPE_RAW)
}
func (r *RawRecorder) Close() (err error) {
if r.File != nil {
err = r.File.Close()
}
return
}
func (r *RawRecorder) OnEvent(event any) {
switch v := event.(type) {
case FileWr:

View File

@@ -2,10 +2,10 @@ package record
import (
"encoding/json"
"fmt"
"net/http"
"time"
"go.uber.org/zap"
. "m7s.live/engine/v4"
"m7s.live/engine/v4/util"
)
@@ -74,34 +74,37 @@ func (conf *RecordConfig) API_start(w http.ResponseWriter, r *http.Request) {
}
recorder := irecorder.GetRecorder()
if fragment != "" {
recorder.Fragment, err = time.ParseDuration(fragment)
f, err := time.ParseDuration(fragment)
if err != nil {
recorder.Fragment = f
}
}
recorder.FileName = fileName
recorder.append = query.Get("append") != ""
err = irecorder.Start(streamPath)
id = recorder.ID
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
util.ReturnError(util.APIErrorInternal, err.Error(), w, r)
return
}
fmt.Fprintf(w, id)
util.ReturnError(util.APIErrorNone, id, w, r)
}
func (conf *RecordConfig) API_list_recording(w http.ResponseWriter, r *http.Request) {
util.ReturnJson(func() (recordings []any) {
util.ReturnFetchValue(func() (recordings []any) {
conf.recordings.Range(func(key, value any) bool {
recordings = append(recordings, value)
return true
})
return
}, time.Second, w, r)
}, w, r)
}
func (conf *RecordConfig) API_stop(w http.ResponseWriter, r *http.Request) {
if recorder, ok := conf.recordings.Load(r.URL.Query().Get("id")); ok {
recorder.(ISubscriber).Stop()
w.Write([]byte("ok"))
recorder.(ISubscriber).Stop(zap.String("reason", "api"))
util.ReturnOK(w, r)
return
}
http.Error(w, "no such recorder", http.StatusBadRequest)
util.ReturnError(util.APIErrorNotFound, "no such recorder", w, r)
}

View File

@@ -35,13 +35,6 @@ func (r *Recorder) CreateFile() (FileWr, error) {
return r.createFile()
}
func (r *Recorder) Close() error {
if r.File != nil {
return r.File.Close()
}
return nil
}
func (r *Recorder) createFile() (f FileWr, err error) {
filePath := r.getFileName(r.Stream.Path) + r.Ext
f, err = r.CreateFileFn(filePath, r.append)
@@ -77,7 +70,6 @@ func (r *Recorder) start(re IRecorder, streamPath string, subType byte) (err err
r.PlayBlock(subType)
RecordPluginConfig.recordings.Delete(r.ID)
delete(r.recording, streamPath)
re.Close()
}()
}
return
@@ -96,6 +88,11 @@ func (r *Recorder) cut(absTime uint32) {
}
}
// func (r *Recorder) Stop(reason ...zap.Field) {
// r.Close()
// r.Subscriber.Stop(reason...)
// }
func (r *Recorder) OnEvent(event any) {
switch v := event.(type) {
case IRecorder: