iv-org / invidious

Invidious is an alternative front-end to YouTube
https://invidious.io
GNU Affero General Public License v3.0
15.96k stars 1.75k forks source link

[Feature request] Download button #83

Closed narcolepticinsomniac closed 5 years ago

narcolepticinsomniac commented 6 years ago

I know it's as simple as right-click/save-as, but a download button would be a good look. Tbh, I don't even recall the last time I downloaded a YT vid, but seeing the option when YT goes out of their way to make it difficult is pretty satisfying.

I've played around a little with userscripts, and the best I could do was utilize GM_download, which converts to a blob. It works, but it'll be slow with larger files, and probably has limits size-wise. Most places I searched, the more reliable method consistently suggested would be on your end, using PHP.

dimqua commented 6 years ago

Should be also possible to download a video in selected quality (resolution and format).

elypter commented 5 years ago

it should be a setting for the admin so he can decide for his mirror.

omarroth commented 5 years ago

I'm not quite sure what you mean @elypter, you'll have to clarify. As an update to this, I plan on adding a download button similar to Hooktube's, where you can select one of the streams to download. I'm also looking into automatically muxing video and audio for 1080p and above, although that will require the client to have JS enabled.

elypter commented 5 years ago

i meant that someone who wants to use the source to host this project himself then that person should have the choice to add a download button or not. i personally would love to have a download button but some people might not be comfortable with it.

omarroth commented 5 years ago

That's an interesting thought. I'm wondering why someone would be uncomfortable with having a download button? It would serve the same files provided used by the player, and if they're hosting it they can always just pull out the code that provides the button.

elypter commented 5 years ago

in some peoples mind streaming and downloading are fundamentally different things, especially for politicians, although it is basically the same. i just think it is better turn those things into settings so you can update easily. its not a big deal, just a something that came to mind.

ghost commented 5 years ago

I created a userscript for Tampermonkey called Invidious Downloader which adds a download button next to the listen mode button. It requires Tampermonkey because of GM_download not existing in Greasemonkey and the one in Violentmonkey doesn't work with EventListeners.

dimqua commented 5 years ago

@erupete does it work for DASH videos, e.g. 1080p ones?

ghost commented 5 years ago

@dimqua not at the moment, only audio files and pre-muxed videos

omarroth commented 5 years ago

Looks good! Added to the list of extensions with 3a44cfd. The issue with DASH videos was the main delay in why this hasn't been added to the site itself. My plan is to use something like videojs/mux.js to combine the separate streams in the browser so that users don't need to use an external tool (e.g. ffmpeg).

mmarfil commented 5 years ago

@omarroth comimg here to give my 👍 too. I'd love to have an option to download either the mp3 or pre-muxed videos so I can listen/watch offline on my mobile device while on the go. Thanks for building Invidious by the way!

omarroth commented 5 years ago

Added with fb535ad6bba09359c176b0d0d7c9570cc873e41a.

Unfortunately there's no way (that I've found) to mux the audio and video streams in the browser in a way that can be downloaded by user. Currently you can download video-only, audio-only, or any of the pre-muxed versions. The default filename of the download is the same as the default template for youtube-dl, #{title}-#{id}.#{ext}, although currently ext will always be mp4. I expect this to be fixed soon.

This functionality relies on proxying videos through the site, so it's another test for how much bandwidth would likely be used for #34. Since the videos themselves are proxied, you should also be able to download videos that have region-blocks, see #92.

You will also likely need to do a hard refresh to pull updated versions of default.css and watch.js.

dimqua commented 5 years ago

@omarroth is it possible to implement this feature without proxying videos? And since the videos are proxied, can't them be pre-muxed on Invidious instance?

omarroth commented 5 years ago

CORS prevents loading resources directly from YouTube. As far as I am aware, the only way to implement this feature is by proxying everything.

I would rather not mux them server-side, since it's generally quite CPU and memory intensive.

dimqua commented 5 years ago

@omarroth does CloudTube and HookTube proxying them too?

elypter commented 5 years ago

