Video Streaming Notes
===

Install dependencies and create `/dev/video1`:

```
apt-get install -y motion v4l2loopback-utils v4l2loopback-source
modprobe v4l2loopback
```

Update `motion.conf`:

```
$ mkdir -p $HOME/log
$ cat <<EOF > $HOME/.motion/motion.conf
stream_port 8080
stream_quality 98
stream_maxrate 25
framerate 10
stream_localhost off
output_pictures off
framerate 30
ffmpeg_video_code mpeg4
width 320
height 240
auto_brightness off
contrast 0
saturation 0
text_right ''
videodevice /dev/video1
log_file /home/pi/log/motion.log
EOF
```

Motion will, by default, look in `~/.motin/motion.conf` for the config file.

A simple video passthrough can be used to test to make sure everything is working:

```
ffmpeg -re -f v4l2 -i /dev/video0 -r 11 -q 3 -f avi - | ffmpeg -re -f avi -i - -f v4l2 /dev/video1
```

After starting `motion`, and pointing a browser to the `motion` port that's been setup (`8080`),
a 320x240 video feed should be seen.

---

Once the simple test has been done, a more complex example can be done with OpenCV that
puts an overlay onto the image.

Here is a simple OpenCV Python program to put some text and an alpha blended box into
the middle of the stream.
Call it `ocv2-overlay-cap.py`:

```
#!/usr/bin/python
#
import sys
import cv2
import numpy as np
foreground = np.ones((100,100,3),dtype='uint8')*255
cap = cv2.VideoCapture(0)
#cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 320)
#cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 240)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
alpha = 0.4
while True:
  ret, background = cap.read()
  #background = cv2.flip(background,1)
  added_image = cv2.addWeighted(background[100:200,100:200,:],alpha,foreground[0:100,0:100,:],1-alpha,0)
  background[100:200,100:200] = added_image
  font = cv2.FONT_HERSHEY_SIMPLEX
  #cv2.putText(background,'alpha:{}'.format(alpha),(10,30), font, 1,(255,255,255),2,cv2.CV_AA)
  cv2.putText(background,'alpha:{}'.format(alpha),(10,30), font, 1,(255,255,255),2,cv2.LINE_AA)
  sys.stdout.write( background.tostring() )
cap.release()
cv2.destroyAllWindows()
```

Now to run:

```
python ./ocv2-overlay-cap.py | \
  ffmpeg -f rawvideo -pixel_format bgr24 -video_size 320x240 -i - -f avi -speed 10 -q 3 -r 11  -fflags nobuffer - | \
  ffmpeg -f avi -i - -f v4l2 /dev/video1
```

This will create a 320x240 feed with a simple overlay of text and a box.

Run `motion` and then point your browser to `localhost:8080`.

Misc.
---

I was getting some errors when trying to load `cv2` from python.
The following solved the issue:

```
apt update
apt upgrade
reboot
```

---

I was getting a different set of errors when trying to get `/dev/video1` to appear:

```
# modprobe v4l2loopback
modprobe: FATAL: Module v4l2loopback not found in directory /lib/modules/4.19.97-v7+
```

After doing:

```
apt-get update
apt-get upgrade
reboot
```

Followed by:

```
# modprobe v4l2loopback
modprobe: FATAL: Module v4l2loopback not found in directory /lib/modules/4.19.97-v7+
# depmod -a
# modprobe v4l2loopback
# ls -la /dev/video*
/dev/video0  /dev/video1  /dev/video10  /dev/video11  /dev/video12
```

[src](https://github.com/umlaeute/v4l2loopback/issues/59)


---

Different qualities can be fed in to try and speed up the video with the `-q`, `-r` and `-speed` parameters.
Some have been chosen above but they can be altered depending on what quality of video and what playback
speed is desired.

---

The `motion` parameters in `motion.conf` can be added to save to output files:

```
output_pictures on
picture_output on
```

---

The `motion` parameter, `stream_localhost`, in `motion.conf` should be set to `off` to ensure
only `localhost` streaming can occur:

```
stream_localhost on
```


References
---

* [SO: OpenCV Python, reading video from named pipe](https://stackoverflow.com/questions/35166111/opencv-python-reading-video-from-named-pipe)
* [GH: How to read a video frame from a pipe, for Opencv #120](https://github.com/kkroening/ffmpeg-python/issues/120)
* [SO: How to stream a local video to webcam using ffmpeg?](https://unix.stackexchange.com/questions/466663/how-to-stream-a-local-video-to-webcam-using-ffmpeg)
* [Add image to a live camera feed using OpenCV-Python](https://theailearner.com/2019/03/18/add-image-to-a-live-camera-feed-using-opencv-python/)
* [How to find frame rate or frames per second (fps) in OpenCV ( Python / C++ ) ?](https://www.learnopencv.com/how-to-find-frame-rate-or-frames-per-second-fps-in-opencv-python-cpp/)
* [How to set cv2.VideoCapture() image size in Python](https://techoverflow.net/2018/12/18/how-to-set-cv2-videocapture-image-size/)
* [GH: v4l2loopback](https://github.com/umlaeute/v4l2loopback)
* [SO: Is there any way ffmpeg send video to /dev/video0 on Ubuntu?](https://askubuntu.com/questions/881305/is-there-any-way-ffmpeg-send-video-to-dev-video0-on-ubuntu)
* [ffmpeg capture/webcam](https://trac.ffmpeg.org/wiki/Capture/Webcam)
* [Picamera web streaming](https://picamera.readthedocs.io/en/release-1.13/recipes2.html#web-streaming)
* [Motion: Output - Pipe Options](https://motion-project.github.io/motion_config.html#OptDetail_Pipe)
* [Making a video with opencv and ffmpeg. How to find the right color format?](https://stackoverflow.com/questions/12503368/making-a-video-with-opencv-and-ffmpeg-how-to-find-the-right-color-format)

