main.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package record
  2. import (
  3. _ "embed"
  4. "errors"
  5. "io"
  6. "sync"
  7. . "m7s.live/engine/v4"
  8. "m7s.live/engine/v4/codec"
  9. "m7s.live/engine/v4/config"
  10. "m7s.live/engine/v4/util"
  11. )
  12. type RecordConfig struct {
  13. config.Subscribe
  14. Flv Record `desc:"flv录制配置"`
  15. Mp4 Record `desc:"mp4录制配置"`
  16. Fmp4 Record `desc:"fmp4录制配置"`
  17. Hls Record `desc:"hls录制配置"`
  18. Raw Record `desc:"视频裸流录制配置"`
  19. RawAudio Record `desc:"音频裸流录制配置"`
  20. recordings sync.Map
  21. }
  22. //go:embed default.yaml
  23. var defaultYaml DefaultYaml
  24. var ErrRecordExist = errors.New("recorder exist")
  25. var RecordPluginConfig = &RecordConfig{
  26. Flv: Record{
  27. Path: "record/flv",
  28. Ext: ".flv",
  29. GetDurationFn: getFLVDuration,
  30. },
  31. Fmp4: Record{
  32. Path: "record/fmp4",
  33. Ext: ".mp4",
  34. },
  35. Mp4: Record{
  36. Path: "record/mp4",
  37. Ext: ".mp4",
  38. },
  39. Hls: Record{
  40. Path: "record/hls",
  41. Ext: ".m3u8",
  42. },
  43. Raw: Record{
  44. Path: "record/raw",
  45. Ext: ".", // 默认h264扩展名为.h264,h265扩展名为.h265
  46. },
  47. RawAudio: Record{
  48. Path: "record/raw",
  49. Ext: ".", // 默认aac扩展名为.aac,pcma扩展名为.pcma,pcmu扩展名为.pcmu
  50. },
  51. }
  52. var plugin = InstallPlugin(RecordPluginConfig, defaultYaml)
  53. func (conf *RecordConfig) OnEvent(event any) {
  54. switch v := event.(type) {
  55. case FirstConfig, config.Config:
  56. conf.Flv.Init()
  57. conf.Mp4.Init()
  58. conf.Fmp4.Init()
  59. conf.Hls.Init()
  60. conf.Raw.Init()
  61. conf.RawAudio.Init()
  62. case SEpublish:
  63. streamPath := v.Target.Path
  64. if conf.Flv.NeedRecord(streamPath) {
  65. go NewFLVRecorder().Start(streamPath)
  66. }
  67. if conf.Mp4.NeedRecord(streamPath) {
  68. go NewMP4Recorder().Start(streamPath)
  69. }
  70. if conf.Fmp4.NeedRecord(streamPath) {
  71. go NewFMP4Recorder().Start(streamPath)
  72. }
  73. if conf.Hls.NeedRecord(streamPath) {
  74. go NewHLSRecorder().Start(streamPath)
  75. }
  76. if conf.Raw.NeedRecord(streamPath) {
  77. go NewRawRecorder().Start(streamPath)
  78. }
  79. if conf.RawAudio.NeedRecord(streamPath) {
  80. go NewRawAudioRecorder().Start(streamPath)
  81. }
  82. }
  83. }
  84. func (conf *RecordConfig) getRecorderConfigByType(t string) (recorder *Record) {
  85. switch t {
  86. case "flv":
  87. recorder = &conf.Flv
  88. case "mp4":
  89. recorder = &conf.Mp4
  90. case "fmp4":
  91. recorder = &conf.Fmp4
  92. case "hls":
  93. recorder = &conf.Hls
  94. case "raw":
  95. recorder = &conf.Raw
  96. case "raw_audio":
  97. recorder = &conf.RawAudio
  98. }
  99. return
  100. }
  101. func getFLVDuration(file io.ReadSeeker) uint32 {
  102. _, err := file.Seek(-4, io.SeekEnd)
  103. if err == nil {
  104. var tagSize uint32
  105. if tagSize, err = util.ReadByteToUint32(file, true); err == nil {
  106. _, err = file.Seek(-int64(tagSize)-4, io.SeekEnd)
  107. if err == nil {
  108. _, timestamp, _, err := codec.ReadFLVTag(file)
  109. if err == nil {
  110. return timestamp
  111. }
  112. }
  113. }
  114. }
  115. return 0
  116. }