Although BitTorrent (BT) protocol was not designed for media streaming, in practice it can be used, with certain extent, to stream a video file from P2P network. Key trick is to force sequential download in BT client (normally BT client selects first pieces, that are least available in swarm, which contributes to better distribution of the file, sequential download is playing against it, so it is not enabled in regular BT clients).
But if we force BT client to download sequentially, cache incoming pieces and have enough incoming bandwidth from peers, we can stream incoming video directly into video player. Indeed it’s a poor man streaming, because it lacks any advanced features like stream synchronization, stream seeking etc., but in many cases it works just good enough.
There is also project BitTorrent Live where BT protocol inventor Bram Cohen comes with enhancement of BT protocol to enable media streaming. This project started at 2011, but it seems to be bit stalled now. (for curious here is link to US patent for BitTorrent Live – P2P Live Streaming).
There has been also some academic research in this area (paper1 , paper2 ), proposing improvement to BT protocol to help with video streaming, focusing mainly on modifications to piece selection mechanism in client, where pieces are split into 3 sets:
- pieces before current play point in file are either not downloaded or are seeded if they were downloaded before
- a small set of pieces including and immediately after current play point (priority set) – are downloaded with highest priority and utilizing preferably high speed peers
- remaining pieces (after priority set) – are downloaded with normal priority, sequentially or even can use regular rarest fist piece selection.
I’ve tested couple of available applications available, which work with standard BT protocol, but use sequential download and piece prioritization to stream video file:
acestream – is not open source, so I did not spent too much time with it but it generally works,
All these clients are working in similar fashion – there is separate BT client process, that uses sequential mode to download torrent and as pieces are downloaded it streams them via HTTP protocol to video player. Playback starts, when ‘enough’ data is cached – in XBMCTorrent it was 1% of torrent size.
As I noted all solutions somehow works, but they are bit heavy-weighted, I’d tried something simple on my own and created simple streaming BTClient in Python . It uses excellent libtorrent library, which enables to do sequential downloads and advanced pieces prioritization. BTClient is a command line utility – it can open either torrent file, or open link to torrent file or magnetic link. It then reads torrent metadata, selects largest video file in the torrent and starts it’s sequential download. After it caches about 1% of the file it starts video player (mplayer or VLC) and streams video to it via HTTP (or stdin, but seek is not supported then) . While playing BTClient shares torrent and provides uploads to other peers. Seeking in the video file is supported.
libtorrent provides several ways, how to influence pieces selection:
- sequential download – this can be set for whole torrent
- pieces prioritization – priority can be set to individual pieces – from 0 (piece is not downloaded) to 7 (highest priority)
- piece deadline – when piece is prioritized, it means only that it starts with priority, but it does not mean that it’ll be finished before non-prioritized pieces. If piece is downloaded from slow peers, it can easily end after non-prioritized pieces. If setting piece a deadline ( a time in future, when piece should be finished), libtorrent downloads piece’s blocks from fastest peers to meet the deadline.
BTClient leverages all above methods to achieve responsive video streaming:
- only pieces for video file are downloaded (other files pieces are set to priority 0)
- sequential download is set for the torrent
- pieces before last seek point have priority set to 0 (so they will not be started, if have not been started or downloaded already)
- piece at last seek/read point and it’s 5 successors have highest priority and deadline set
- remaining pieces are downloaded with normal priority
- get tail of the file at beginning – it helps with quick video player start (because both mplayer and VLC look at be video file ending before they start to play it). It is also used to search for subtitles (opensubtitles are using file hash from first and last 64kB of the file for search)
- Player control (to pause if there are no data to send – DBus ?)
- MPlayer OSD?
- Use Mplayer in slave mode via API?
- Custom player via gstreamer (this can provide much closer integration between BT client pieces prioritization and playback)
- GTK3 GUI?