17

I have a RaspberryPi and a Logitech C920 Webcam. I want to use these devices to work as a surveillance / babycam, i.e. : Stream audio + video over HTTP (or any other protocol) without cpu intensive video transcoding

The C920 webcam is able to stream H264 natively, so theoretically I won't need to ask RaspberyPi+VLC to transcode the video stream.

The built-in C920 Microphone stream does not seem to be included in the webcam stream. Cam and microphone are 2 separate devices.

The C920 also has a built-in led indicator. I want to control that to avoid the LED to ligth up while recording.

How can I achieve that ?

LoneWanderer
  • 3,058
  • 1
  • 23
  • 41

2 Answers2

42

This solution is tested and working with versions indicated below. Using this method, the RaspberryPi3 is always around 5% CPU.

edit 2018-11-18: One can also see the all-in-one solution prototype on RaspiVWS project homepage (for curious people, see GitHub project)

0. Preliminary checks

1. Webcam video configuration

2. Microphone identification

3. Stream using VLC

4. Make RaspberryPi3+ a Wifi access point (If you have no existing network to connect your Pi to)

5. Script at startup or as a service

6. [EDIT] Additional commands : infinite loop recording & split video

7. [EDIT] Program execution at a given instant

8. [EDIT] TROUBLESHOOTING


0. Preliminary checks

The answer is working with Raspbian 9.4 Stretch. Check your version with the following command :

lsb_release -a

You should see:

No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 9.4 (stretch)
Release:        9.4
Codename:       stretch

We can rely on the following tools :

  • v4l allows to control the webcam. It offers the command v4l2-ctl which will allows us to control and config the webcam.
  • VLC which is not only a video player, but also has powerful streaming capabilities

You can install them with the following commands :

sudo apt-get install vlc
sudo apt-get install v4l-utils

Once everything is installed, you can configure your C920 webcam.


1. Webcam video configuration

v4l2-ctl --all lists all available devices and their config

pi@raspberrypi:~ $ v4l2-ctl --all
Driver Info (not using libv4l2):
    Driver name   : uvcvideo
    Card type     : HD Pro Webcam C920
    Bus info      : usb-3f980000.usb-1.5
    Driver version: 4.14.30
    Capabilities  : 0x84200001
        Video Capture
        Streaming
        Extended Pix Format
        Device Capabilities
    Device Caps   : 0x04200001
        Video Capture
        Streaming
        Extended Pix Format
Priority: 2
Video input : 0 (Camera 1: ok)
Format Video Capture:
    Width/Height      : 1920/1080
    Pixel Format      : 'H264'
    Field             : None
    Bytes per Line    : 3840
    Size Image        : 4147200
    Colorspace        : sRGB
    Transfer Function : Default
    YCbCr/HSV Encoding: Default
    Quantization      : Default
    Flags             : 
Crop Capability Video Capture:
    Bounds      : Left 0, Top 0, Width 1920, Height 1080
    Default     : Left 0, Top 0, Width 1920, Height 1080
    Pixel Aspect: 1/1
Selection: crop_default, Left 0, Top 0, Width 1920, Height 1080
Selection: crop_bounds, Left 0, Top 0, Width 1920, Height 1080
Streaming Parameters Video Capture:
    Capabilities     : timeperframe
    Frames per second: 30.000 (30/1)
    Read buffers     : 0
                     brightness (int)    : min=0 max=255 step=1 default=-8193 value=128
                       contrast (int)    : min=0 max=255 step=1 default=57343 value=128
                     saturation (int)    : min=0 max=255 step=1 default=57343 value=128
 white_balance_temperature_auto (bool)   : default=1 value=1
                           gain (int)    : min=0 max=255 step=1 default=57343 value=255
           power_line_frequency (menu)   : min=0 max=2 default=2 value=2
      white_balance_temperature (int)    : min=2000 max=6500 step=1 default=57343 value=4822 flags=inactive
                      sharpness (int)    : min=0 max=255 step=1 default=57343 value=128
         backlight_compensation (int)    : min=0 max=1 step=1 default=57343 value=0
                  exposure_auto (menu)   : min=0 max=3 default=0 value=3
              exposure_absolute (int)    : min=3 max=2047 step=1 default=250 value=333 flags=inactive
         exposure_auto_priority (bool)   : default=0 value=1
                   pan_absolute (int)    : min=-36000 max=36000 step=3600 default=0 value=0
                  tilt_absolute (int)    : min=-36000 max=36000 step=3600 default=0 value=0
                 focus_absolute (int)    : min=0 max=250 step=5 default=8189 value=0 flags=inactive
                     focus_auto (bool)   : default=1 value=1
                  zoom_absolute (int)    : min=100 max=500 step=1 default=57343 value=100
                      led1_mode (menu)   : min=0 max=3 default=3 value=3
                 led1_frequency (int)    : min=0 max=255 step=1 default=0 value=0