could it work if both files were downloaded to localstorage and then merged? i think that is how those downloads on mega.nz work

omarroth commented 5 years ago

See a similar conversation on proxying in #177, which also links to explanations on how FreeTube and CloudTube do things.

HookTube now uses the embedded player after receiving a C&D from YouTube, so there's no need for it to proxy anything. It also never appeared to support higher than 720p, see the FAQ page at https://hooktube.com for an explanation why.

There's a difference between merging two chunks of data and muxing them in the way that is required here. I have yet to find a solution that is able to do that. MediaSources come very close, but they unfortunately are not able to extend to this use case, see w3c/media-source#209.

dimqua commented 5 years ago

@omarroth well, if CloudTube's approach isn't ideal for playing DASH videos, it probably doesn't mean it's bad for downloading them, right?

omarroth commented 5 years ago

I'm not quite sure what you're asking, but as far as I know it isn't possible to use that approach for downloading videos, since browsers have stricter controls on downloading media than they do on playing it.

omarroth commented 5 years ago

Since the original functionality has been implemented I'm going to close this. For pre-muxed versions or any extensions to this functionality I would recommend opening a new issue.

dimqua commented 5 years ago

as far as I know it isn't possible to use that approach for downloading videos

Ah, my bad, I thought CloudTube allows to download videos, but it doesn't.

But if I use Invidious with JS disabled, I can download videos (up to 720p) using direct links:

But I can't do the same using the 'Download' button. Also the button does not work without JS at all.

omarroth commented 5 years ago

Removed JS from download button with 1692f7640c74d83d909e121356b0f4c593c5ac59. It now proxies the direct links with Content-Disposition: attachment; filename=#{title}-#{id}.mp4.

narcolepticinsomniac commented 5 years ago

Why are src URLs obfuscated now? I had a simple little script to set a referrer policy so I could have a download button which opens the src URL, and triggers automatic downloads based on the referrer. Just noticed that it stopped working, and after checking why, I'm obviously getting no referrer because of this new redirect. What was the point of this?

omarroth commented 5 years ago

Would you mind clarifying or providing the script you're using? Are you referring to /latest_version or something else?

narcolepticinsomniac commented 5 years ago

Are you referring to /latest_version

Yeah. Used to be just a regular googlevideo src URL, because I was able to pass a referrer before the redirect was added.

Script relies on a userstyle as well:

https://pastebin.com/zC7t4qGS https://pastebin.com/PRpYmG8s

narcolepticinsomniac commented 5 years ago

Download button is for embeds only, obviously.

omarroth commented 5 years ago

The reason /latest_version is used is because googlevideo links expire after 6 hours, which creates issues when leaving the player idle (see #276). Additionally, in the case where an invalid URL is encountered, the player can reload to receive a fresh URL, for example when a server is unavailable or tries to serve an incomplete file.

Assuming you have an id and itag, you can use /latest_version?download_widget={"id":"#{id}","itag":"#{itag}","title":"#{desired title}"}, which will add Content-Disposition: to trigger download automatically.

narcolepticinsomniac commented 5 years ago

Guess those are some good reasons. I must not have tried to download anything in a while if that wasn't a recent change. The method I was using was super simple and used to work. I don't really know how to implement the workaround you're suggesting.

narcolepticinsomniac commented 5 years ago

Assuming you have an id and itag, you can use...

I did try this briefly previously, but I used the exact syntax provided in the example, minus the curly brackets where I inserted the correct strings. Wasn't working, so I got irritated and gave up on it. Finally got around to giving it another try, and removing the hashtags makes it work as advertised. Probably should've figured that just by looking at it. Anyway, cool feature, and thanks for the heads up.

narcolepticinsomniac commented 4 years ago

Assuming you have an id and itag, you can use...

I'm getting "Administrator has disabled this endpoint" now.

narcolepticinsomniac commented 4 years ago

@omarroth What's the word on this? Did you disable it intentionally, or can it be fixed?

omarroth commented 4 years ago

See #883. It's been disabled intentionally. I'll look into providing them in a way that doesn't use as much bandwidth.