IP Camera to Youtube & WebTorrent

Streaming video is one of the most bandwidth demanding applications out there. Scaling it up to serve a lot of clients can be done by streaming to a publicly available CDN (Content Distribution Network) like Youtube or Facebook but also to your own CDN. Which is a bit more challenging.

################################################################
THIS ARTICLE IS NOW OBSOLETE SINCE MY NEW CAMERA HAS RTMP BUILD IN.
################################################################

Player Instances

Below i’ve embedded two instances of the same stream. The first one is from Youtube. The second one is a Clappr player using a Peer to Peer technique from WebTorrent.

Youtube

Youtube stream

Clappr/Webtorrent

Clappr HLS/P2P stream

This (P2P) technique is very usefull and efficient in offloading my bandwidth. Which means that traffic is shared between simultaneous viewers of this stream. You can check it out by ‘inspecting’ the player element. Over in console http and p2p traffic is displayed. Demo page screenshot

Criteria

To get to this point I’ve tried several different approaches but along the way i realized that it had to apply to three criteria.

  • Youtube/RTMP dump
  • HLS/DASH source for P2P stream sharing
  • RTSP source for Machine Learning Python apps

So i’ve ended up with the following scenario.

So the RTSP stream is pulled of the IP Camera with Wowza from a remote location to my server. There it is split up in several different sub streams (HLS/RTSP/RTMP) and pushed to Youtube. The stress on the server is very minimal. No transcoding is done, the full 2K (1440p) is fed to all the streams.

Now for the interesting part. Using HLS, the stream is pulled from Wowza and served to visitors of my website viewing the Clappr stream. Once a client connects it makes itself known to the tracker. The tracker holds a collections of already connected clients and instructs the WebTorrent script to start sharing the stream among each other. In theory only 25% of all traffic is pulled of of my server and 75% is shared between clients. This makes scalability much easier and more cost efficient.

The last part of the puzzle is used for personal projects. Playing around with machine learning apps in Python. Counting the number of boats passing by every day for example.

Youtube Streaming

Like i said on the previous page. It took me a while to get to this point. A stable connection from which i can pull different sub streams of.

My first attempt was using FFMpeg and GStreamer and pushing it to Youtube. Both worked well, but had some stability issues. Alternatively I could have used the FFMpeg/GStreamer API for Python and adding a watchdog function for stream monitoring.

FFMpeg example

ffmpeg -rtsp_transport tcp -i "rtsp://user:password@ip-address-camera:554/cam/realmonitor?channel=1&subtype=0" -framerate 30 -vcodec libx264 -preset fast -maxrate 6M -bufsize 12M -g 60 -c:a aac -b:a 128k -ar 44100 -f flv rtmp://a.rtmp.youtube.com/live2/your-youtube-private-key

GStreamer example

gst-launch-1.0 -v rtspsrc location=rtsp://user:password@ip-address-camera:554/cam/realmonitor?channel=1&subtype=0 ! decodebin ! x264enc ! mp4mux ! queue ! flvmux streamable=true name=mux ! rtmpsink location="rtmp://a.rtmp.youtube.com/live2/your-youtube-private-key

Clappr/Webtorrent Streaming

Also using FFMpeg and GStreamer pushed a HLS stream to my NGINX webserver. From there it was picked up by the P2P enabled Clappr player and shared among viewers.

A HLS (or DASH) stream is basically a stream chopped into pieces. So you get a file structure on your NGINX server like this:

  • section1.ts
  • section2.ts
  • section3.ts
  • section4.ts
  • section5.ts
  • playlist.m3u8

FFMpeg example

ffmpeg -fflags nobuffer \
 -rtsp_transport tcp \
 -i rtsp://user:password@ip-address-camera:554/Streaming/channels/101 \
 -vsync 0 \
 -copyts \
 -vcodec copy \
 -movflags frag_keyframe+empty_moov \
 -an \
 -hls_flags delete_segments+append_list \
 -f segment \
 -segment_list_flags live \
 -segment_time 5 \
 -segment_list_size 20 \
 -segment_format mpegts \
 -segment_list /path/to/your/webserver/index.m3u8 \
 -segment_list_type m3u8 \
 /path/to/your/webserver/%d.ts

GStreamer example

gst-launch-1.0 -v -e rtspsrc protocols=tcp location=rtsp://user:password@ip-address-camera:554/Streaming/channels/101 latency=3000 ! queue ! rtph264depay ! h264parse config-interval=-1 ! mpegtsmux ! hlssink location=/path/to/your/webserver/%06d.ts playlist-location=/path/to/your/webserver/playlist.m3u8 max-files=30 target-duration=6 playlist-length=20
en_USEnglish