-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow http video streaming while downloading #12542
Conversation
IMO, it is another step on the way to make qBittorrent "bloatware". |
While it is a cool feature, unfortunately it doesn't really align with this project vision. It should be a good idea to maintain such a fork (on your side) and users could have more choices. |
Since QBittorrent isn't good with handling large number of torrents and "real" seeders will use a barebone libtorrent wrappers anyway. I think our target audience consists of casual torrenters. Utorrent and many other clients have this feature and at the end of the day, it's pretty useful for people who just use torrent for movies which is the majority. I personally use this a lot and had to use Web torrent until now and then shift my torrents to qBittorrent for seeding (don't want to use Utorrent). It would be quite useful for me if you guys let me get this in. I can help with maintenance.
I do this for fun and learning and maintaining a fork would be too much for me. Personally I think it would not be successful anyway, not many people run anything from the internet, I would never. I hope you guys will see it more from the user side. |
@jagannatharjun I need some clarification since the title is minimal an now description is given in the opening comment. And I am not going to look through all that code. What does this do? Does it stream local video files to someone connected to the qbt-machine via http? |
@jagannatharjun I think qbittorrent-nox has the potential of competing with the more barebones libtorrent wrappers. The WebAPI and WebUI just need a little more work. Anyway, I must say the purpose of this PR is also not entirely clear to me. What does this accomplish that is different from simply downloading sequentially and opening the file? I will build this and test it during the week to have a closer look, but I'd also appreciate a more detailed explanation. Thanks for the initiative anyway. |
Is it affecting GUI or WebUI? I think supporting more workload is always the goal for qbittorrent ;)
AFAIK it gives the user a URL for a movie file on server, and the user can open it with a media player and play it (and probably seek it). |
I have some "seeders" friends, they tend to use rtorrent or deluge for seedboxes. They imply that qbittorrent is too "heavy" for seedboxes and can't handle 100+ torrent. But that's a different debate. And I still stand by that our main user base is "normal" people, who just download torrents to watch movies and this feature would be very useful for this group of people.
Sorry about that. this lockdown is getting on my head🤦♂️ |
People using qbittorrent in a headless setting got the impression that it does not handle 100+ torrents well because they are most likely using the webUI, and for a long time the webUI was badly misusing the webAPI in a way that severely impacted performance. This was relatively recently fixed in #11635. Before that, just clicking around the WebUI would send more and more requests before the current one was complete, essentially DOS'ing the instance. Now, even on slow machines the experience is good with up to ~1000 torrents. After that, the steady performance degradation starts to become noticeable. A faster machine may still handle several thousands very well, but qBittorrent is definitely not capable yet of handling several thousands or 10k+ torrents in general with the current webAPI implementation. But the "10k" problem is another matter entirely.
👍 |
In that case I have to agree with @glassez and @Chocobo1. This is out of scope for a bittorrent client. Or at least for qBittorrent. It would be another story, if this was an optimization to serially download torrent pieces to facilitate "streaming" by simultaneously downloading a torrent and watching it. I am sorry that you did all this work, but we can't accept it. |
I respect your opinion, but most of the users don't run on servers but locally, not all features are useful for everyone but if it is useful for most of them, it should be considered. If I'm correct Utorrent has this since like 2011 |
But if they run it locally then why can't simply access the storage themselves? |
The main idea here is to provide seeking. |
Can you expand on that? Do you mean seeking a file from a multifile torrent or seeking inside a file? |
Seeking in video files while playing, This enables QBittorrent to download that part of the file which is currently playing in the video player. |
So somewhere in your code you implement this:
Right? |
In Http byte streaming, one can ask for the part of a file from the server through simple Http request, this is how this PR facilitates the streaming of file, The media player (client) provides us the range, and we provide the file back in the specified range by the following process :
basically this PR adds the ability to selectively and promptly download the currently needed chunk of the file by the media player.
yes, they won't be able to seek if they were to directly open from disk, they should open it from the provided URL. |
Whenever a user requests to "stream a file", we provide an Http URL, if that URL is opened with media player, we follow http byte serving protocol and serve the file in this manner
|
@jagannatharjun thanks for the clarifications. Are the seeked pieces still saved on disk, same as any other piece? If so, this seems like it could be a straight improvement over simply downloading sequentially - the files get saved all the same, but with this method the user has the freedom to seek around while playing, outside of strict sequential order. |
yes, they are still saved, there is no difference from that end. |
After the explanation/clarification given in the previous comments I can see that this feature might be useful to some users. Now I am not entirely against it. Does anyone else feel like this is ok to add? |
Current Implementation works but doesn't follow RFC fully. Had to reimplement a large part of it and I don't think I can use @glassez @Chocobo1 any chance of getting this in or should I close this PR 😊? |
It's a generally bad idea to make something universal if it ends up being equally bad for everyone. If it can't be equally good, it's better to have different implementations for different tasks. |
The problem is that all clients actually request whole file in a single request, so then I have to store the connection for a very long time send response in chunks, this is bit difficult with the current setup of Http::Server and Http::Connection. moreover, I have to do this in asynchronous manner Also with this response, I assume you approve this feature 😊, will continue working on it. |
...if it "looks nice" in the end (not as something "alien", breaking code design and unmaintainable). |
13038cc
to
539a288
Compare
539a288
to
24d25fe
Compare
with the latest push, This PR is complete specification wise and "works". So if anyone wants to try out they can do it by downloading files from Github action or compiling themselves. PS: I may not able to complete it for review till next year. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to start dealing with this PR, but there are so many Coding Style violations here that I'm starting to get bogged down in it... Could you get it ready for review first?
, m_torrentHandle(torrentHandle) | ||
{ | ||
const BitTorrent::TorrentInfo info = m_torrentHandle->info(); | ||
m_name = info.name() + '/' + info.fileName(fileIndex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not m_name = info.fileName(fileIndex);
? Or even m_name = torrentHandle->fileName(fileIndex);
@@ -328,6 +328,7 @@ void SearchWidget::on_searchButton_clicked() | |||
QString tabName = pattern; | |||
tabName.replace(QRegularExpression("&{1}"), "&&"); | |||
m_ui->tabWidget->addTab(newTab, tabName); | |||
//m_ui->tabWidget->setTabsClosable(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like unrelated changes...
@@ -64,7 +64,8 @@ void ProgressBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o | |||
|
|||
QStyleOptionProgressBar newopt; | |||
newopt.initFrom(&m_dummyProgressBar); | |||
newopt.rect = option.rect; | |||
static_cast<QStyleOption &>(newopt) = static_cast<const QStyleOption &>(option); | |||
newopt.palette = m_dummyProgressBar.palette(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like unrelated changes...
using QTcpServer::QTcpServer; | ||
|
||
void start(); | ||
private: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add empty line above.
#include <QTcpSocket> | ||
#include <QElapsedTimer> | ||
|
||
#include "../indexrange.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use base/indexrange.h
and so on.
#include "../indexrange.h" | ||
#include "../http/types.h" | ||
|
||
class HttpSocket : public QObject |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to put this class into separate files.
|
||
StreamFile *StreamingManager::findFile(int fileIndex, BitTorrent::TorrentHandle *torrentHandle) const | ||
{ | ||
const auto fileIter = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong coding style.
Please use the following:
const auto fileIter = std::find_if(m_files.begin(), m_files.end()
, [fileIndex, torrentHandle](const StreamFile *file)
{
return file->isSameFile(fileIndex, torrentHandle);
});
m_files.remove(m_files.indexOf(file)); | ||
}); | ||
} | ||
QProcess::startDetached(vlcPath(), {url(file)}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, what is it for?
connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentAboutToBeRemoved, file, [this, torrentHandle, file](BitTorrent::TorrentHandle *handle) | ||
{ | ||
if (handle == torrentHandle) | ||
m_files.remove(m_files.indexOf(file)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it a memory leak?
@@ -47,6 +47,13 @@ namespace BitTorrent | |||
class InfoHash; | |||
class TrackerEntry; | |||
|
|||
struct PieceFileInfo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this structure describe? Index of what? Start of what? Length of what?
Thanks for taking a look, but this is not ready for review, I and my friends are actually using this in our builds for the last couple of months and I know of a couple of edge cases I have to deal with. I actually submit this work as my minor project this semester :), I will probably open a new PR when it's complete. I should be able to complete this by mid-January. Until then I'm leaving this open just in case if anyone wants to try it out. |
This PR is stale because it has been 60 days with no activity. This PR will be automatically closed within 7 days if there is no further activity. |
This PR was closed because it has been stalled for some time with no activity. |
It basically provides the user with an HTTP URL, which can be played with any video player that allows users to watch movies and seek while a file is downloading. Internally it uses HTTP byte serving.
with this QBittorrent is almost "complete" for me 😊