These cameras record 1080p wide-angle video at 30 frames per second, use power over ethernet (PoE), can see when it's dark using builtin infrared LEDs and are weather-proof. The video quality is impressive and they are surprisingly inexpensive. The camera can deliver two streams at once, so you can pull a lower resolution stream for preview, motion detection, etc., and simultaneously pull the higher resolution stream to simply record it for later scrutinizing.
After buying a few of these cameras I needed a simple way to pull the raw H264 video from them, and with some digging I discovered the cameras speak RTSP and RTP which are standard protocols for streaming video and audio from IP cameras. Many IP cameras have adopted these standards.
Both VLC and MPlayer can play RTSP/RTP video streams; for the Lorex cameras the default URL is:
rtsp://admin:000000@<hostname>/PSIA/Streaming/channels/1
.
After more digging I found the nice open-source (LGPL license) Live555 project, which is a C++ library for all sorts of media related protocols, including RTSP, RTP and RTCP. VLC and MPlayer use this library for their RTSP support. Perfect!
My C++ is a bit rusty, and I really don't understand all of Live555's numerous APIs, but I managed to cobble together a simple Python extension module, derived from Live555's
testRTSPClient.cpp
example, that seems to work
well.
I've posted my current source code in a new Google code project named pylive555. It provides a very simple API (only 3 functions!) to pull frames from a remote camera via RTSP/RTP; Live555 has many, many other APIs that I haven't exposed.
The code is thread-friendly (releases the global interpreter lock when invoking the Live555 APIs).
I've included a simple
example.py
Python program, that shows how to load H264 video frames from the
camera and save them to a local file. You could start from this
example and modify it to do other things, for example use the
ffmpeg H264 codec to decode
individual frames, use a motion detection library to trigger recording,
parse each frame's metadata to find the keyframes, etc. Here's the current example.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | import time
import sys
import live555
import threading
# Shows how to use live555 module to pull frames from an RTSP/RTP
# source. Run this (likely first customizing the URL below:
# Example: python3 example.py 10.17.4.118 1 10 out.264
if len(sys.argv) != 5:
print()
print('Usage: python3 example.py cameraIP channel seconds fileOut')
print()
sys.exit(1)
cameraIP = sys.argv[1]
channel = sys.argv[2]
seconds = float(sys.argv[3])
fileOut = sys.argv[4]
# NOTE: the username & password, and the URL path, will vary from one
# camera to another! This URL path works with the Lorex LNB2153:
url = 'rtsp://admin:000000@%s/PSIA/Streaming/channels/%s' % (cameraIP, channel)
fOut = open(fileOut, 'wb')
def oneFrame(codecName, bytes, sec, usec, durUSec):
print('frame for %s: %d bytes' % (codecName, len(bytes)))
fOut.write(b'\0\0\0\1' + bytes)
# Starts pulling frames from the URL, with the provided callback:
useTCP = False
live555.startRTSP(url, oneFrame, useTCP)
# Run Live555's event loop in a background thread:
t = threading.Thread(target=live555.runEventLoop, args=())
t.setDaemon(True)
t.start()
endTime = time.time() + seconds
while time.time() < endTime:
time.sleep(0.1)
# Tell Live555's event loop to stop:
live555.stopEventLoop()
# Wait for the background thread to finish:
t.join()
|
Installation is very easy; see the
README.txt
.
I've only tested on Linux with Python3.2 and with the Lorex LNB2151
cameras.
I'm planning on installing one of these Lorex cameras inside a bat house that I'll build with the kids this winter. If we're lucky we'll be able to view live bats in the summer!