YouTube Video ID From URL - Swift or Objective-C
Solution 1
So a YouTube URL looks something like:
http://www.youtube.com/watch?v=oHg5SJYRHA0
The video ID you're interested in is the part at the end (oHg5SJYRHA0
).... though it's not necessarily at the end, as YouTube URLs can contain other parameters in the query string.
Your best bet is probably to use a regular expression and Foundation's NSRegularExpression
class. I'd presume this approach is used in the other-language tutorials you've found -- note that the content of regular expressions is pretty much the same in any language or toolkit which includes them, so any regex found in those tutorials should work for you. (I'd advise against your approach of breaking on v=
and taking exactly 11 characters, as this is prone to various modes of failure to which a regex is more robust.)
To find the video ID you might want a regex like v=([^&]+)
. The v=
gets us to the right part of the query URL (in case we get something like watch?fmt=22&v=oHg5SJYRHA0
). The parentheses make a capture group so we can extract only the video ID and not the other matched characters we used to find it, and inside the parentheses we look for a sequence of one or more characters which is not an ampersand -- this makes sure we get everything in the v=whatever
field, and no fields after it if you get a URL like watch?v=oHg5SJYRHA0&rel=0
.
Whether you use this or another regex, it's likely that you'll be using capture groups. (If not, rangeOfFirstMatchInString:options:range:
is just about all you need, as seen in Dima's answer.) You can get at the contents of capture groups (as NSTextCheckingResult
objects) using firstMatchInString:options:range:
or similar methods:
NSError *error = NULL;
NSRegularExpression *regex =
[NSRegularExpression regularExpressionWithPattern:@"?.*v=([^&]+)"
options:NSRegularExpressionCaseInsensitive
error:&error];
NSTextCheckingResult *match = [regex firstMatchInString:youtubeURL
options:0
range:NSMakeRange(0, [youtubeURL length])];
if (match) {
NSRange videoIDRange = [match rangeAtIndex:1];
NSString *substringForFirstMatch = [youtubeURL substringWithRange:videoIDRange];
}
Solution 2
Here is RegExp it cover these cases
Objective C
- (NSString *)extractYoutubeIdFromLink:(NSString *)link {
NSString *regexString = @"((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)";
NSRegularExpression *regExp = [NSRegularExpression regularExpressionWithPattern:regexString
options:NSRegularExpressionCaseInsensitive
error:nil];
NSArray *array = [regExp matchesInString:link options:0 range:NSMakeRange(0,link.length)];
if (array.count > 0) {
NSTextCheckingResult *result = array.firstObject;
return [link substringWithRange:result.range];
}
return nil;
}
Swift
func extractYoutubeIdFromLink(link: String) -> String? {
let pattern = "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)"
guard let regExp = try? NSRegularExpression(pattern: pattern, options: .CaseInsensitive) else {
return nil
}
let nsLink = link as NSString
let options = NSMatchingOptions(rawValue: 0)
let range = NSRange(location: 0,length: nsLink.length)
let matches = regExp.matchesInString(link as String, options:options, range:range)
if let firstMatch = matches.first {
return nsLink.substringWithRange(firstMatch.range)
}
return nil
}
Swift 3
func extractYoutubeIdFromLink(link: String) -> String? {
let pattern = "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)"
guard let regExp = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) else {
return nil
}
let nsLink = link as NSString
let options = NSRegularExpression.MatchingOptions(rawValue: 0)
let range = NSRange(location: 0, length: nsLink.length)
let matches = regExp.matches(in: link as String, options:options, range:range)
if let firstMatch = matches.first {
return nsLink.substring(with: firstMatch.range)
}
return nil
}
Solution 3
After spending ages trying to find the correct syntax for the regex, I've come across this which has helped me.
NSString *regexString = @"(?<=v(=|/))([-a-zA-Z0-9_]+)|(?<=youtu.be/)([-a-zA-Z0-9_]+)";
Taken from here. This works for the following URL formats:
- www.youtube.com/v/VIDEOID - www.youtube.com?v=VIDEOID - http://www.youtube.com/watch?v=KFPtWedl7wg&feature=youtu.be - http://www.youtube.com/watch?v=MkTD2Y4LXcM - youtu.be/KFPtWedl7wg_U923 - http://www.youtube.com/watch?feature=player_detailpage&v=biVLGTAMC_U#t=31s
Solution 4
The tutorials you are probably seeing are just instructions on how to use regular expressions, which is also what you want to use in this case.
The Cocoa class you will need to use is NSRegularExpression.
Your actual regex string will depend on the format you are expecting the url to be in since it looks like youtube has several. The general function will look something like:
+ (NSString *)extractYoutubeID:(NSString *)youtubeURL
{
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"your regex string goes here" options:NSRegularExpressionCaseInsensitive error:&error];
NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:youtubeURL options:0 range:NSMakeRange(0, [youtubeURL length])];
if(!NSEqualRanges(rangeOfFirstMatch, NSMakeRange(NSNotFound, 0)))
{
NSString *substringForFirstMatch = [youtubeURL substringWithRange:rangeOfFirstMatch];
return substringForFirstMatch;
}
return nil;
}
Solution 5
Based on this answer: PHP Regex to get youtube video ID?
I adapted a regex for c/objc/c++ string, the important part here is that the regex doesn't get videos from facebook or other services. iOS regex is based on: ICU
NSString *regexString = @"^(?:http(?:s)?://)?(?:www\\.)?(?:m\\.)?(?:youtu\\.be/|youtube\\.com/(?:(?:watch)?\\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)/))([^\?&\"'>]+)";
NSError *error;
NSRegularExpression *regex =
[NSRegularExpression regularExpressionWithPattern:regexString
options:NSRegularExpressionCaseInsensitive
error:&error];
NSTextCheckingResult *match = [regex firstMatchInString:message
options:0
range:NSMakeRange(0, [message length])];
if (match && match.numberOfRanges == 2) {
NSRange videoIDRange = [match rangeAtIndex:1];
NSString *videoID = [message substringWithRange:videoIDRange];
return videoID;
}
Matches:
- youtube.com/v/vidid
- youtube.com/vi/vidid
- youtube.com/?v=vidid
- youtube.com/?vi=vidid
- youtube.com/watch?v=vidid
- youtube.com/watch?vi=vidid
- youtu.be/vidid
- youtube.com/embed/vidid
- http://youtube.com/v/vidid
- http://www.youtube.com/v/vidid
- https://www.youtube.com/v/vidid
- youtube.com/watch?v=vidid&wtv=wtv
- http://www.youtube.com/watch?dev=inprogress&v=vidid&feature=related
- https://m.youtube.com/watch?v=vidid
Does not match:
- www.facebook.com?wtv=youtube.com/v/vidid
- https://www.facebook.com/video.php?v=10155279523025107
Related videos on Youtube
Comments
-
The Man over 1 year
I have a Youtube url as an
NSString
or SwiftString
, but I need to extract the video id that is displayed in the url. I found many tutorials on how to do this in php or and other web-based programming languages, but none in Objective-C or Swift for Apple platforms...I'm looking for a method that asks for an NSString url as the parameter and returns the video id as another NSString...
-
eternalmatt almost 12 yearsYou could supply an example URL and what you have tried.
-
-
Dima almost 12 yearsupdated because I agree, but in general it doesn't matter here.
-
João Nunes about 11 yearsThis worked for me, just to mention that uou ned to access to the range number 0 to get it: NSRange videoIDRange = [match rangeAtIndex:0]; NSString *videoID = [message substringWithRange:videoIDRange];
-
GangstaGraham almost 11 yearsDis be da cooolest answer evaaa! If it was combined with dat Dima homie's answer
-
Alex over 7 years@AlmasAdilbek, it's just an example, it is working and you can change it static or convert to String extension, it's up to you
-
Ravi Panchal about 7 yearsthere is still some case where this regex is not working so here is the new regex pattern use this.@"(?<=watch\\?v=|/videos/|embed\\/|youtu.be\\/|\\/v\\/|\\/e\\/|watch\\?v%3D|watch\\?feature=player_embedded&v=|%2Fvideos%2F|embed%\u200C\u200B2F|youtu.be%2F|%2Fv%2F)[^#\\&\\?\\n]*"
-
Alex about 7 years@ravi.p can you give me an example when this regex is not working?