Live Stream Your Pets with Linux and YouTube!
Anyone who reads Linux Journal knows about my fascination with birdwatching. I've created my own weatherproof video cameras with a Raspberry Pi. I've posted instructions on how to create your own automatically updating camera image page with JavaScript. Heck, I even learned CSS so I could make a mobile-friendly version of BirdCam that filled the screen in landscape mode.
Recently, however, I've finally been able to create an automated system that streams my BirdCam live over YouTube. It starts when the sun comes up and stops when the sun goes down. And thanks to some powerful open-source software, I never have to touch the system!
Some of the tools I describe here have been covered in other articles, but this is the first time I've been able to create a stream that anyone can see utilizing bandwidth Google pays for!
Figure 1. Birds are always camera-shy. If you watch long enough, however, they come and steal peanuts!
My List of IngredientsFirst off, I want to be clear about what sort of hardware and software is required in order to accomplish something similar to what I'm doing:
-
A Linux computer: if you plan to use USB cameras, this needs to be a physical computer. If your video source is network-based, this can be a virtual machine on your network. A Raspberry Pi isn't really powerful enough for the video work that has to be done, unless maybe it's low-resolution. I have an old i5 CPU running at 1.6GHz, and it's more than enough.
-
A video source: this can be pretty much any video source you have at hand. If you plan to use a USB webcam, you'll need to be sure you are using a physical Linux computer as noted above. I've used USB, MJPEG over http (see my old BirdCam articles), cheap wireless security cameras that have an RTSP stream, and most recently, I started using UniFi video cameras. In fact, if you are considering purchasing outdoor video cameras for a project like this, I can't recommend UniFi cameras enough. They are PoE, HD and the free software handles recording and provides RTSP streams that have both HD video and top-notch audio.
-
A YouTube account with Live Streaming enabled: you'll need to verify your account, and then enable live streaming here. It's not a difficult process, but without following those steps, you won't be able to use the free service.
-
Open Broadcaster Software: I've tried multiple ways to use a CLI solution to stream directly to YouTube with FFmpeg or mencoder, but I've never been able to make it work consistently. I was hesitant to use OBS, because it's a GUI solution and doesn't have a CLI interface, but I worked around that problem, and I'm actually happy to have the GUI now.
-
A web server to host your embedded channel: you could just share the URL to your YouTube channel, but embedding is much cooler, because you can integrate it into your own site.
-
Enough upstream bandwidth to support 1.5–2mbps while streaming: since YouTube is going to redistribute, the local bandwidth requirements don't change regardless of how many people are watching your stream. For some folks (like me, unfortunately), sacrificing that much bandwidth is difficult and sometimes causes issues. Just know that it takes a small, but not insignificant amount of constant upstream bandwidth to stream live video. That should be obvious, but it's something to consider.
-
A few other utilities like crontab and sunwait: the latter is only if you want to time your streams with sunrise and sunset. And, crontab is needed only if you want to automate the starting and stopping. Those touches really make a difference for me though, so I encourage you to consider it.
YouTube:
In order to live stream, you'll need a few bits of information. As I mentioned above, you'll need to verify your account to turn on streaming. Then you'll need to get your streaming key (Figure 2). It's important that you not share the streaming key, because it acts like your authentication. If others get your key, they can stream to your channel, even without your user name.
Figure 2. That's not my real streaming key, just FYI.
The other bit of information you'll need from YouTube is your channel ID. It's not easy to find the channel ID, but if you want to embed your video, you'll need it later. Head to this page, and find the line that looks like, "YouTube Channel ID: UCbUTB3bVg3cmeyJUtUC9DPA" (your channel ID will be different from mine). The long string of text is your channel ID, copy that somewhere easy to find.
Video Camera Feeds:
I can really give you only hints about what to look for here. You need to find the streaming video feed coming from your camera. Make sure you don't use the web page that has the stream embedded (most cameras have a rudimentary web server that embeds the stream). You need the raw feed itself. Google or the user's manual will be your best bet for figuring out the raw stream URL.
I have an Onvif-compatible video camera that has an MJPEG stream URL that looks like this: http://192.168.1.170:9090/stream/video.mjpeg.
One of my Foscam cameras requires a user name and password in the URL in order to get the stream. It looks like this: http://192.168.1.180:88/cgi-bin/CGIStream.cgi?cmd=GetMJStream&usr=admin&pwd=xxx.
And my new UniFi cameras actually use an RTSP URL that comes from the UniFi server instead of from the cameras directly. It looks like this: rtsp://192.168.1.16:7447/58cf11bef14c359f4b3c7b2e_1.
The point I'm trying to make is that finding your video camera's streaming URL often is challenging. If you do it before you start, it can save hours of frustration. An easy way to test if you've found the correct URL is to try opening it in VLC. I haven't found a video camera that VLC can't view, so if it complains about an invalid video source, you probably don't have the correct URL. Google, along with your camera's model number, is probably the best way to figure it out.
The SoftwareThere are many scripts online claiming to stream from a camera source to YouTube using FFmpeg. I'm sure they work for someone, but I've never gotten them to work, no matter how many settings I tweak. In fact, I gave up for quite a while because I didn't want to rely on a GUI interface to stream. I wanted my server to do the dirty work and do it without my interaction. One day recently, however, I discovered that Open Broadcaster Software (OBS) supports command-line flags for starting streaming. That means I could have the server start streaming without the need to "click" anything.
One problem I had to overcome was the lack of the X Window System on my BirdCam server. There's no monitor connected to the server, but in order for OBS to work, it has to have a logged-in GUI desktop. I hooked up a monitor long enough to get a GUI installed and then set the system to log in automatically. I also disabled all power-saving features for the monitor, because I wouldn't have one logged in anyway. Once it was set up, I installed TeamViewer so I could control the system remotely if I needed to. There have been some issues with TeamViewer's security recently, so it might not be the software you choose for controlling the server, but it's what I have installed, and it works. Figure 3 shows my "server" controlled remotely via TeamViewer.
Figure 3. I don't normally have the security camera to my cat's litter cave on my live stream, but I wanted to show multiple cameras.
Installing OBS is simple. Head over to the OBS site and download the latest version, or simply install their PPA if you're using Ubuntu. The software has matured since I last mentioned it, and I didn't have any problems with dependencies, even when connecting over a remote session.
OBS also has the great feature of saving your last-used session. That means once you set up your cameras, you don't have to worry about readjusting them on the next launch. OBS just uses the same settings you had before. If you look back at Figure 3, you'll see there are multiple cameras added to the preview window. Without the need to save a layout, OBS just remembers from launch to launch how you had the cameras positioned.
In order to get the best results, you need to tweak a few OBS settings. Click the settings button, and then head over to the Video tab (Figure 4). This is a little confusing, but you have two different resolutions to set. The "canvas" is how big you want OBS to show on your preview window. The "output" resolution is what it scales your video to for streaming and recording. I just set them both to 720p, because I figure scaling takes CPU. You also set the frames per second (FPS) for the output video. I use 10FPS with the 720p size. You can adjust this if you want 1080p, or down if you don't have bandwidth.
Figure 4. The resolutions are flexible, but I like to keep it simple.
Next, click on the "Output" tab (Figure 5). My settings are visible, and I recommend keeping them close to mine, except for the bitrate of the video and audio. If you want higher quality video (and you can afford the bandwidth), this is where you set the average upload speed. You also can change the audio quality if you want higher quality. Keep in mind that the resolution you chose in the last step will work with the bandwidth you selected here to give you the video quality users will see. A video rate of 1500 (measured in kbps) works well with my 10FPS and 720p resolution. But if you try to stream 1080p, 30FPS video with 1500kbps, it's going to be really poor quality video. You'll have to experiment to find the sweet spot.
Figure 5. 1500 is the maximum my current internet connection can handle.
The "Stream" tab is where you configure the streaming service you want OBS to use (Figure 6). You should be able to select YouTube and then paste that stream key you got from YouTube earlier. (This is not the channel ID; it's that hidden key from back in Figure 2.) Once entered, you shouldn't need to make any changes in settings. OBS will keep all the settings, including streaming information.
Figure 6. It's truly amazing how well OBS does with YouTube streaming.
All that's left is to add the camera(s) to your preview screen. This is the nicest feature of OBS, well apart from actually being able to stream to YouTube. The setup is drag and drop, and you can resize cameras, overlap cameras and arrange them however you want. Since OBS supports so many types of inputs, you can get crazy with text overlays and so on. To add a network camera, click the + at the bottom middle of the main window, and select "media source" (Figure 7). Then uncheck "local file" and enter the camera URL in the "input" field (Figure 8). Once you click OK, your camera should appear on the preview window, and you can resize and move it. The interface also allows you to crop the section of the video you want to use. It's very powerful and incredibly user-friendly. Plus, as I mentioned earlier, OBS stores all your tweaks automatically, so the next time you start it, you'll get the same arrangement.
Figure 7. Media source isn't obvious as the choice for network cameras.
Figure 8. Be sure to uncheck the "local file", or you won't have an input field.
Once you have your camera(s) set up, you can decide whether you want to include audio if your camera supports it. The audio levels should appear in the column next to the list of cameras. Then just click "Start Streaming" to send your stream live to YouTube. It takes 30 seconds or so to show up in the YouTube dashboard, but now is the time to make sure streaming works.
AutomationI could just leave OBS running 24/7 and have it stream my bird feeders all night. Honestly, I'm not sure how YouTube would handle a 24/7 stream, but I don't want to do that anyway. I not only want to automate the starting and stopping of OBS, but I also want to make sure that if something crashes, it starts back up the next day without me needing to fix it. Cron was the obvious way to manage that, but since OBS is a GUI program, cron proved to be challenging. In the end, I was able to include environment variables in my crontab, and things worked smoothly. Here's what my OBS part of crontab looks like. Check it out, and I'll explain it afterward:
DISPLAY=:0
@reboot sleep 10; obs --startstreaming
0 5 * * * /usr/local/bin/sunwait civ up 45.3733N 84.9553W;
↪obs --startstreaming
0 16 * * * /usr/local/bin/sunwait civ down 45.3733N
↪84.9553W; pkill obs
First off, setting the DISPLAY
environment variable
to :0
means that
crontab can launch a GUI application on the current desktop. I was
embarrassed when I realized how easy it was to get cron to launch GUI
apps. It is important to note that the user must be logged in, however.
The @reboot
line starts OBS when the system boots. The simple
--startstreaming
flag tells OBS to launch and immediately start
streaming. It's awesome. Really, if I had to figure out a way to automate
actually clicking a button, we probably wouldn't be doing this project
together.
The next two lines are a little confusing. First off, I have the program "sunwait" installed. It's an old program, but it's so incredible, I can't believe it's not in every distribution by default. I've mentioned it before in BirdCam articles, but basically, it's a C program that determines sunrise and sunset based on your longitude and latitude. The last version was released in 2004 (seriously), but it still compiles. You can get the source here.
Anyway, those two cron lines tell the server to start and stop OBS
at sunrise and sunset. At 5AM, I tell sunwait to "wait" until the sun
rises. It literally just waits until sunrise and then ends. Once it ends,
OBS is started up. Then at 4PM, I tell sunwait to wait until sunset, and
after the sunwait program ends, kill
stops OBS. Why 5AM and 4PM? Well,
in my part of the world, the sun never rises before 5AM and never sets
before 4PM. There is the potential problem that if I reboot my server
after 4PM, it will stream all night. But that potential problem doesn't
concern me enough to make the logic more complicated.
Since my server doesn't have a monitor or keyboard connected, a random GUI application starting and stopping in the middle of the screen doesn't affect anything. Since I connect to my server's desktop only when I want to make a change to OBS, it's actually convenient that it's always running front and center on my desktop! I couldn't be happier with the current live stream setup.
Embedding the StreamNot long ago, YouTube made a change so that every time a live stream starts, it gets its own embed code. That means if you simply use the "share" button on the live stream to get the embed code, it will work only for that current streaming session. For me, that means the next day it would show a recording of the previous day, but not the live stream. I'll be honest, that quiet change was very frustrating! Thankfully, there is a way to embed the actual live stream, so that any time you start live streaming, it becomes active—that's where the Channel ID you got earlier comes in.
Here is the embed code for my live stream at http://birds.brainofshawn.com">:
<iframe width="1280" height="720"
↪src="https://www.youtube.com/embed/live_stream?channel=
↪UCbUTB3bVg3cmeyJUtUC9DPA&autoplay=1" frameborder="0"
↪allowfullscreen></iframe>
Obviously, you'll need to make the changes for your own channel, but it should be clear what the various things mean. I stuck with the 720p size even on my embedded page. Since this is embed code, you don't have to put it on its own page like I did; you could embed a tiny resolution version on your blog, for instance.
Setting up the live stream through YouTube is nice for several reasons. One, your bandwidth requirements don't change even if you have 10,000 viewers. Also, since it's YouTube, you can "cast" the video to a television or Chromecast device and show off your channel to your friends. I still hope to get more cameras and maybe set up camera rotation on multiple bird feeders, but for right now, I couldn't be happier. Enjoy!