XCDYouTubeKit icon indicating copy to clipboard operation
XCDYouTubeKit copied to clipboard

Updated repo with all fixes so far, including slow download

Open cbg-dev-k opened this issue 3 years ago • 12 comments

This PR contains all the fixes I had applied locally (from other comments on the repo) + a fix for the slow downloads

cbg-dev-k avatar Oct 21 '21 11:10 cbg-dev-k

@kbex-dev I have just tried your repo, and everything works well, except i can't get the thumbnail in the iOS demo. it says unsupported URL, please help.

zhengyanWork avatar Oct 22 '21 09:10 zhengyanWork

Hi @zhengyanWork, I'm using a different API to get video_info but didn't change the mapping provided by YoutubeKit. It's possible the thumbnail url was moved to another field and a change is needed on the Video model in this repo?

I'm sorry to say that this isn't a priority for my use case, I won't have time to look into it.

cbg-dev-k avatar Oct 22 '21 12:10 cbg-dev-k

@kbex-dev Thanks for this! To fix thumbnails, insert the following after Line 228 in XCDYouTubeVideo.m file :-

if (!thumbnails) {
    NSDictionary *thumbnailDictionary = videoDetails[@"thumbnail"];
    if (thumbnailDictionary && [thumbnailDictionary isKindOfClass:[NSDictionary class]]) {
        NSArray *thumbnailArray = thumbnailDictionary[@"thumbnails"];
        if (thumbnailArray && [thumbnailArray isKindOfClass:[NSArray class]]) {
            thumbnails = thumbnailArray;
        }
    }
}

kunalsood avatar Nov 16 '21 06:11 kunalsood

Hey @kunalsood, thanks for sharing.

I've added your code to the fork, though I haven't confirmed the fix. Hopefully it helps others needing those thumbnails.

cbg-dev-k avatar Nov 16 '21 09:11 cbg-dev-k

No worries @kbex-dev.

One question (since I haven't get been able to go through all the issues open about this, on this repo here): Where is the _innertubeApiKey here from? Is it an API key I generate for my own use? or is it safe to use the one already there?

kunalsood avatar Nov 16 '21 10:11 kunalsood

The default key is scraped from their website. I think you could create your own API key from a YT account, but I never bothered since we're not exactly following their terms of service :|

In my own codebase I occasionally scrape the YT website to see if the key was updated, but I think it's still the same.

Another gotcha is that their API expects a consent/gdpr cookie (at least when in Europe). This can also be mocked.

I'll add my own (Swift 5) implementation for both issues below as a reference:


import Alamofire
import Foundation
import Kanna
import XCDYouTubeKit

enum Hacks {
	static func provideYoutubeCookie() {
		guard let cookieStorage = Alamofire.SessionManager.default.session.configuration.httpCookieStorage else { return }
		let cookieName = "CONSENT"
		let cookieValue = "YES+cb.\(youtubeDateString)-17-p0.en+FX+\(Int.random(in: 101...998))"

		if let existingCookie = cookieStorage.cookies?.first(where: { $0.name == cookieName }),
		   existingCookie.value.contains("YES") {
			// existing cookie should be good
			return
		}
		let hackyYoutubeCookie = HTTPCookie(properties: [
			.domain: ".youtube.com",
			.path: "/",
			.name: cookieName,
			.value: cookieValue,
			.secure: "TRUE"
		])
		hackyYoutubeCookie.map { cookieStorage.setCookie($0) }
	}

	/// Using a recent date for consent cookie, in case youtube verifies this
	private static var youtubeDateString: String {
		let defaultDateString = "20210519"
		guard let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date()) else { return defaultDateString }
		return youtubeDateFormatter.string(from: yesterday)
	}

	private static let youtubeDateFormatter = DateFormatter().then {
		$0.locale = Locale(identifier: "en_US_POSIX")
		$0.dateFormat = "yyyyMMdd"
	}
}

extension Hacks {
	static func scrapeYoutubeApiKey() {
		Hacks.provideYoutubeCookie()

		let link = "https://www.youtube.com"
		Alamofire.request(link).responseString { response in
			if let html = response.value {
				if let doc = try? HTML(html: html, encoding: .utf8) {
					if let text = doc.xpath("//script[contains(., 'INNERTUBE_API_KEY')]/text()").first?.text {
						if let results = text.match("ytcfg.set\\((\\{.*?\\})\\)").last?.last {
							if let data = results.data(using: .utf8), let model = try? JSONDecoder().decode(InnertubeScrap.self, from: data) {
								let key = model.INNERTUBE_API_KEY
								XCDYouTubeClient.setInnertubeApiKey(key)
							}
						}
					}
				}
			}
		}
	}

	struct InnertubeScrap: Codable {
		let INNERTUBE_API_KEY: String
	}
}

extension String {
	func match(_ regex: String) -> [[String]] {
		let nsString = self as NSString
		// swiftlint:disable:next legacy_constructor
		return (try? NSRegularExpression(pattern: regex, options: []))?.matches(in: self, options: [], range: NSMakeRange(0, nsString.length)).map { match in
			(0..<match.numberOfRanges).map { match.range(at: $0).location == NSNotFound ? "" : nsString.substring(with: match.range(at: $0)) }
		} ?? []
	}
}

cbg-dev-k avatar Nov 16 '21 10:11 cbg-dev-k

Awesome! Thanks.

kunalsood avatar Nov 16 '21 10:11 kunalsood

The slow download issue seems to be popping up more and more for our users.

yt-dlp seems to handle it fine, but I'm having a hard time finding out what they do to fix it.

If anyone is feeling up for it, I'd happily accept PRs on my fork :)

cbg-dev-k avatar Feb 02 '22 10:02 cbg-dev-k

I'm having trouble with Iphone 8 without sound, anyone has seen this behavior?

mkwitko avatar Feb 04 '22 13:02 mkwitko

Hi @kbex-dev,

Thanks for the work you've done. Instead of deleting my original comments, I thought I'd just pass on what I'd done. Brilliant work! https://stephenmonro.wordpress.com/2022/04/13/getting-youtube-videos-to-play-again-in-ionic5/

Thanks, Steve

vrdriver avatar Apr 24 '22 11:04 vrdriver

Hi Steve

I'm glad you got it to work!

As a word of warning, these fixes aren't a complete solution. It worked for a while, but I've since received new reports about slow/stalled videos.

I haven't been able to fix those issues on this repo without a complete refactor to mimick youtubedl :/

cbg-dev-k avatar Apr 25 '22 08:04 cbg-dev-k

Well, it's much better than having them not working for the moment. :) Apparently it hasn't been working since last year... so I'll take the gamble and push an upload to the Apple App store. I'll keep you posted if I notice anything weird though.

vrdriver avatar Apr 25 '22 09:04 vrdriver