Skip to content
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

Updated repo with all fixes so far, including slow download #552

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

cbg-dev-k
Copy link

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 cbg-dev-k changed the title Updated repo with all fixes so far Updated repo with all fixes so far, including slow download Oct 21, 2021
@zhengyanWork
Copy link

@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.

@cbg-dev-k
Copy link
Author

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.

@kunalsood
Copy link

@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;
        }
    }
}

@cbg-dev-k
Copy link
Author

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.

@kunalsood
Copy link

kunalsood commented Nov 16, 2021

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?

@cbg-dev-k
Copy link
Author

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)) }
		} ?? []
	}
}

@kunalsood
Copy link

Awesome! Thanks.

@cbg-dev-k
Copy link
Author

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 :)

@mkwitko
Copy link

mkwitko commented Feb 4, 2022

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

@vrdriver
Copy link

vrdriver commented Apr 24, 2022

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

@cbg-dev-k
Copy link
Author

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 :/

@vrdriver
Copy link

vrdriver commented Apr 25, 2022

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.

Copy link

@aluco100 aluco100 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants