Improving regex for parsing YouTube / Vimeo URLs

瘦欲@ 提交于 2019-11-28 18:50:45

I am not sure about your question 3), but provided that your induction on the url forms is correct, the regexes can be combined into one as follows:

/http:\/\/(?:www.)?(?:(vimeo).com\/(.*)|(youtube).com\/watch\?v=(.*?)&)/

You will get the match under different positions (1st and 2nd matches if vimeo, 3rd and 4th matches if youtube), so you just need to handle that.

Or, if you are quite sure that vimeo's id only includes numbers, then you can do:

/http:\/\/(?:www.)?(vimeo|youtube).com\/(?:watch\?v=)?(.*?)(?:\z|&)/

and the provider and the id will apprear under 1st and 2nd match, respcetively.

Here's my attempt at the regex, which covers most updated cases:

function parseVideo(url) {
    // - Supported YouTube URL formats:
    //   - http://www.youtube.com/watch?v=My2FRPA3Gf8
    //   - http://youtu.be/My2FRPA3Gf8
    //   - https://youtube.googleapis.com/v/My2FRPA3Gf8
    // - Supported Vimeo URL formats:
    //   - http://vimeo.com/25451551
    //   - http://player.vimeo.com/video/25451551
    // - Also supports relative URLs:
    //   - //player.vimeo.com/video/25451551

    url.match(/(http:\/\/|https:\/\/|)(player.|www.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com))\/(video\/|embed\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/);
    var type = null;
    if (RegExp.$3.indexOf('youtu') > -1) {
        type = 'youtube';
    } else if (RegExp.$3.indexOf('vimeo') > -1) {
        type = 'vimeo';
    }

    return {
        type: type,
        id: RegExp.$6
    };
}

Regex is wonderfully terse but can quickly get complicated.

http://jsfiddle.net/8nagx2sk/

function parseYouTube(str) {
    // link : //youtube.com/watch?v=Bo_deCOd1HU
    // share : //youtu.be/Bo_deCOd1HU
    // embed : //youtube.com/embed/Bo_deCOd1HU

    var re = /\/\/(?:www\.)?youtu(?:\.be|be\.com)\/(?:watch\?v=|embed\/)?([a-z0-9_\-]+)/i; 
    var matches = re.exec(str);
    return matches && matches[1];
}

function parseVimeo(str) {
    // embed & link: http://vimeo.com/86164897

    var re = /\/\/(?:www\.)?vimeo.com\/([0-9a-z\-_]+)/i;
    var matches = re.exec(str);
    return matches && matches[1];
}

Sometimes simple code is nicer to your fellow developers.

https://jsfiddle.net/1dzb5ag1/

// protocol and www neutral
function getVideoId(url, prefixes) {
  var cleaned = url.replace(/^(https?:)?\/\/(www\.)?/, '');
  for(var i = 0; i < prefixes.length; i++) {
    if (cleaned.indexOf(prefixes[i]) === 0)
      return cleaned.substr(prefixes[i].length)
  }
  return undefined;
}

function getYouTubeId(url) {
  return getVideoId(url, [
    'youtube.com/watch?v=',
    'youtu.be/',
    'youtube.com/embed/',
    'youtube.googleapis.com/v/'
  ]);
}

function getVimeoId(url) {
  return getVideoId(url, [
    'vimeo.com/',
    'player.vimeo.com/'
  ]);
}

Which do you prefer to update?

Here is my regex

http://jsfiddle.net/csjwf/1/

about sawa's answer :

a little update on the second regex :

/http:\/\/(?:www\.)?(vimeo|youtube)\.com\/(?:watch\?v=)?(.*?)(?:\z|$|&)/

(escaping the dots prevents from matching url of type www_vimeo_com/… and $ added…)

here is the same idea for matching the embed urls :

/http:\/\/(?:www\.|player\.)?(vimeo|youtube)\.com\/(?:embed\/|video\/)?(.*?)(?:\z|$|\?)/

For Vimeo, Don't rely on Regex as Vimeo tends to change/update their URL pattern every now and then. As of October 2nd, 2017, there are in total of six URL schemes Vimeo supports.

https://vimeo.com/*
https://vimeo.com/*/*/video/*
https://vimeo.com/album/*/video/*
https://vimeo.com/channels/*/*
https://vimeo.com/groups/*/videos/*
https://vimeo.com/ondemand/*/*

Instead, use their API to validate vimeo URLs. Here is this oEmbed (doc) API which takes an URL, checks its validity and return a object with bunch of video information(check out the dev page). Although not intended but we can easily use this to validate whether a given URL is from Vimeo or not.

So, with ajax it would look like this,

var VIMEO_BASE_URL = "https://vimeo.com/api/oembed.json?url=";
var yourTestUrl = "https://vimeo.com/23374724";


$.ajax({
  url: VIMEO_BASE_URL + yourTestUrl,
  type: 'GET',
  success: function(data) {
    if (data != null && data.video_id > 0)
      // Valid Vimeo url
    else
      // not a valid Vimeo url
  },
  error: function(data) {
    // not a valid Vimeo url
  }
});

3) Your regex does not match https url's. I haven't tested it, but I guess the "http://" part would become "http(s)?://". Note that this would change the matching positions of the provider and id.

Just in case here is a php version

/*
* parseVideo
* @param (string) $url 
* mi-ca.ch 27.05.2016
* parse vimeo & youtube id
* format url for iframe embed 
* https://regex101.com/r/lA0fP4/1
*/

function parseVideo($url) {
  $re = "/(http:|https:|)\\/\\/(player.|www.)?(vimeo\\.com|youtu(be\\.com|\\.be|be\\.googleapis\\.com))\\/(video\\/|embed\\/|watch\\?v=|v\\/)?([A-Za-z0-9._%-]*)(\\&\\S+)?/"; 
preg_match($re, $url, $matches);

if(strrpos($matches[3],'youtu')>-1){
    $type='youtube';
    $src='https://www.youtube.com/embed/'.$matches[6];
}else if(strrpos($matches[3],'vimeo')>-1){
    $type="vimeo";
    $src='https://player.vimeo.com/video/'.$matches[6];
}else{
    return false;
}


return array(
         'type' =>  $type // return youtube or vimeo
        ,'id'   =>  $matches[6] // return the video id
        ,'src'  =>  $src // return the src for iframe embed
        );
} 

I based myself the previous answers but I needed more out the regex.

Maybe it worked in 2011 but in 2019 the syntax has changed a bit. So this is a refresh.

The regex will allow us to detect weather the url is Youtube or Vimeo. I've added Capture group to easily retrieve the videoID.

If ran with Case insensitive setting please remove the (?i).

(?:(?i)(?:https:|http:)?\/\/)?(?:(?i)(?:www\.youtube\.com\/(?:embed\/|watch\?v=)|youtu\.be\/|youtube\.googleapis\.com\/v\/)(?<YoutubeID>[a-z0-9-_]{11,12})|(?:vimeo\.com\/|player\.vimeo\.com\/video\/)(?<VimeoID>[0-9]+))

https://regex101.com/r/PVdjg0/2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!