diff --git a/docs/ghostream.example.yml b/docs/ghostream.example.yml index 0a0ce36..c516dce 100644 --- a/docs/ghostream.example.yml +++ b/docs/ghostream.example.yml @@ -38,13 +38,17 @@ auth: ## Stream forwarding ## # Forward an incoming stream to other servers # The URL can be anything FFMpeg can accept as an stream output +# If a file is specified, the name may contains %Y, %m, %d, %H, %M or %S +# that will be replaced by the current date information. forwarding: # By default nothing is forwarded. # # This example forwards a stream named "demo" to Twitch and YouTube, + # and save the record in a timestamped-file, #demo: # - rtmp://live-cdg.twitch.tv/app/STREAM_KEY # - rtmp://a.rtmp.youtube.com/live2/STREAM_KEY + # - /home/ghostream/lives/%name/live-%Y-%m-%d-%H-%M-%S.flv ## Prometheus monitoring ## # Expose a monitoring endpoint for Prometheus diff --git a/stream/forwarding/forwarding.go b/stream/forwarding/forwarding.go index f4fd157..52f6299 100644 --- a/stream/forwarding/forwarding.go +++ b/stream/forwarding/forwarding.go @@ -3,8 +3,11 @@ package forwarding import ( "bufio" + "fmt" "log" "os/exec" + "strings" + "time" "gitlab.crans.org/nounous/ghostream/messaging" ) @@ -49,20 +52,30 @@ func Serve(streams *messaging.Streams, cfg Options) { // Start forwarding log.Printf("Starting forwarding for '%s' quality '%s'", name, qualityName) - go forward(quality, streamCfg) + go forward(name, quality, streamCfg) } } // Start a FFMPEG instance and redirect stream output to forwarded streams -func forward(q *messaging.Quality, fwdCfg []string) { +func forward(streamName string, q *messaging.Quality, fwdCfg []string) { output := make(chan []byte, 1024) q.Register(output) // Launch FFMPEG instance params := []string{"-hide_banner", "-loglevel", "error", "-re", "-i", "pipe:0"} for _, url := range fwdCfg { + // If the url should be date-formatted, replace special characters with the current time information + now := time.Now() + formattedURL := strings.ReplaceAll(url, "%Y", fmt.Sprintf("%04d", now.Year())) + formattedURL = strings.ReplaceAll(formattedURL, "%m", fmt.Sprintf("%02d", now.Month())) + formattedURL = strings.ReplaceAll(formattedURL, "%d", fmt.Sprintf("%02d", now.Day())) + formattedURL = strings.ReplaceAll(formattedURL, "%H", fmt.Sprintf("%02d", now.Hour())) + formattedURL = strings.ReplaceAll(formattedURL, "%M", fmt.Sprintf("%02d", now.Minute())) + formattedURL = strings.ReplaceAll(formattedURL, "%S", fmt.Sprintf("%02d", now.Second())) + formattedURL = strings.ReplaceAll(formattedURL, "%name", streamName) + params = append(params, "-f", "flv", "-preset", "ultrafast", "-tune", "zerolatency", - "-c", "copy", url) + "-c", "copy", formattedURL) } ffmpeg := exec.Command("ffmpeg", params...) @@ -95,7 +108,7 @@ func forward(q *messaging.Quality, fwdCfg []string) { go func() { scanner := bufio.NewScanner(errOutput) for scanner.Scan() { - log.Printf("[FORWARDING FFMPEG] %s", scanner.Text()) + log.Printf("[FORWARDING FFMPEG %s] %s", streamName, scanner.Text()) } }()