Turning an Old Laptop into an IP Camera
This is way out of date now
The information in this post is so out-dated that I wonder why I'm keeping it around. I guess I'm a digital hoarder...
The Why
...I'm cheap.
I already have an old and crusty laptop doing nothing but collecting dust...and I couldn't justify the $40 to $80 bucks it would have cost to get a 'real' IP camera.
The How
There are two parts to this task. The first part is standing up an RTSP server that will accept the webcam stream and serve it.
The Second part is the capture of the integrated webcam and microphone using FFmpeg so it can be sent to the RTSP server.
The Tech
The laptop in question is an old Dell Latitude E6520.
The OS installed is Archlinux.
The software used is rtsp-server and FFmpeg.
The Initial Attempt
I started out just using VLC to accomplish this, but ran into an issue. It seems that there is something amiss between how VLC serves the RTSP stream and how FFMPEG connects to it or vice versa.
I could get the server stood up with VLC:
cvlc v4l2:///dev/video0 --sout '#rtp{mux=ts,sdp=rtsp://IP:PORT/cam.sdp}'
I could also get a VLC client to connect to it:
vlc rtsp://IP:PORT/cam.sdp
I could not however get FFmpeg to connect to it:
Command:
ffmpeg -i "rtsp://IP:PORT/cam.sdp"
Output:
ffmpeg version n4.1.1 Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 8.2.1 (GCC) 20181127
...
[rtsp @ 0x5602a0212e00] method SETUP failed: 459 Client error
rtsp://IP:PORT/cam.sdp: Server returned 4XX Client Error, but not one of 40{0,1,3,4}
I attempted to troubleshoot that...but eventually gave up when I could not find any good info. So I changed my approach.
RTSP Server
Getting this installed on Archlinux was mostly an easy task. I found building the package from the Archlinux User Repository a little time consuming as not all the required Perl modules are called out in the PKGBUILD. That or they are and the required perl modules to install the required perl modules were missing. I realize that is a confusing statement. It really boils down to a little bit of dependency hell (which I may go through again and document that at a later date).
Once installed, you just have to start up the server:
/usr/share/perl5/site_perl/RTSP/rtsp-server.pl
By default, it attempts to bind to port 554 to serve the stream and port 5545 to accept input. See https://github.com/revmischa/rtsp-server#running for more info.
FFmpeg Webcam Capture
You have to do a little work to determine where you microphone and camera are
and what your camera is capable of. In my case, /dev/video0
is my integrated
webcam.
Finding the Webcam
Command:
v4l2-ctl --list-devices
Output:
Laptop_Integrated_Webcam_FHD: I (usb-0000:00:1a.0-1.5):
/dev/video0
/dev/video1
Command:
v4l2-ctl -d /dev/video0 --list-formats
Output:
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture
[0]: 'YUYV' (YUYV 4:2:2)
[1]: 'MJPG' (Motion-JPEG, compressed)
I really don't know what /dev/video1
does. If I --list-formats
against it,
I just get Type: Video Capture
.
Finding the Microphone
Command:
arecord -l
Output:
**** List of CAPTURE Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: 92HD90BXX Analog [92HD90BXX Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
Putting it all Together
Armed with this info, I hand crafted the following command from only the finest DuckDuckGo searches, StackExchange posts, and general trial and error:
/usr/bin/ffmpeg -f alsa -i hw:0,0 -f v4l2 -input_format mjpeg -i /dev/video0 -c:v copy -f rtsp -muxdelay 0.1 rtsp://IP:5545/cam
Microphone Capture:
-f alsa -i hw:0,0
- This is the part that sets the format
-f
for the input-i
. In this case the input is the audio capture device device.
Webcam Capture:
-f v4l2 -input_format mjpeg -i /dev/video0
-
Pretty much the same as the audio capture bit, but this time we point it at the webcam and set the input format to
v4l2
and tellv4l2
to use theinput_format
of mjpeg. -
-c:v copy
-
Don't rencode the video
-
-f rtsp -muxdelay 0.1 rtsp://IP:5545/cam
- Set the output format to
rtsp
- Set
-muxdely
to 0.1 - Send the stream to our rtsp-server
rtsp://IP:5545/cam
cam
was randomly chosen. Pretty sure you can put anything there.
Command:
/usr/bin/ffmpeg -f alsa -i hw:0,0 -f v4l2 -input_format mjpeg -i /dev/video0 -c:v copy -f rtsp -muxdelay 0.1 rtsp://IP:5545/cam
Output:
ffmpeg version n4.1.1 Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 8.2.1 (GCC) 20181127
...
Guessed Channel Layout for Input Stream #0.0 : stereo
Input #0, alsa, from 'hw:0,0':
Duration: N/A, start: 1553354038.802212, bitrate: 1536 kb/s
Stream #0:0: Audio: pcm_s16le, 48000 Hz, stereo, s16, 1536 kb/s
Input #1, video4linux2,v4l2, from '/dev/video0':
Duration: N/A, start: 54826.273717, bitrate: N/A
Stream #1:0: Video: mjpeg, yuvj422p(pc, bt470bg/unknown/unknown), 640x480, 30 fps, 30 tbr, 1000k tbn, 1000k tbc
Stream mapping:
Stream #1:0 -> #0:0 (copy)
Stream #0:0 -> #0:1 (pcm_s16le (native) -> aac (native))
Press [q] to stop, [?] for help
Output #0, rtsp, to 'rtsp://IP:PORT/cam':
Metadata:
encoder : Lavf58.20.100
Stream #0:0: Video: mjpeg, yuvj422p(pc, bt470bg/unknown/unknown), 640x480, q=2-31, 30 fps, 30 tbr, 90k tbn, 1000k tbc
Stream #0:1: Audio: aac (LC), 48000 Hz, stereo, fltp, 128 kb/s
Metadata:
encoder : Lavc58.35.100 aac
[alsa @ 0x55a5e1911080] Thread message queue blocking; consider raising the thread_queue_size option (current value: 8)
frame= 46 fps=7.6 q=-1.0 size=N/A time=00:00:06.42 bitrate=N/A speed=1.06x
The Results
You can play the stream with anything that accepts the protocol rtsp://
VLC can:
vlc rtsp://IP/cam
FFmpeg can:
ffmpeg -i rtsp://IP/cam -c:v copy -t 15 output.mkv
You could even send it to your Home Assistant!
camera:
- platform: ffmpeg
input: '-i rtsp://IP/cam'
extra_arguments: '-q:v 2 -r 15'
name: thickcam
Finally - The Glorious LIVE WEBCAM STREAM!!!!!! not really