I have a program that uses ffmpeg to stream an rtsp camera to hls format. When ffmpeg runs in the background, create goroutine
for each rtsp linkThe stream is added with the following code.
func streamprocess(data <-chan streamdata, ctx context.context) { for v := range data { ctx, _ := context.withcancel(ctx) go func() { if !getstreams(v.camera_id) { var stream streamstate stream.camera_id = v.camera_id stream.state = true go stream(v, ctx) wg.wait() } else { return } }() }
}
Run the streaming function of the ffmpeg command.
func Stream(meta StreamData, ctx context.Context) error { log.Println("Started Streaming") ffmpegCmd := exec.Command("ffmpeg", "-i", meta.rtsp, "-pix_fmt", "yuv420p", "-c:v", "libx264", "-preset", "ultrafast", "-b:v", "600k", "-c:a", "aac", "-b:a", "160k", "-f", "rtsp", fmt.Sprintf("rtsp://localhost:8554/%s", meta.camera_id)) output, _ := ffmpegCmd.CombinedOutput() log.Println(string(output)) for { select { case <-ctx.Done(): log.Println("killing process") ffmpegCmd.Process.Kill() return nil } }}
My goal is to stop every os.exec process (ffmpeg command) or at least close all goroutines under the ffmpeg command without shutting down the fiber server.
** Golang newbie needs help **
This is the working code:
func streamprocess(data <-chan streamdata, ctx context.context) { ctx, cancel := context.withcancel(ctx) defer cancel() for { select { case v, ok := <-data: if ok { go func() { if !getstreams(v.camera_id) { var stream streamstate stream.camera_id = v.camera_id stream.state = true go stream(v, ctx) } }() } else if !ok { cancel() return } case <-ctx.done(): log.println("closed ctx") cancel() } }
and start streaming:
func Stream(meta StreamData, ctx context.Context) error { log.Println("Started Streaming") err := exec.CommandContext(ctx, "ffmpeg", "-i", meta.rtsp, "-pix_fmt", "yuv420p", "-c:v", "libx264", "-preset", "ultrafast", "-b:v", "600k", "-c:a", "aac", "-b:a", "160k", "-f", "rtsp", fmt.Sprintf("rtsp://localhost:8554/%s", meta.camera_id)).Run() if err != nil { log.Println("error in streaming", err) return err } log.Println(string("waiting for closure")) for { select { case <-ctx.Done(): log.Println("killing process") return nil case <-time.After(2* time.second): log.Println("started default context") return nil } }
.
This worked for me, now I don't find a better way. If anyone has a better way please comment.
The above is the detailed content of Close the goroutine generated by the Fiber endpoint. For more information, please follow other related articles on the PHP Chinese website!