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

Error XCDYouTubeVideoErrorDomain -2 when i try open video #544

Open
Dem909 opened this issue Jul 22, 2021 · 23 comments
Open

Error XCDYouTubeVideoErrorDomain -2 when i try open video #544

Dem909 opened this issue Jul 22, 2021 · 23 comments

Comments

@Dem909
Copy link

Dem909 commented Jul 22, 2021

when i try to open any video it returns an error XCDYouTubeVideoErrorDomain, Code: -2

Before that, other tips from other discussions helped, but now something new :(

@Dem909
Copy link
Author

Dem909 commented Jul 22, 2021

This brunch helped me

pod 'XCDYouTubeKit', :git => 'https://github.com/dpwilhelmsen/XCDYouTubeKit', :branch => 'hotfix/fix-get-video-info-error', submodules: true

But i just replace 2 files
https://github.com/dpwilhelmsen/XCDYouTubeKit/blob/hotfix/fix-get-video-info-error/XCDYouTubeKit/XCDYouTubeVideoOperation.m

https://github.com/dpwilhelmsen/XCDYouTubeKit/blob/hotfix/fix-get-video-info-error/XCDYouTubeKit/XCDYouTubeVideoWebpage.m

It's working one time, now not work

@toyinswift
Copy link

yes, it does not work anymore

@Dem909
Copy link
Author

Dem909 commented Jul 22, 2021

And now what i can do? :)

@cbg-dev-k
Copy link

I'm seeing the same issue here.

When using a VPN to the US, videos still play. Maybe it's related to the consent cookie tweak we've had to implement before? That only affected non-US clients I believe.

@ardavydov
Copy link

Ah shit, here we go again

@someziggyman
Copy link

Maybe this can help:
https://stackoverflow.com/questions/67615278/get-video-info-youtube-endpoint-suddenly-returning-404-not-found/67629882#67629882

There's a new answer named UPDATE (July 2021)

POST: https://youtubei.googleapis.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8

with the body :

{
"context": {
"client": {
"hl": "en",
"clientName": "WEB",
"clientVersion": "2.20210721.00.00",
"mainAppWebInfo": {
"graftUrl": "/watch?v={VIDEO_ID}"
}
}
},
"videoId": "{VIDEO_ID}"
}

@armendh
Copy link

armendh commented Jul 24, 2021

the above mentioned fix seems to work
checkout #545

the innertube api key is hardcoded and we don't know how long it will last so it is recommended to scrap the api key from youtube and set it via XCDYouTubeClient.setInnertubeApiKey

func scrapInnertubeApiKey(){
    let link = "https://www.youtube.com"
    Alamofire.request(link).responseString { (response) in  // network lib https://github.com/Alamofire/Alamofire
        if let html = response.value {
            if let doc = try? HTML(html: html, encoding: .utf8) {   // HTML parser https://github.com/tid-kijyun/Kanna
                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
        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)) }
        } ?? []
    }
}

@SirCochese
Copy link

I can confirm the post method works, but the response schema is different than the current get_video_info. So, I think there are some meaningful changes required to get this working from within XCDYouTubeKit. In case it helps anyone in the short-term, here's snippet from my swift app. But I started needing to re-implement some of the signature stuff inside XCDYouTubeKit, and decided to slow my roll.

Note that postToUrl is a shared helper which is pretty simple, so left out here for brevity.

func getVideoUrl(videoId: String, completion: @escaping ([UInt:String]) -> Void) {
	let infoParams: [String: Any] = [
		"graftUrl": "/watch?v=\(videoId)"
	]
	let clientParams: [String: Any] = [
		"hl": "en",
		"clientName": "WEB",
		"clientVersion": "2.20210721.00.00",
		"mainAppWebInfo": infoParams
	]
	let contextParams: [String: Any] = [
		"client": clientParams
	]
	let parameters: [String: Any] = [
		"context": contextParams,
		"videoId": videoId
	]
	
	postToUrl(urlStr: "https://youtubei.googleapis.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8", parameters: parameters, commandCompletion: { (data, response, error) in
		var streamURLs: [UInt:String] = [:]
		
		//let dataString = String(decoding: data!, as: UTF8.self)
		//STLog(logStr: dataString)
		
		if  let data = data,
		    let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
		    let streamingData = json["streamingData"] as? [String: Any],
			let formats = streamingData["formats"] as? [[String: Any]] {
				for format in formats
				{
					if let itag = format["itag"] as? UInt
					{
						if let url = format["url"] as? String {
							streamURLs[itag] = url
						}
						else if let signatureCipher = format["signatureCipher"] as? String,
								let queryDict = signatureCipher.queryDictionary,
								let url = queryDict["url"],
								let sig = queryDict["s"] {
							// TODO: twiddle the signature, should likely do this in XCDYouTubeKit
							streamURLs[itag] = url
						}
					}
				}
			}
		
		completion(streamURLs)
	})
}

