Youtube Video Id from URL - Swift3

后端 未结 8 2308
眼角桃花
眼角桃花 2021-02-15 12:52

Basically I have a Youtube URL as string, I want to extract the video Id from that URL. I found some code in objective c that is as below:

NSError *error = NULL;         


        
相关标签:
8条回答
  • 2021-02-15 13:21

    Safer version (without force unwrapping !):

    extension String {
        var youtubeID: String? {
            let pattern = "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)"
    
            let regex = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive)
            let range = NSRange(location: 0, length: count)
    
            guard let result = regex?.firstMatch(in: self, range: range) else {
                return nil
            }
    
            return (self as NSString).substring(with: result.range)
        }
    }
    

    Examples:

    "https://www.youtube.com/watch?v=C0DPdy98e4c".youtubeID // "C0DPdy98e4c"
    "https://youtube.com/watch?v=C0DPdy98e4c".youtubeID // "C0DPdy98e4c"
    "www.youtube.com/watch?v=C0DPdy98e4c".youtubeID // "C0DPdy98e4c"
    "youtube.com/watch?v=C0DPdy98e4c".youtubeID // "C0DPdy98e4c"
    
    "https://youtu.be/C0DPdy98e4c".youtubeID // "C0DPdy98e4c"
    "youtu.be/C0DPdy98e4c".youtubeID // "C0DPdy98e4c"
    

    Credits: Usman Nisar's answer

    0 讨论(0)
  • 2021-02-15 13:22

    Your first problem is you are not escaping ? in your expression. ? is reserved character and if you want to use it in your expressions, you must escape with \ and since \ is used also to escape " character you must escape ? with double backslash something like \\?. So according to above information, following code correctly extracts the videoId

    let youtubeURL = "https://www.youtube.com/watch?v=uH8o-JTHJdM"
    let regex = try! NSRegularExpression(pattern: "\\?.*v=([^&]+)", options: .caseInsensitive)
    let match = regex.firstMatch(in: youtubeURL, options: [], range: NSRange(location: 0, length: youtubeURL.characters.count))
    if let videoIDRange = match?.rangeAt(1) {
        let substringForFirstMatch = (youtubeURL as NSString).substring(with: videoIDRange)
    } else {
        //NO video URL
    }
    
    0 讨论(0)
  • 2021-02-15 13:22

    Swift 5

    var youtubeURLs = [
        "http://www.youtube.com/watch?v=-wtIMTCHWuI",
        "http://www.youtube.com/v/-wtIMTCHWuI?version=3&autohide=1",
        "http://youtu.be/-wtIMTCHWuI",
        "http://www.youtube.com/oembed?url=http%3A//www.youtube.com/watch?v%3D-wtIMTCHWuI&format=json",
        "https://youtu.be/uJ2PZaO1N5E",
        "https://www.youtube.com/embed/M7lc1UVf-VE",
        "http://www.youtube.com/attribution_link?a=JdfC0C9V6ZI&u=%2Fwatch%3Fv%3DEhxJLojIE_o%26feature%3Dshare",
        "https://www.youtube.com/attribution_link?a=8g8kPrPIi-ecwIsS&u=/watch%3Fv%3DyZv2daTWRZU%26feature%3Dem-uploademail"
    ]
    
    func getVideoID(from urlString: String) -> String? {
        guard let url = urlString.removingPercentEncoding else { return nil }
        do {
            let regex = try NSRegularExpression.init(pattern: "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)", options: .caseInsensitive)
            let range = NSRange(location: 0, length: url.count)
            if let matchRange = regex.firstMatch(in: url, options: .reportCompletion, range: range)?.range {
                let matchLength = (matchRange.lowerBound + matchRange.length) - 1
                if range.contains(matchRange.lowerBound) &&
                    range.contains(matchLength) {
                    let start = url.index(url.startIndex, offsetBy: matchRange.lowerBound)
                    let end = url.index(url.startIndex, offsetBy: matchLength)
                    return String(url[start...end])
                }
            }
        } catch {
            print(error.localizedDescription)
        }
        return nil
    }
    
    for url in youtubeURLs {
        print("Video id: \(getVideoID(from: url) ?? "NA") for url: \(url)")
    }
    

    Result:

    Video id: -wtIMTCHWuI for url: http://www.youtube.com/watch?v=-wtIMTCHWuI
    Video id: -wtIMTCHWuI for url: http://www.youtube.com/v/-wtIMTCHWuI?version=3&autohide=1
    Video id: -wtIMTCHWuI for url: http://youtu.be/-wtIMTCHWuI
    Video id: -wtIMTCHWuI for url: http://www.youtube.com/oembed?url=http%3A//www.youtube.com/watch?v%3D-wtIMTCHWuI&format=json
    Video id: uJ2PZaO1N5E for url: https://youtu.be/uJ2PZaO1N5E
    Video id: M7lc1UVf-VE for url: https://www.youtube.com/embed/M7lc1UVf-VE
    Video id: EhxJLojIE_o for url: http://www.youtube.com/attribution_link?a=JdfC0C9V6ZI&u=%2Fwatch%3Fv%3DEhxJLojIE_o%26feature%3Dshare
    Video id: yZv2daTWRZU for url: https://www.youtube.com/attribution_link?a=8g8kPrPIi-ecwIsS&u=/watch%3Fv%3DyZv2daTWRZU%26feature%3Dem-uploademail
    
    0 讨论(0)
  • 2021-02-15 13:23

    I have a different way of doing this using URLComponents. You then just select the 'v' parameter from the url, if it exists.

    func getYoutubeId(youtubeUrl: String) -> String? {
        return URLComponents(string: youtubeUrl)?.queryItems?.first(where: { $0.name == "v" })?.value
    }
    

    And then pass in a Youtube url like this:

    print (getYoutubeId(youtubeUrl: "https://www.youtube.com/watch?v=Y7ojcTR78qE&spfreload=9"))
    
    0 讨论(0)
  • 2021-02-15 13:30

    To get video Id from Youtube Url, use code # Swift4 :

    var videoId = ""
    
        if youtubeLink.lowercased().contains("youtu.be"){
                linkString = youtubeLink
                if let range = linkString.range(of: "be/"){
                    videoId = youtubeLink[range.upperBound...].trimmingCharacters(in: .whitespaces)
                }
            }
            else if youtubeLink.lowercased().contains("youtube.com"){
                linkString = youtubeLink
                if let range = linkString.range(of: "?v="){
                    videoId = youtubeLink[range.upperBound...].trimmingCharacters(in: .whitespaces)
                }
            }
    

    Hope will be helping! :)

    0 讨论(0)
  • 2021-02-15 13:31

    A Swift 4 version using the elegant flatMap:

    func extractYouTubeId(from url: String) -> String? {
        let typePattern = "(?:(?:\\.be\\/|embed\\/|v\\/|\\?v=|\\&v=|\\/videos\\/)|(?:[\\w+]+#\\w\\/\\w(?:\\/[\\w]+)?\\/\\w\\/))([\\w-_]+)"
        let regex = try? NSRegularExpression(pattern: typePattern, options: .caseInsensitive)
        return regex
            .flatMap { $0.firstMatch(in: url, range: NSMakeRange(0, url.count)) }
            .flatMap { Range($0.range(at: 1), in: url) }
            .map { String(url[$0]) }
    }
    

    This method uses a regex that detects most of the possible YouTube URL formats (.be/*, /embed/, /v/ - you can find the full list here).

    0 讨论(0)
提交回复
热议问题