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

[BUG] - I cannot download the YouTube videos from some video stream URLs #44

Open
DanielCrompton123 opened this issue Jun 3, 2024 · 6 comments

Comments

@DanielCrompton123
Copy link

I am using a function to download a video at a specific URL which relies on YouTubeKit:

    func download(to directoryURL: URL) async {
        downloading = true
        defer { downloading = false }
        
        // Make sure the URL exists
        if videoURL.isEmpty {
            error = "Please provide a URL"
            return
        }
        guard let url =  URL(string: videoURL) else {
            error = "Could not parse you input to a URL"
            return
        }
        
        // Make the YouTube video
        let video = YouTube(url: url)
        guard let videoTitle = try? await video.metadata?.title else {
            self.error = "Could not get video title"
            return
        }
        // get the streams and filter for highest resolution
        do {
            let streams = try await video.streams
            
            guard let stream = audioOnly ? streams.highestAudioBitrateStream() : streams.highestResolutionStream() else {
                self.error = "Could not get the highest stream resolution"
                return
            }
            
            // Download the video
            let url = stream.url
            print("URL is \(url.absoluteString)")
            
            do {
                let (data, _) = try await URLSession.shared.data(from: url)
                let fileURL = directoryURL.appendingPathComponent(videoTitle, conformingTo: audioOnly ? .mpeg4Audio : .mpeg4Movie)
                print("File URL = \(fileURL.relativePath)")
                try! data.write(to: fileURL)
                print("SUCCESS!")
            } catch {
                self.error = "Could not write the video data to disk"
            }
            
        } catch {
            self.error = "Could not get video streams"
        }
    }

However when videoURL = "https://www.youtube.com/watch?v=byrRbWGN1Nk&t=2s" the url links gives me a 403 code which of course means the video cannot be downloaded.

However with other videos, eg: https://www.youtube.com/watch?v=kOf54RdoH7A the video will download.

