diff --git a/device/webcam/webcam.go b/device/webcam/webcam.go index 0ac08751..fbb3a91b 100644 --- a/device/webcam/webcam.go +++ b/device/webcam/webcam.go @@ -28,6 +28,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "os/exec" "strings" @@ -61,15 +62,19 @@ var ( // Webcam is an implementation of the AVDevice interface for a Webcam. Webcam // uses an ffmpeg process to pipe the video data from the webcam. type Webcam struct { - out io.ReadCloser - log config.Logger - cfg config.Config - cmd *exec.Cmd + out io.ReadCloser + log config.Logger + cfg config.Config + cmd *exec.Cmd + done chan struct{} } // New returns a new Webcam. func New(l config.Logger) *Webcam { - return &Webcam{log: l} + return &Webcam{ + log: l, + done: make(chan struct{}), + } } // Name returns the name of the device. @@ -151,6 +156,32 @@ func (w *Webcam) Start() error { return fmt.Errorf("failed to create pipe: %w", err) } + stderr, err := w.cmd.StderrPipe() + if err != nil { + return fmt.Errorf("could not pipe command error: %w", err) + } + + go func() { + for { + select { + case <-w.done: + w.cfg.Logger.Log(logger.Info, "webcam.Stop() called, finished checking stderr") + return + default: + buf, err := ioutil.ReadAll(stderr) + if err != nil { + w.cfg.Logger.Log(logger.Error, "could not read stderr", "error", err) + return + } + + if len(buf) != 0 { + w.cfg.Logger.Log(logger.Error, "error from webcam stderr", "error", string(buf)) + return + } + } + } + }() + err = w.cmd.Start() if err != nil { return fmt.Errorf("failed to start ffmpeg: %w", err) @@ -161,6 +192,7 @@ func (w *Webcam) Start() error { // Stop will kill the ffmpeg process and close the output pipe. func (w *Webcam) Stop() error { + close(w.done) if w.cmd == nil || w.cmd.Process == nil { return errors.New("ffmpeg process was never started") }