Sky Watch

Meow video streaming with Raspberry Pi

First of all, let’s make one thing clear—you don’t take care of your cat; your cat takes care of you.

In order for my cat to take better care of me, I was planning to purchase a home surveillance camera, something like a Nest camera. However my cat told me such a thing is too expensive, and not worth the price. After all I don’t need fancy features like motion detection, online backup, and all those “cloud” nonsense, I don’t even need video storage at all (I only want to see live video feed). I wouldn’t trust any company to have videos of my home, where my cat sometimes walks naked. So I decided to build my own video streaming server.

I bought a Raspberry Pi 2, the official IR camera module, and a plastic case for the Pi. Upon 1st time it is booted, it shows a interface to select a OS to install. I tried Arch Linux, but it won’t boot after restart. So I went with the default Debian. It’s a pretty capable OS right after installation; it even has a version of Mathematica on it! Who knows, I might just migrate my research work to the Pi.

The easy way

Naturally, a lot of people want to do the same thing on their Pis, and there are a bunch of articles on how to do it. The catch is, 99% of them don’t work. For example, UV4L promises 0 configuration video streaming on HTML5, along with a bunch of other things. But it appears that the video is not compressed with hardware acceleration. I’m not entirely sure, but this is the only reason I can think of that explains why the video is fixed at 640x480 (strangely it has a setting page that is suppose to change this, and guess what, it never works) , and are so darn laggy. It also provides configuration files and is able to stream the video through other means than HTML5, but it never worked on me.

The same goes all methods based on v4l2 module. It does not utilize hardware acceleration, and therefore is always laggy and unusable.

The not-working-but-should way

I had a lot of good experience with FFmpeg, and expected it to just work. However it is not the case this time. I set up FFserver with something like

HTTPPort 8090
HTTPBindAddress 0.0.0.0
MaxHTTPConnections 8
MaxClients 4
MaxBandwidth 1000
CustomLog -
#NoDaemon

<Feed feed1.ffm>
    File /tmp/feed1.ffm
    FileMaxSize 5M
    ACL allow 127.0.0.1
</Feed>

<Stream live.flv>
    Feed feed1.ffm
    NoAudio
</Stream>

<Stream stat.html>
    Format status
    # Only allow local people to get the status
    ACL allow localhost
    ACL allow 192.168.0.0 192.168.255.255
</Stream>

Then I start the server with ffserver -f server.conf &, and use raspivideo to feed the (hardware accelerated!) H264 stream into ffmpeg, which is supposed to just wrap the stream in a FLV container,

raspivid -t 0 -w 640 -h 480 -b 1024000 -fps 5 -ih -n -o - | \
  ffmpeg -i - -c:v copy -r 5 -an -f flv -override_ffserver \
  http://localhost:8090/feed1.ffm

That should be all I need to do. However FFmpeg refused to wrap the H.264 stream, and complained

[flv @ 0x215e520] Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly
Thu Mar  3 02:58:36 2016 127.0.0.1 - - [POST] "/feed1.ffm HTTP/1.1" 200 276
av_interleaved_write_frame(): Connection reset by peer
[flv @ 0x215e520] Failed to update header with correct duration.
[flv @ 0x215e520] Failed to update header with correct filesize.
Error writing trailer of http://localhost:8090/feed1.ffm: Connection reset by peer

I posed a question in StackExchange, but so far nobody seems to know what’s wrong.

The only way

After some annoying trial-and-error, the following is the only way I can get it to work,

It’s not an elegant solution, and VLC is lacking in many ways in comparison with FFmpeg. But at least now I can see my cat in office.