XCDYouTubeKit icon indicating copy to clipboard operation
XCDYouTubeKit copied to clipboard

Error XCDYouTubeVideoErrorDomain -2 when i try open video

Open Dem909 opened this issue 3 years ago • 23 comments

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 avatar Jul 22 '21 13:07 Dem909

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

Dem909 avatar Jul 22 '21 13:07 Dem909

yes, it does not work anymore

toyinswift avatar Jul 22 '21 13:07 toyinswift

And now what i can do? :)

Dem909 avatar Jul 22 '21 13:07 Dem909

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.

cbg-dev-k avatar Jul 23 '21 08:07 cbg-dev-k

Ah shit, here we go again

ardavydov avatar Jul 24 '21 05:07 ardavydov

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}" }

someziggyman avatar Jul 24 '21 08:07 someziggyman

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

armendh avatar Jul 24 '21 14:07 armendh

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

SirCochese avatar Jul 25 '21 00:07 SirCochese

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

Return error "Precondition check failed" :(

Dem909 avatar Jul 25 '21 18:07 Dem909

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 avatar Jul 25 '21 19:07 Dem909

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

Dem909 avatar Jul 25 '21 21:07 Dem909

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.

SirCochese avatar Jul 25 '21 21:07 SirCochese

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!

Dem909 avatar Jul 26 '21 00:07 Dem909

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.

Kiu212 avatar Jul 26 '21 02:07 Kiu212

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

444ten avatar Jul 26 '21 08:07 444ten

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

cbg-dev-k avatar Jul 26 '21 11:07 cbg-dev-k

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

tkachV avatar Jul 26 '21 15:07 tkachV

need a fix :'(

HaKKeBeilHaRRy avatar Jul 29 '21 08:07 HaKKeBeilHaRRy

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.

cbg-dev-k avatar Jul 29 '21 13:07 cbg-dev-k

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

HaKKeBeilHaRRy avatar Jul 30 '21 07:07 HaKKeBeilHaRRy

anyone got the solution ??

FazilMuhammed avatar Jul 31 '21 10:07 FazilMuhammed

Hello guys, someone got the solution?

MaurixFx avatar Aug 04 '21 14:08 MaurixFx

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

dredscabral avatar Feb 02 '22 16:02 dredscabral