A Peer-to-Peer Live Video Streaming Library built on WebTorrent
We built Nile.js, a peer-to-peer live video streaming library designed to handle scaling. Our library uses WebTorrent, a distributed file delivery protocol inspired by BitTorrent and built with WebRTC. We chose WebTorrent as our means of broadcasting the stream because video streams can get progressively stronger as more peers join the stream. This also makes it a better fit than implementing typical WebRTC peer connections due to the approximately 10 to 20 connection limit per peer that WebTorrent has been able to mitigate.
How we use WebTorrent to stream
First, torrent files used by WebTorrent are immutable, making it less than ideal for live streaming. To emulate streaming, we take the video stream and split it into clips that are distributed to viewers through their own generated torrent files.
Once the WebTorrent client begins to seed, a magnet link (an identifier in the form of a string) is generated. We propagate the magnet to the viewing peers through a series of WebSocket and WebRTC connections. The magnet is first passed to a Node/Express server which is connected to a limited number of WebSockets. The server emits the magnet to the initial WebSocket connections which pass the magnet along through WebRTC peers in a linked list structure. After receiving the magnet, each viewer client will begin to leech (download) and seed (upload) the stream.
Because of the linked list structure of our WebSocket to WebRTC connection, if a peer disconnects, the chain would be broken. Our library is designed to automatically reconnect on service disruptions. The disconnected webRTC peer will open a WebSocket connection with server, where it will be reassigned to a new WebSocket peer.
If there are only a few peers viewing the stream, initial upload speed is highly dependent on the broadcaster’s bandwidth and network speed, creating a major bottleneck. To offset this poor initial performance, we allowed the broadcaster enough time to send each peer enough data to view without missing a second. From this experience, we further acknowledge the effectiveness of combining peer-to-peer delivery with a CDN, a la Peer5, to handle the spectrum of low to high numbers of viewers.
As we rack up the number WebTorrent seeds on the broadcaster side, there seems to be a client side memory leak which eventually causes the browser to crash. We’ve checked the CPU and memory usage but have found no error messages or anomalies.
Unsuccessful approaches that we have taken to solve the issue:
- Server side seeding in place of client side seeding
- Seeding with Web Workers
- Seeding in iframes
- Destroying WebTorrent client on each new seed
- Destroying WebTorrent file on each new seed
One solution that we have found, is browser specific. If using Chrome Canary to test the library, it seems to run indefinitely. If anyone in the open source community is able to provide some insight, please make a pull request on our GitHub repo.