The last 2 lines gives us clues to control the built-in LED indicator, for instance, to deactivate the LED indicator. The -d0 parameter indicates on which device the modifcation should be applied (if you ahve several cams or its device name changed)

v4l2-ctl -d0 --set-ctrl=led1_mode=0
v4l2-ctl -d0 --set-ctrl=led1_frequency=30

2. Microphone identification

The command arecord -l will give us the list of ALSA devices. (ALSA is the audio manager in RaspberryPi)

pi@raspberrypi:~ $ arecord -l
**** Liste des Périphériques Matériels CAPTURE ****
carte 1: C920 [HD Pro Webcam C920], périphérique 0: USB Audio [USB Audio]
  Sous-périphériques: 1/1
  Sous-périphérique #0: subdevice #0

This means that the built-in microphone is located on hardware 1, periph 0. You can check that in command line with alsamixer -c 1 -V capture

3. Stream using VLC

VLC can be launched using command line. Since we do not have video and audio already mixed together in a single stream access, we need to ask VLC to do that. It is the role of the transcoding feature of VLC.

  1. Stream over HTTP

We also want to stream over HTTP, VLC can also achieve that.

cvlc v4l2:///dev/video0:chroma=h264 :input-slave=alsa://hw:1,0 --sout '#transcode{acodec=mpga,ab=128,channels=2,samplerate=44100,threads=4,audio-sync=1}:standard{access=http,mux=ts,mime=video/ts,dst=:8099}'

Explanation

  • v4l2:///dev/video0:chroma=h264 gives VLC input data : it grabs the video stream from /dev/video0 and that it is a h264 encoding (if your webcam is the 0th video device, it could also be another number, refer to v4l2-ctl --all command)
  • :input-slave=alsa://hw:1,0 tells VLC to take another input stream with the video. It is the audio stream identified from the arecord above
  • --sout tells VLC how to handle the output stream
  • #transcode{acodec=mpga,ab=128,channels=2,samplerate=44100,threads=4,audio-sync=1} tells VLC to convert the audio to mpga codec, 128 kbits/s, 2 channels, 44100 Hz sampling, using all 4 RaspberryPi3+ cores. audiosync is optional. It took me some time to realize this : the webcam h264 video stream is kept as provided (no video transcoding).
  • :standard{access=http,mux=ts,mime=video/ts,dst=:8099} tells VLC to provide stream over HTTP on port 8099 with the TS muxing format.

On any other device, you can use VLC to access your RaspberryPi3+ VLC stream : vlc http://<raspberrypi-ip>:8099

It works with any VLC client :

  • windows
  • unix
  • mac
  • confirmed with iPhone 7 (v11.2.1 (15C153)) with VLC app (3.0.3 (305))

NB : Having the video already in H264 1920x1080 30fps in output of the webcam saves a lot of RaspberryPi3+ CPU.

  1. Different containers

You can also record to various containers, or even containers + stream, here are some examples:

  • record to MKV cvlc v4l2:///dev/video0:chroma=h264 :input-slave=alsa://hw:1,0 --sout '#transcode{acodec=mpga,ab=128,channels=2,samplerate=44100,threads=4,audio-sync=1}:standard{access=file,mux=mkv,dst='/home/pi/Webcam_Record/MyVid.mkv'}'

  • record to MP4 cvlc v4l2:///dev/video0:chroma=h264 :input-slave=alsa://hw:1,0 --sout '#transcode{acodec=mpga,ab=128,channels=2,samplerate=44100,threads=4,audio-sync=1}:standard{access=file,mux=mp4,dst='/home/pi/Webcam_Record/MyVid.mp4'}'

  • record + stream cvlc v4l2:///dev/video0:chroma=h264 :input-slave=alsa://hw:1,0 --sout '#transcode{acodec=mpga,ab=128,channels=2,samplerate=44100,threads=4,audio-sync=1}:duplicate{dst=standard{access=file,mux=mp4,dst='/home/pi/Webcam_Record/MyVid.mp4'},dst=standard{access=http,mux=ts,mime=video/ts,dst=:8099}}'

    1. Format filenames, timestamps

You can also use formatted string for filenames. Prefix command like this:

cvlc --sout-file-format v4l2:///dev/video0:<...> dst='/home/pi/Webcam_Record/%F_%T_MyVid.mp4'}

It will produce a file named YYYY-MM-DD_HH:MM:SS_MyVid.mp4 (: are authorized in unix filenames, but not in windows filenames)

4. Make RaspberryPi3+ a Wifi access point