You mentioned this project corresponds somewhat with Pytube for Python: I tested the same (broken) video URL with Pytube on Python and the video URLs both libraries gave were similar but different.
Here is the video URL from YouTubeKit (https://www.youtube.com/watch?v=byrRbWGN1Nk&t=2s): https://rr4---sn-cu-h5oe7.googlevideo.com/videoplayback?expire=1717471505&ei=sTReZu2JGLXYxN8P9IStmAc&ip=2a00%3A23c6%3A8916%3A4601%3A3ccd%3A97d2%3A584%3Ab609&id=o-AMh2onJ7kBeM1TcBSzEH3AHwi3RxBvc1g5MIfnOf5w_f&itag=313&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C248%2C271%2C278%2C313&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=na&mm=31%2C29&mn=sn-cu-h5oe7%2Csn-cu-auod&ms=au%2Crdu&mv=m&mvi=4&pcm2cms=yes&pl=44&initcwndbps=2188750&bui=AbKP-1OvLtwCb4L6dwT1GMEbkK3ZrL7X3gxm7Jk2uN3SPgdGh3yM2NERxfv-OI8gbvJZsqTLa-8SccZ_&spc=UWF9fxsIyYb90o96SI929OsJfiC5ftcu7cmAbYWrLrXY1meJws4thG_mk5sC&vprv=1&svpuc=1&mime=video%2Fwebm&ns=c1SX90TtWbl62x8S5MhcphYQ&rqh=1&gir=yes&clen=41458899&dur=251.920&lmt=1634000891472896&mt=1717449442&fvip=4&keepalive=yes&c=WEB&sefc=1&txp=6216224&n=G66MYAPZ87IsYsFCO&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cspc%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhAMO0Pdosml7oxsuppKGIpKLSussPwkE7nwdrtEVXBNyFAiEA2EKgHHo4d0MUPosLPhHQZryODpoMejeeHDj1yNr_F9k%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpcm2cms%2Cpl%2Cinitcwndbps&lsig=AHlkHjAwRgIhAPNn3zf-pAHhlEGjbsrVn7fjeWZ0fOVcUepyieRln2iMAiEAuHEKzTdThDUEtTrWVe64qgB6GWv-DFsAZZJcOXn9YWM%3D and here it is from Pytube: https://rr4---sn-cu-h5oe7.googlevideo.com/videoplayback?expire=1717471554&ei=4jReZrKbB8eKmLAPm-u2qAQ&ip=2a00%3A23c6%3A8916%3A4601%3A3ccd%3A97d2%3A584%3Ab609&id=o-ANagADo5V_Hh4UtyXzzaZEFTX4S4ekFAI4OaX1uxc1L9&itag=22&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=na&mm=31%2C29&mn=sn-cu-h5oe7%2Csn-cu-auod&ms=au%2Crdu&mv=m&mvi=4&pcm2cms=yes&pl=44&initcwndbps=2191250&bui=AbKP-1MGBozmWktaGcxs8nIzz7TRKbdAbxOSv-yL2rwxjGZlrF2wxZLfga6IxX3NSWnT47RiiUXRARtC&vprv=1&mime=video%2Fmp4&rqh=1&cnr=14&ratebypass=yes&dur=251.982&lmt=1634000896163657&mt=1717449687&fvip=4&c=ANDROID_EMBEDDED_PLAYER&txp=6211224&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Cmime%2Crqh%2Ccnr%2Cratebypass%2Cdur%2Clmt&sig=AJfQdSswRQIhAJ1MSgLtyxWxLnQobNiRgFntwlN3p-oJ0RzqPxHknq4zAiBcbtfpxkSFvMYRtmMl2JyFp9KfhpXkOIDZRAm5fy_TCw%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpcm2cms%2Cpl%2Cinitcwndbps&lsig=AHlkHjAwRQIgdi5NBPdmU2IOAQCFBTY_2Mr_kZLFu3NUh1aZ9jICM1cCIQCgrRs5TdeaLnJ4wq40U9Ni8nPgOJQ6qONtLzWwdJ67Zw%3D%3D.

Hope this helps.

@garfbargle
Copy link

garfbargle commented Jun 13, 2024

Getting something similar and for links that were previously working.

YouTube(url: url, methods: [.local, .remote])

pattern (ytplayer.config\s*=\s*) failed: The operation couldn’t be completed. (YouTubeKit.YouTubeKitError error 1.)

@garfbargle
Copy link

image
Test Case '-[YouTubeKitTests.PlayabilityTests testHDRStreamNativePlayability]' started.
Skipping player response from client 1. Got player response for nil instead of njX2bu-_Vw4
applying descrambler
finding initial function name
Failed to decode object from given start point: The data couldn’t be read because it isn’t in the correct format.
pattern (ytplayer.config\s*=\s*) failed: The operation couldn’t be completed. (YouTubeKit.YouTubeKitError error 1.)
signature found, skip decipher

Connection 3: received failure notification
nw_flow_add_write_request [C3 66.241.125.190:443 failed parent-flow (satisfied (Path is satisfied), interface: utun7, ipv4, dns)] cannot accept write requests
nw_write_request_report [C3] Send failed with error "Socket is not connected"
nw_flow_add_write_request [C3 66.241.125.190:443 failed parent-flow (satisfied (Path is satisfied), interface: utun7, ipv4, dns)] cannot accept write requests
nw_write_request_report [C3] Send failed with error "Socket is not connected"
nw_connection_add_timestamp_locked_on_nw_queue [C62] Hit maximum timestamp count, will start dropping events

@chaojiezheng
Copy link

I am using a function to download a video at a specific URL which relies on YouTubeKit:

    func download(to directoryURL: URL) async {
        downloading = true
        defer { downloading = false }
        
        // Make sure the URL exists
        if videoURL.isEmpty {
            error = "Please provide a URL"
            return
        }
        guard let url =  URL(string: videoURL) else {
            error = "Could not parse you input to a URL"
            return
        }
        
        // Make the YouTube video
        let video = YouTube(url: url)
        guard let videoTitle = try? await video.metadata?.title else {
            self.error = "Could not get video title"
            return
        }
        // get the streams and filter for highest resolution
        do {
            let streams = try await video.streams
            
            guard let stream = audioOnly ? streams.highestAudioBitrateStream() : streams.highestResolutionStream() else {
                self.error = "Could not get the highest stream resolution"
                return
            }
            
            // Download the video
            let url = stream.url
            print("URL is \(url.absoluteString)")
            
            do {
                let (data, _) = try await URLSession.shared.data(from: url)
                let fileURL = directoryURL.appendingPathComponent(videoTitle, conformingTo: audioOnly ? .mpeg4Audio : .mpeg4Movie)
                print("File URL = \(fileURL.relativePath)")
                try! data.write(to: fileURL)
                print("SUCCESS!")
            } catch {
                self.error = "Could not write the video data to disk"
            }
            
        } catch {
            self.error = "Could not get video streams"
        }
    }

However when videoURL = "https://www.youtube.com/watch?v=byrRbWGN1Nk&t=2s" the url links gives me a 403 code which of course means the video cannot be downloaded.

However with other videos, eg: https://www.youtube.com/watch?v=kOf54RdoH7A the video will download.

You mentioned this project corresponds somewhat with Pytube for Python: I tested the same (broken) video URL with Pytube on Python and the video URLs both libraries gave were similar but different. Here is the video URL from YouTubeKit (https://www.youtube.com/watch?v=byrRbWGN1Nk&t=2s): https://rr4---sn-cu-h5oe7.googlevideo.com/videoplayback?expire=1717471505&ei=sTReZu2JGLXYxN8P9IStmAc&ip=2a00%3A23c6%3A8916%3A4601%3A3ccd%3A97d2%3A584%3Ab609&id=o-AMh2onJ7kBeM1TcBSzEH3AHwi3RxBvc1g5MIfnOf5w_f&itag=313&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C248%2C271%2C278%2C313&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=na&mm=31%2C29&mn=sn-cu-h5oe7%2Csn-cu-auod&ms=au%2Crdu&mv=m&mvi=4&pcm2cms=yes&pl=44&initcwndbps=2188750&bui=AbKP-1OvLtwCb4L6dwT1GMEbkK3ZrL7X3gxm7Jk2uN3SPgdGh3yM2NERxfv-OI8gbvJZsqTLa-8SccZ_&spc=UWF9fxsIyYb90o96SI929OsJfiC5ftcu7cmAbYWrLrXY1meJws4thG_mk5sC&vprv=1&svpuc=1&mime=video%2Fwebm&ns=c1SX90TtWbl62x8S5MhcphYQ&rqh=1&gir=yes&clen=41458899&dur=251.920&lmt=1634000891472896&mt=1717449442&fvip=4&keepalive=yes&c=WEB&sefc=1&txp=6216224&n=G66MYAPZ87IsYsFCO&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cspc%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhAMO0Pdosml7oxsuppKGIpKLSussPwkE7nwdrtEVXBNyFAiEA2EKgHHo4d0MUPosLPhHQZryODpoMejeeHDj1yNr_F9k%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpcm2cms%2Cpl%2Cinitcwndbps&lsig=AHlkHjAwRgIhAPNn3zf-pAHhlEGjbsrVn7fjeWZ0fOVcUepyieRln2iMAiEAuHEKzTdThDUEtTrWVe64qgB6GWv-DFsAZZJcOXn9YWM%3D and here it is from Pytube: https://rr4---sn-cu-h5oe7.googlevideo.com/videoplayback?expire=1717471554&ei=4jReZrKbB8eKmLAPm-u2qAQ&ip=2a00%3A23c6%3A8916%3A4601%3A3ccd%3A97d2%3A584%3Ab609&id=o-ANagADo5V_Hh4UtyXzzaZEFTX4S4ekFAI4OaX1uxc1L9&itag=22&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=na&mm=31%2C29&mn=sn-cu-h5oe7%2Csn-cu-auod&ms=au%2Crdu&mv=m&mvi=4&pcm2cms=yes&pl=44&initcwndbps=2191250&bui=AbKP-1MGBozmWktaGcxs8nIzz7TRKbdAbxOSv-yL2rwxjGZlrF2wxZLfga6IxX3NSWnT47RiiUXRARtC&vprv=1&mime=video%2Fmp4&rqh=1&cnr=14&ratebypass=yes&dur=251.982&lmt=1634000896163657&mt=1717449687&fvip=4&c=ANDROID_EMBEDDED_PLAYER&txp=6211224&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Cmime%2Crqh%2Ccnr%2Cratebypass%2Cdur%2Clmt&sig=AJfQdSswRQIhAJ1MSgLtyxWxLnQobNiRgFntwlN3p-oJ0RzqPxHknq4zAiBcbtfpxkSFvMYRtmMl2JyFp9KfhpXkOIDZRAm5fy_TCw%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpcm2cms%2Cpl%2Cinitcwndbps&lsig=AHlkHjAwRQIgdi5NBPdmU2IOAQCFBTY_2Mr_kZLFu3NUh1aZ9jICM1cCIQCgrRs5TdeaLnJ4wq40U9Ni8nPgOJQ6qONtLzWwdJ67Zw%3D%3D.

Hope this helps.

Solve it?

@alexeichhorn
Copy link
Owner

I pushed some fixes. Can you try again with the current main branch.

@DanielCrompton123
Copy link
Author

DanielCrompton123 commented Jun 22, 2024

Hey thanks for responding. I tried again with this function:

    func download(to url: URL) async {
        // 1. Ensure that the URL entered by the user is valid
        if videoURL.isEmpty {
            error = "Please provide a URL"
            return
        }
        
        // 2. Make a URL
        guard let url = URL(string: videoURL) else {
            error = "Could not parse entered text into a URL"
            return
        }
        
        // 2. Make the video object
        let video = YouTube(url: url)
        
        // 3. Find the correct stream & title
        guard
            let stream = try? await audioOnly ? video.streams.highestAudioBitrateStream() : video.streams.highestResolutionStream(),
            let title = try? await video.metadata?.title else {
            self.error = "Error funding the correct stream"
            return
        }
        
        // 4. Find video output URL
        let outputUrl = url.appendingPathComponent(title, conformingTo: audioOnly ? .mpeg4Audio : .mpeg4Movie)
        
        // Download the video
        guard let data = try? Data(contentsOf: stream.url),
              data.count > 0 else {
            print("Error making data with contents of the URL: \(stream.url)")
            return
        }
        try? data.write(to: outputUrl)
    }

And this video URL: https://www.youtube.com/watch?v=qaR9Dl56eHk which the program game me stream.url as: https://rr4---sn-cu-h5oe7.googlevideo.com/videoplayback?expire=1719096681&ei=CQF3ZvfCMrmuvdIP_8qlyAo&ip=2a00%3A23c6%3A8916%3A4601%3Af0cf%3A4cca%3A81ca%3A7b5e&id=o-AHDYMWrGnwU2vUxA92t9MHs7u_KjA5rVKuKVsdKDK2xI&itag=308&aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C308&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=xY&mm=31%2C29&mn=sn-cu-h5oe7%2Csn-cu-auod&ms=au%2Crdu&mv=m&mvi=4&pcm2cms=yes&pl=41&initcwndbps=1893750&bui=AbKP-1M1TBH_2lr2GwovpHIBmcgE2Swi3X2X_9Aeaa9OLU4sCm0balS_hB5SOOIU8fLJDU3QhduKF4Bj&spc=UWF9fwyrXpM0jpeGLIeHUIzAhqdkVuv5Hljvj81gPO6L8oZhDhj0O44mtteP&vprv=1&svpuc=1&mime=video%2Fwebm&ns=k5ZQLXFyuoxKwEDJra95ZmAQ&rqh=1&gir=yes&clen=68649338&dur=52.485&lmt=1669982161214493&mt=1719074701&fvip=4&keepalive=yes&c=WEB&sefc=1&txp=5319224&n=UlPCfw5bWF6Qf7JYb2&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cspc%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIhAK0N-1pe1f5D2trXjDxsFNc8XEl9s2J8qwVcCKqo3EBYAiANT5sDaqpPuUFfH1YkCa6QsqjZ0DV-99g90fynlBsKOA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpcm2cms%2Cpl%2Cinitcwndbps&lsig=AHlkHjAwRQIgWzhi3AVw4hEts5uYvdugVaxO0afmC6xQXaWCaCtvh8ICIQCxVV1B38nX0R4Qj2cT4ssijRjHGvhGKnLWPL9xLyCMCg%3D%3D

However when I make data from the URL retrieved, Data is nil.

Furthermore, when I print the stream.url and copy it in Chrome, it says 404, access denied. I looked at the other linked issue however I am downloading the highest resolution so cannot tell if 360p works.

Thanks, Dan.

@garfbargle
Copy link

@alexeichhorn Your new changes fixed remote url extraction for large videos for me. It also fixed local extraction for both small and large videos. :) Thank you! I believe there was a bug before (not sure about now) where even if I had local extraction priority, and remote as 2nd priority, it wouldn't do remote extraction (because it would download a video with no data and think it succeeded.)

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

4 participants