@Dem909
Copy link
Author

Dem909 commented Jul 25, 2021

Note that postToUrl is a shared helper which is pretty simple, so left out here for brevity.

Return error "Precondition check failed" :(

@Dem909
Copy link
Author

Dem909 commented Jul 25, 2021

the above mentioned fix seems to work
checkout #545

the innertube api key is hardcoded and we don't know how long it will last so it is recommended to scrap the api key from youtube and set it via XCDYouTubeClient.setInnertubeApiKey

func scrapInnertubeApiKey(){
    let link = "https://www.youtube.com"
    Alamofire.request(link).responseString { (response) in  // network lib https://github.com/Alamofire/Alamofire
        if let html = response.value {
            if let doc = try? HTML(html: html, encoding: .utf8) {   // HTML parser https://github.com/tid-kijyun/Kanna
                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
        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)) }
        } ?? []
    }
}

Looks good, but the problem is that at my stage
if let text = doc.xpath("//script[contains(., 'INNERTUBE_API_KEY')]/text()").first?.text {
does not return anything, and a screen with the YouTube privacy policy is displayed in the doc. content

But i tested key "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8" - he is work, but Privacy Policy blocked all and video not returned(

@Dem909
Copy link
Author

Dem909 commented Jul 25, 2021

When i try get video info, google return this:

<NSHTTPURLResponse: 0x283dae420> { URL: https://youtubei.googleapis.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8 } { Status Code: 404, Headers { "Alt-Svc" = ( "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\"" ); "Content-Encoding" = ( br ); "Content-Length" = ( 138 ); "Content-Type" = ( "application/json; charset=UTF-8" ); Date = ( "Sun, 25 Jul 2021 21:16:49 GMT" ); Server = ( ESF ); Vary = ( Origin, "X-Origin", Referer ); "x-content-type-options" = ( nosniff ); "x-frame-options" = ( SAMEORIGIN ); "x-xss-protection" = ( 0 ); } }

@SirCochese
Copy link

Note that postToUrl is a shared helper which is pretty simple, so left out here for brevity.

Return error "Precondition check failed" :(

I saw that, you need to make sure that the content type is application/json and you don't percent encode it.

@Dem909
Copy link
Author

Dem909 commented Jul 26, 2021

Note that postToUrl is a shared helper which is pretty simple, so left out here for brevity.

Return error "Precondition check failed" :(

I saw that, you need to make sure that the content type is application/json and you don't percent encode it.

It's... work...

I hope this doesn't sound weird, but I love you, thank you very much! :)
You helped a lot, because the application in the store began to pour out, users complained and real hell began for me ... You really saved me, thanks!

@Kiu212
Copy link

Kiu212 commented Jul 26, 2021

I followed the code in #545, but still getting XCDYouTubeVideoErrorDomain -2 for upcoming live stream video.
This is no doubt that if the problem solved, this will be the perfect fix.
Any idea for this? Thanks.

@444ten
Copy link

444ten commented Jul 26, 2021

@Kiu212 +1
Addition. This problem is specific to the European Region

@cbg-dev-k
Copy link

cbg-dev-k commented Jul 26, 2021

After combining #545 with the changes I already had locally (consent cookie etc), it started playing videos again in europe.

When I try a livestream however, the POST works but youtubekit fails to play the stream. The log eventually notifies that a request went timeout. Anyone else seeing this?

The timeout error:
[XCDYouTubeKit] URL GET operation finished with error: The request timed out. Domain: NSURLErrorDomain Code: -1001 User Info: { NSErrorFailingURLKey = "https://r9---sn-uxaxoxu-cg0r.googlevideo.com/videoplayback?expire=1627321020&ei=XJ7-YIKUIYKx1wK-2pCADw&ip=2a02%3A1810%3Aa418%3Af700%3A38fc%3Aa27c%3Aa8bc%3A63e6&id=DWcJFNfaw9c.3&itag=243&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C248%2C278&source=yt_live_broadcast&requiressl=yes&mh=Ms&mm=44%2C29&mn=sn-uxaxoxu-cg0r%2Csn-5hnekn7d&ms=lva%2Crdu&mv=u&mvi=9&pl=45&pcm2=yes&vprv=1&live=1&hang=1&noclen=1&mime=video%2Fwebm&ns=EtxyS696fTkFieyGVFLQZrAG&gir=yes&mt=1627298950&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466588&c=WEB&n=FSF8yu_YZ5HouZ&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cpcm2%2Cvprv%2Clive%2Chang%2Cnoclen%2Cmime%2Cns%2Cgir&sig=AOq0QJ8wRQIhAKPUVg1BS0dny9J4cVDhB57s1VBGBrZw2NppdaL-APesAiAU8b2kXbeM9iV-Yt_s4qMftNiJhNKDitq8M0FD6ESGMg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl&lsig=AG3C_xAwRgIhAI8vIV-EqXsXq0Y5zwdqvYYlrTKy3TqHoGRy0l4rXNJ5AiEAyspZ6SOPFDdQ-CnjDvqHl55kOAVMenro0IxH-jFdcoA%3D&ratebypass=yes"; NSErrorFailingURLStringKey = "https://r9---sn-uxaxoxu-cg0r.googlevideo.com/videoplayback?expire=1627321020&ei=XJ7-YIKUIYKx1wK-2pCADw&ip=2a02%3A1810%3Aa418%3Af700%3A38fc%3Aa27c%3Aa8bc%3A63e6&id=DWcJFNfaw9c.3&itag=243&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C248%2C278&source=yt_live_broadcast&requiressl=yes&mh=Ms&mm=44%2C29&mn=sn-uxaxoxu-cg0r%2Csn-5hnekn7d&ms=lva%2Crdu&mv=u&mvi=9&pl=45&pcm2=yes&vprv=1&live=1&hang=1&noclen=1&mime=video%2Fwebm&ns=EtxyS696fTkFieyGVFLQZrAG&gir=yes&mt=1627298950&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466588&c=WEB&n=FSF8yu_YZ5HouZ&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cpcm2%2Cvprv%2Clive%2Chang%2Cnoclen%2Cmime%2Cns%2Cgir&sig=AOq0QJ8wRQIhAKPUVg1BS0dny9J4cVDhB57s1VBGBrZw2NppdaL-APesAiAU8b2kXbeM9iV-Yt_s4qMftNiJhNKDitq8M0FD6ESGMg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl&lsig=AG3C_xAwRgIhAI8vIV-EqXsXq0Y5zwdqvYYlrTKy3TqHoGRy0l4rXNJ5AiEAyspZ6SOPFDdQ-CnjDvqHl55kOAVMenro0IxH-jFdcoA%3D&ratebypass=yes"; NSLocalizedDescription = "The request timed out."; NSUnderlyingError = "Error Domain=kCFErrorDomainCFNetwork Code=-1001 \"(null)\" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}"; "_NSURLErrorFailingURLSessionTaskErrorKey" = "LocalDataTask <2272A8E5-2351-4FC3-942F-980D3DCBAEC5>.<1>"; "_NSURLErrorRelatedURLSessionTaskErrorKey" = ( "LocalDataTask <2272A8E5-2351-4FC3-942F-980D3DCBAEC5>.<1>" ); "_kCFStreamErrorCodeKey" = "-2102"; "_kCFStreamErrorDomainKey" = 4; }

@tkachV
Copy link

tkachV commented Jul 26, 2021

I have same error... If someone have solution - pls share...
Thanks.

@HaKKeBeilHaRRy
Copy link

need a fix :'(

@cbg-dev-k
Copy link

Well damn, it seems I didn't apply one of the previous fixes and it came back to bite me.

The only missing code I needed was near line 173 in XCDYoutubeVideo.m:
if (httpLiveStream.length == 0) { httpLiveStream = info[@"streamingData"][@"hlsManifestUrl"]; }

Now both livestreams and past broadcasts are working for me.

@HaKKeBeilHaRRy
Copy link

no of the fixes works anymore (for me). it looks like it will only play videos randomly.

@FazilMuhammed
Copy link

anyone got the solution ??

@MaurixFx
Copy link

MaurixFx commented Aug 4, 2021

Hello guys, someone got the solution?

@dredscabral
Copy link

I was getting this error when I tried to pass the video url instead of the video id.

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

No branches or pull requests