If you have no existing network to connect your Pi to: You can follow instructions from official RaspberryPi3+ website : https://www.raspberrypi.org/documentation/configuration/wireless/access-point.md

Otherwise, if you already have a network you can connect to your pi using its IP. See part 3

On any other device, you can use VLC to access your RaspberryPi3+ VLC stream : vlc http://<raspberrypi-ip>:8099

5. Script at startup

You can put many commands into a bash file my_bash_file.sh. For instance :

#!/bin/bash
# auto stream launch + led off
#cvlc -vvv for verbose debug

# change this value to adapt to your webcam device number
deviceNb=0

# force video format + led off
v4l2-ctl -d${deviceNb} --set-fmt-video=width=1920,height=1080,pixelformat=1 --set-ctrl=led1_mode=0

# if delay needed 
# cvlc v4l2:///dev/video${deviceNb}:chroma=h264 :input-slave=alsa://hw:1,0  :live-caching=2500  --sout '#transcode{acodec=mpga,ab=128,channels=2,samplerate=44100,threads=4,audio-sync=1}:standard{access=http,mux=ts,mime=video/ts,dst=:8099}'

# no delay
cvlc v4l2:///dev/video${deviceNb}:chroma=h264 :input-slave=alsa://hw:1,0 --sout '#transcode{acodec=mpga,ab=128,channels=2,samplerate=44100,threads=4,audio-sync=1}:standard{access=http,mux=ts,mime=video/ts,dst=:8099}'
  1. Basic method

You can then make the rc.local script use your custom script to be executed at startup. You can follow instructions from official RaspberryPi3+ website : https://www.raspberrypi.org/documentation/linux/usage/rc-local.md

  1. Another method : Create a deamon service

We will create a "webcam-stream" service, assuming all necessary bash commands are located /home/pi/Webcam_Record/vlc_webcam_stream_service.sh

cd /lib/systemd/system/
sudo nano webcam-stream.service

And write in it:

[Unit]
Description=Custom Webcam Streaming Service
After=multi-user.target

[Service]
Type=simple
ExecStart=/home/pi/Webcam_Record/vlc_webcam_stream_service.sh
Restart=on-abort

[Install]
WantedBy=multi-user.target

Make the service file and the script executable:

sudo chmod 644 /lib/systemd/system/webcam-stream.service
chmod +x /home/pi/Webcam_Record/vlc_webcam_stream.sh

Allow VLC to be excuted as root:

sudo sed -i 's/geteuid/getppid/' /usr/bin/vlc

Reload deamons and enable our service:

sudo systemctl daemon-reload
sudo systemctl enable webcam-stream.service

Check it is recognized and working:

sudo service webcam-stream status
sudo service webcam-stream start

You can check with another computer that the video is correctly streamed. Note that the webcam won't be available while the service is running.


Once you're done, you can connect to the RaspberryPi3+ wifi access point and access your video stream.


6. [EDIT] Additional commands : infinite loop recording & split video

The following bash scripts allows infinite recording of 15 s long videos with timestamped filenames and streaming

#!/bin/bash
# auto stream launch + led off
#cvlc -vvv for verbose debug

# adapt to video device name
deviceNb=1

# loop duration
duration=15

#infinite recording
#loopOption=
loopOption=--loop

# force video format + led off
v4l2-ctl -d ${deviceNb} --set-fmt-video=width=1920,height=1080,pixelformat=1 --set-ctrl=led1_mode=0

# if delay needed :live-caching=2500
cvlc --sout-file-format --run-time=${duration} ${loopOption} v4l2:///dev/video${deviceNb}:chroma=h264 :input-slave=alsa://hw:1,0 --sout '#transcode{acodec=mpga,ab=128,channels=2,samplerate=44100,threads=4,audio-sync=1}:duplicate{dst=standard{access=file,mux=mp4,dst='/home/pi/Webcam_Record/%F_%T_Spy.mp4'}:dst=standard{access=http,mux=ts,mime=video/ts,dst=:8099}'

7. [EDIT] Program execution at a given instant

EDIT 04 aug 2018

To launch the execution today at 14:00, you can use the following command:

./my_vlc_webcam_script.sh | at 1400

See the at command manual for further details.


8. TROUBLESHOOTING

EDIT 07 jul 2018

I recently ran into VLC error after a dist-upgrade:

VLC media player 2.2.6 Umbrella (revision 2.2.6-0-g1aae78981c)
[00acb230] pulse audio output error: PulseAudio server connection failure: Connection refused

The solution I found is to launch VLC in GUI mode and change the default audio device to ALSA (instead of Automatic). I can also be done in command line. See the solution found here VLC issues with PulseAudio

