After months of work, and procrastination, I’m glad to present to you the latest incarnation of my torrent streaming technology – TorrentFlix!
TorrentFlix is a Node application, built with WebTorrent, Express, jQuery, FFmpeg, and some other technologies. It’s completely open source, licensed under the GNU Public License version 3.
TorrentFlix is available for download right now, on Github – here. Pull requests and contributions are welcome!
- Download the zip of the repository from Github or clone the git repository
- Install the dependencies with “npm install”
- Start the application with “npm start”
- Open the browser to http://localhost:9111/ and try it out :)
How it works?
The application is powered by Express which serves as the core router of the application. The frontend is served by “serve-static” of Express, and written in HTML5, CSS and jQuery. No other fancy frameworks used.
When you add a torrent, it get’s processed by “parse-torrent” and we extract the infoHash. We then construct the generic magnet URI with the most popular trackers. Then we call WebTorrent, add the torrent, and send a response back to the client.
By this time timer was set which will trigger every second. It will check if there are any torrents which weren’t accessed in the last 30 minutes, and remove them, to save on storage space and CPU usage, and of course, bandwidth. This is very greedy behavior, but for my own home connection it’s satisfactory (it’s only 2Mbps upload).
After the page receives a successful response from the server, it then lists the files in the torrent and renders that to the page. When you click a file, we try to detect whether it’s a video file or any other type of file. For other types we just open a new tab and force a download.
For video files, we open a video player in a frame and try to transcode the video.
The player first requests metadata for the video, to determine it’s length. The metadata endpoint calls ffprobe on the raw download URL, and serializes the response.
After we get the duration, we trick VideoJS into thinking the video is complete by overriding the internal duration methods. We also override the seek method so when the user seeks we load a new URI but keep the duration.
We then load the transcode endpoint, which in background opens the raw URI and starts FFmpeg which starts transcoding the video into a preset quality (720p, 480p, 360p, 240p or 144p, depending on the power of the computer the app is running on) and outputs the video to the browser, which plays it.
When you seek, we stop the current request, and load a new video with a start parameter that tells FFmpeg to seek to the position we want and play from that position, but because of our override the duration won’t change and the user will not know that we changed the video and began transcoding again.
After you abandon a video, you can either stop it explicitly, or just wait for 30 minutes and it’ll get deleted automatically.
Video which is in queue but not playing doesn’t use any CPU power, and only uses a moderate amount of network.
Seeding is disabled completely, you only upload data while downloading to ensure the maximum download speed.
A video which showcases the app is embedded below:
In my next post I am going to go line by line and explain in-depth how the app functions and why I made it the way I did.