diff --git a/writer/cmd/main.go b/writer/cmd/main.go index c79ebd4..ea6632d 100644 --- a/writer/cmd/main.go +++ b/writer/cmd/main.go @@ -2,13 +2,12 @@ package main import ( "flag" + "git.insit.tech/psa/rtsp_reader-writer/writer/internal/config" + "git.insit.tech/psa/rtsp_reader-writer/writer/internal/ingest/rtsp" "log" - "writer/internal/config" - "writer/internal/procRTSP" ) func main() { - directory := flag.String("dir", "/home/psa/GoRepository", "directory") flag.Parse() @@ -23,9 +22,9 @@ func main() { log.Printf("start recording on camera: %s\n", link) go func() { - err = procRTSP.ProcRTSP(*directory, 1, link) + err = rtsp.RTSP(*directory, 60, link) if err != nil { - panic(err) + log.Printf("procRTSP function error for camera %s: %s", link, err.Error()) } }() } diff --git a/writer/cmd/reader-writer b/writer/cmd/reader-writer deleted file mode 100755 index 40db4c6..0000000 Binary files a/writer/cmd/reader-writer and /dev/null differ diff --git a/writer/go.mod b/writer/go.mod index f0c63a5..06004cb 100644 --- a/writer/go.mod +++ b/writer/go.mod @@ -1,4 +1,4 @@ -module writer +module git.insit.tech/psa/rtsp_reader-writer go 1.23.6 diff --git a/writer/internal/auth/auth.go b/writer/internal/auth/auth.go new file mode 100644 index 0000000..8832b06 --- /dev/null +++ b/writer/internal/auth/auth.go @@ -0,0 +1 @@ +package auth diff --git a/writer/internal/config/parser.go b/writer/internal/config/parser.go new file mode 100644 index 0000000..69a3b94 --- /dev/null +++ b/writer/internal/config/parser.go @@ -0,0 +1,23 @@ +package config + +import ( + "gopkg.in/yaml.v3" + "os" +) + +// ParseCamerasYAML parses camera links from YAML file into struct Cameras. +func ParseCamerasYAML(dir string) (map[string]string, error) { + var CamerasYAML map[string]string + + data, err := os.ReadFile(dir + "/rtsp_reader-writer/writer/internal/config/source.yaml") + if err != nil { + return CamerasYAML, err + } + + err = yaml.Unmarshal(data, &CamerasYAML) + if err != nil { + return CamerasYAML, err + } + + return CamerasYAML, nil +} diff --git a/writer/internal/config/source.yaml b/writer/internal/config/source.yaml index dc46b30..c46964e 100644 --- a/writer/internal/config/source.yaml +++ b/writer/internal/config/source.yaml @@ -32,5 +32,5 @@ #camera_32: rtsp://intercom-video-1.insit.ru/dp-woxvkbynctgfbuztsalttgburbpvjf #camera_33: rtsp://intercom-video-1.insit.ru/dp-fdzbasqehtptsuhxnjeqqnlrixfahcgvlcr #camera_34: rtsp://intercom-video-1.insit.ru/dp-exyeqscyamrbkwkjifagouyprtsdoe -camera_35: rtsp://intercom-video-2.insit.ru/dp-sutyagina3a-iv-uujtwbsjekv +#camera_35: rtsp://intercom-video-2.insit.ru/dp-sutyagina3a-iv-uujtwbsjekv camera_36: rtsp://intercom-video-1.insit.ru/dp-wyshispseamhqmnhkqwkbarshnrvni \ No newline at end of file diff --git a/writer/internal/media/g711.go b/writer/internal/ingest/rtsp/g711.go similarity index 98% rename from writer/internal/media/g711.go rename to writer/internal/ingest/rtsp/g711.go index e5472a8..c9d4454 100644 --- a/writer/internal/media/g711.go +++ b/writer/internal/ingest/rtsp/g711.go @@ -1,4 +1,4 @@ -package media +package rtsp import ( "errors" diff --git a/writer/internal/media/h264.go b/writer/internal/ingest/rtsp/h264.go similarity index 98% rename from writer/internal/media/h264.go rename to writer/internal/ingest/rtsp/h264.go index bf9a6e7..885fcad 100644 --- a/writer/internal/media/h264.go +++ b/writer/internal/ingest/rtsp/h264.go @@ -1,4 +1,4 @@ -package media +package rtsp import ( "errors" diff --git a/writer/pkg/converter/pcm_to_aac.go b/writer/internal/ingest/rtsp/pcm_to_aac.go similarity index 97% rename from writer/pkg/converter/pcm_to_aac.go rename to writer/internal/ingest/rtsp/pcm_to_aac.go index 15b195e..2b1ace7 100644 --- a/writer/pkg/converter/pcm_to_aac.go +++ b/writer/internal/ingest/rtsp/pcm_to_aac.go @@ -1,4 +1,4 @@ -package converter +package rtsp import ( "bytes" diff --git a/writer/internal/procRTSP/client.go b/writer/internal/ingest/rtsp/rtsp.go similarity index 79% rename from writer/internal/procRTSP/client.go rename to writer/internal/ingest/rtsp/rtsp.go index 73610e8..c27ef3b 100644 --- a/writer/internal/procRTSP/client.go +++ b/writer/internal/ingest/rtsp/rtsp.go @@ -1,8 +1,10 @@ -package procRTSP +package rtsp import ( "errors" "fmt" + "git.insit.tech/psa/rtsp_reader-writer/writer/internal/storage" + "git.insit.tech/psa/rtsp_reader-writer/writer/pkg/converter" "git.insit.tech/sas/rtsp_proxy/protos/gens" "github.com/bluenviron/gortsplib/v4" "github.com/bluenviron/gortsplib/v4/pkg/base" @@ -14,14 +16,11 @@ import ( "os" "strings" "time" - "writer/internal/config" - "writer/internal/media" - "writer/pkg/converter" ) // StartWriter starts the program. func StartWriter(dir string, period int, URI string) error { - err := ProcRTSP(dir, period, URI) + err := RTSP(dir, period, URI) if err != nil { // Temporary solution for inner cameras. @@ -36,19 +35,14 @@ func StartWriter(dir string, period int, URI string) error { return nil } -// ProcRTSP process RTSP protocol and writes H264 and PCM flows into TS container. -func ProcRTSP(dir string, period int, link string) error { +// RTSP processes RTSP protocol. +func RTSP(dir string, period int, link string) error { resolutions := []string{"1280x720"} - // Return the last part of the URI after "/". - cuttedURI := config.CutURI(link) + // Create file name structure and directory for files. + cuttedURI := storage.CutURI(link) + fn := storage.CreateFileName(dir, resolutions, cuttedURI, period) - // Create FileName structure - fn := config.CreateFileName(dir, resolutions, cuttedURI, period) - - //////////////////////////////////////////////////////////////////////////////////////// - - // Create directory for files according to resolutions. err := os.MkdirAll(fmt.Sprintf("%s", fn.Path), 0755) if err != nil { return fmt.Errorf("mkdirall error: %w", err) @@ -57,48 +51,42 @@ func ProcRTSP(dir string, period int, link string) error { // Create M3U8 playlist. go gens.MediaPlaylistGenerator(dir+"/data/"+cuttedURI, "", fn.Duration, resolutions) - //////////////////////////////////////////////////////////////////////////////////////// - - // Initialise client. + // Connect to the server. c := gortsplib.Client{ UserAgent: "PSA", } - // Parse URL. u, err := base.ParseURL(link) if err != nil { return fmt.Errorf("parse URL error: %w", err) } - // Connect to the server. err = c.Start(u.Scheme, u.Host) if err != nil { return fmt.Errorf("connect to the server error: %w", err) } defer c.Close() - // Find available medias. - desc, _, err := c.Describe(u) + desc, r, err := c.Describe(u) if err != nil || desc == nil { log.Printf("medias not found for camera [%s]: %v", link, err) return nil } - //////////////////////////////////////////////////////////////////////////////////////// + /////////////// - // Find the H264 media and format. + // Find formats. //var run bool - h264Format, h264Media, err := media.CheckH264Format(desc) + h264Format, h264Media, err := CheckH264Format(desc) if err != nil { log.Printf("H264 format not found: %v", err) //run = true } - //// Find the G711 media and format. - //g711Format, g711Media, err := media.CheckG711Format(desc) + //g711Format, g711Media, err := CheckG711Format(desc) //if err != nil { // log.Printf("G711 format not found: %v", err) - // run = true + // // run = true //} // Initialising variable for AAC. @@ -120,7 +108,7 @@ func ProcRTSP(dir string, period int, link string) error { //////////////////////////////////////////////////////////////////////////////////////// // Wait for the next period. - config.Waiter(period) + storage.WaitPeriod(period) log.Println("Start recording") //////////////////////////////////////////////////////////////////////////////////////// @@ -153,7 +141,7 @@ func ProcRTSP(dir string, period int, link string) error { switch forma.(type) { case *format.H264: // Process H264 flow and return PTS and AU. - pts, au, err := media.ProcH264(&c, h264Media, h264RTPDec, pkt) + pts, au, err := ProcH264(&c, h264Media, h264RTPDec, pkt) if err != nil { //log.Printf("%s: process H264 error: %s\n", cuttedURI, err) } @@ -197,7 +185,7 @@ func ProcRTSP(dir string, period int, link string) error { } // Create ticker for rotation files. - ticker := time.NewTicker(time.Duration(period) * time.Minute) + ticker := time.NewTicker(time.Duration(period) * time.Second) defer ticker.Stop() // Rotate files. @@ -234,12 +222,12 @@ func changeDomain(directory string, period int, URI string, err error) error { err2 := errors.New("404 (Not found)") if errors.As(err, &err2) { if strings.Contains(URI, "video-1") { - err = ProcRTSP(directory, period, strings.Replace(URI, "video-1", "video-2", 1)) + err = RTSP(directory, period, strings.Replace(URI, "video-1", "video-2", 1)) if err != nil { return err } } else { - err = ProcRTSP(directory, period, strings.Replace(URI, "video-2", "video-1", 1)) + err = RTSP(directory, period, strings.Replace(URI, "video-2", "video-1", 1)) if err != nil { return err } diff --git a/writer/internal/storage/file.go b/writer/internal/storage/file.go new file mode 100644 index 0000000..7b7eb39 --- /dev/null +++ b/writer/internal/storage/file.go @@ -0,0 +1,19 @@ +package storage + +import "time" + +type Segment struct { + Start time.Time + Duration time.Duration + + H264 byte + G711 byte + + SPS []byte + PPS []byte +} + +type StreamRecord struct { + ID string + Segments []Segment +} diff --git a/writer/internal/storage/segmenter.go b/writer/internal/storage/segmenter.go new file mode 100644 index 0000000..82be054 --- /dev/null +++ b/writer/internal/storage/segmenter.go @@ -0,0 +1 @@ +package storage diff --git a/writer/pkg/parser/parser.go b/writer/pkg/parser/parser.go deleted file mode 100644 index 0bfe2c2..0000000 --- a/writer/pkg/parser/parser.go +++ /dev/null @@ -1 +0,0 @@ -package parser