cvlc -A alsa,none --alsa-audio-device default
LoneWanderer
  • 3,058
  • 1
  • 23
  • 41
  • 5
    I wish I could upvote this more than once. The configuration for this stuff is really complicated and this is the first comprehensive explanation I have seen. – Nathan Jun 28 '18 at 00:41
  • I'm having an issue with sound with the bash file you provided. Sound is not recorded the first time I execute the script. Video works, no sounds. If I terminate the stream on the pi, and start it again, the second time the sound works. The sound also works subsequent times. I have seen some people having the inverse problem where it works initially and then does not work subsequent times. I think it's the same issue, but that is how it manifests with pulse audio as the default. I set the VLC default to ALSA, and that has the inverse problem somehow. – Nathan Jun 28 '18 at 18:45
  • Hi, I did not face this kind of problem on my Pi. Is your Pi up to date (distribution and packages) ? – LoneWanderer Jun 28 '18 at 20:44
  • Or maybe you have another program that takes precedence over the device ? – LoneWanderer Jun 28 '18 at 20:45
  • Tried to make it work today, but somehting must be broken `led1_mode (menu) : min=0 max=3 default=3 value=3` does not appear anymore in the webcam capabilities ... – LoneWanderer Jul 05 '18 at 16:52
  • I don't mind if the LED stays on. It might actually be preferable in my use case, but it's not a big issue either way. The sound is a minor problem as well, I am happy enough to have stable video and if I need sound I can just restart it. However. I would be put at ease a bit if there no problems at all. I am using 9.4 stretch. I believe that this reproduces with the newest v4l2-ctl and vlc, but I am trying to configure multiple pis for this job and I think I have tried different configurations on different ones. – Nathan Jul 05 '18 at 21:05
  • Well, after verification today I’m facing the same sound issue (+ led control) since dist-upgrade 2 days ago ... I consider opening a ticket for raspbian. – LoneWanderer Jul 07 '18 at 11:07
  • Post opened on raspberrypi stackexchange for these two issues : https://raspberrypi.stackexchange.com/questions/85740/raspbian-stretch-c920-webcam-driver-led-control-regression – LoneWanderer Jul 07 '18 at 14:47
  • I consider making a more configurable script and posting it on github, when I get time for this. – LoneWanderer Aug 04 '18 at 11:50
  • use ' :live-caching=1000 --sout-keep' to fix the audio issue – Gotschi Aug 18 '18 at 15:18
  • Thanks @JonathanEustace I put a first bash project on github but I've come up with a greater idea that needs some global rethinking. I'll need some time to think of it and a lot more to do it :D – LoneWanderer Dec 04 '18 at 19:07
  • It looks like at some point either the uvc driver, the c920 firmware, or vlc changed the API a bit. I'm running kernel 5.4 on Slackware-current and I was unable to get this to work using `cvlc ... :chroma=h264 ...` and after much banging of head and searching found that I needed to set ti to `cvlc ... :chroma=mjpg ...` instead. `v4l2-ctl -d 0 --all` also shows the pixel format as MJPG and not H264 on my setup. Perhaps a note should be added to the answer? Thanks for your hard work! – BytePorter Jan 26 '20 at 21:08
  • If `led1_mode` is not showing up, try plugging in differernt USB ports. – jellycsc Sep 18 '20 at 06:52
  • known bug VLC 3.0.16 vlc does not accept the alsa url https://code.videolan.org/videolan/vlc/-/issues/26054 so `:input-slave=alsa://hw:1,0` won't work with this VLC version – LoneWanderer Feb 13 '22 at 17:47
0

You need the vcodec= for video to work and deinterlace if you want that.

cvlc v4l2:///dev/video0:chroma=h264
                       :input-slave=alsa://hw:1,0
                       :live-caching=2500
--sout '#transcode{
                     deinterlace,
                     vcodec=mpgv,
                     acodec=mpga,
                     ab=128,
                     channels=2,
                     samplerate=44100,
                     threads=4,
                     audio-sync=1}
       :standard{
                     access=http,
                     mux=ts,
                     mime=video/ts,
                     dst=0.0.0.0:8099}'
PaSe
  • 93
  • 1
  • 1
  • Terminal reads input options as one line so please use discretion. `cvlc v4l2:///dev/video0:chroma=h264:input-slave=alsa://hw:1,0:live-caching=200 --sout '#transcode{deinterlace,vcodec=h264,acodec=mp3,ab=128,channels=2,samplerate=44100, threads=4,audio-sync=1}:standard{access=http,mux=ts,mime=video/ts,dst=0.0.0.0:8099}'` – PaSe May 11 '19 at 16:42
  • I'm not seeing this work with my set up -- not sure why just yet. – dalanmiller Mar 21 '20 at 03:33