b5i / YouTubeKit

A way to interact with YouTube's API in Swift (without any API key!)
https://swiftpackageindex.com/b5i/YouTubeKit
MIT License
83 stars 8 forks source link

downloadFormats does not contain tracks that contain both audio AND video #5

Closed ldenoue closed 12 months ago

ldenoue commented 12 months ago

Other libraries for NodeJS such as https://github.com/fent/node-ytdl-core are somehow able to return URLs that contain both audio and video info (and they support range requests, making downloading them very fast since we can request ranges in parallel).

But here downloadFormats only seems to contain either video or audio tracks.

Do you know how this could be solved?

Thank you!

b5i commented 12 months ago

Hello, thanks for your interest in YouTubeKit! I’m already currently working on the implementation of range requests for the download formats! (It should be added soon)

b5i commented 12 months ago

Other libraries for NodeJS such as https://github.com/fent/node-ytdl-core are somehow able to return URLs that contain both audio and video info (and they support range requests, making downloading them very fast since we can request ranges in parallel).

But here downloadFormats only seems to contain either video or audio tracks.

Do you know how this could be solved?

Thank you!

But if you only want to download in parts without having the need of knowing the video time interval their data represent, you can use (for example) the code of this answer that works well for the download formats provided by YouTubeKit.

b5i commented 12 months ago

I’m going to investigate about formats that have both audio and video data, during that time, you can create an AVMutableComposition that contains both tracks, and then download it (or download the 2 then merge them together).

ldenoue commented 12 months ago

@b5i ok but why is it that the ytdl library seems to be able to retrieve a downloadable video+audio? Why would we have to download each track independently and merge them? I didn't see merging happening in their source code. Could it be that they use a special User-Agent https://github.com/fent/node-ytdl-core/blob/9e15c7381f1eba188aba8b536097264db6ad3f7e/lib/info.js#L57C7-L58C6 that makes YouTube server somehow return different streamingData?

b5i commented 12 months ago

@b5i ok but why is it that the ytdl library seems to be able to retrieve a downloadable video+audio? Why would we have to download each track independently and merge them? I didn't see merging happening in their source code. Could it be that they use a special User-Agent https://github.com/fent/node-ytdl-core/blob/9e15c7381f1eba188aba8b536097264db6ad3f7e/lib/info.js#L57C7-L58C6 that makes YouTube server somehow return different streamingData?

They might be using the default formats of YouTube (the non-adaptative ones, those in streamingData.formats extracted here), I’m going to check if those actually have both audio and video (very likely I think) data and then implement the scrapping of those into the concerned responses. (I will also test the user agent thing but I’m not sure about this hypothesis)

b5i commented 12 months ago

I can confirm that those "default formats" contain both video and audio (original audio language if there is more than one), I think that this is the formats that YouTube uses to download videos in their mobile apps (with YouTube premium). I added the decoding of those "default formats" in this commit, they allow you to download videos at a higher speed than the adaptative ones. Let me know if it worked for you and if you have any other question!

ldenoue commented 12 months ago

@b5i yes that's it! Now the downloadFormats usually contains 2 entries in mp4: one 360p and one 720p. And like you said, these are fast to download with range requests! May I add a further request: the ability to get the width and height in the struct, so we can sort and return the resolution we want?

b5i commented 12 months ago

May I add a further request: the ability to get the width and height in the struct, so we can sort and return the resolution we want?

Isn't this already available in the VideoDownloadFormat struct?

ldenoue commented 12 months ago

@b5i yes you're right, I just had to cast DownloadFormat down to VideoDownloadFormat and I could find the width and height. Too me a little time to figure out the trick. Thank you for this amazing lib, the videos found in the new defaultFormats are indeed downloading fast and contain audio+video tracks. Fantastic!