Skip to content

Instantly share code, notes, and snippets.

@jschr
Last active February 8, 2024 05:57
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jschr/e98030e4e51c9fc243abf7052c762188 to your computer and use it in GitHub Desktop.
Save jschr/e98030e4e51c9fc243abf7052c762188 to your computer and use it in GitHub Desktop.
Parse YouTube URLs
import UrlPattern from 'url-pattern';
import qs from 'query-string';
// Returns YouTube Player API options from a YouTube URL.
// ie. { playlistId }
// { videoId, start, end }
// { query }
export default function parseYouTubeUrl(url) {
const [domain, querystring] = url.split('?');
const options = {};
const query = qs.parse(querystring);
if (query.list) {
// URLs with a playlist can also have a video id so we need to check
// for a playlist first.
// ie. https://www.youtube.com/watch?v=:videoId&list=:playlistId
options.playlistId = query.list;
} else if (query.v) {
// Check if the video id was provided in the query string.
// ie. https://www.youtube.com/watch?v=:videoId
options.videoId = query.v;
} else {
// Check for short urls, direct urls and embed urls.
// ie. https://youtu.be/:videoId
// https://www.youtube.com/v/:videoId
// https://www.youtube.com/embed/:videoId
const shortVideo = new UrlPattern('(http(s)\\://)(www.)youtu.be/:videoId');
const directVideo = new UrlPattern(
'(http(s)\\://)(www.)youtube.com/v/:videoId',
);
const embedVideo = new UrlPattern(
'(http(s)\\://)(www.)youtube.com/embed/:videoId',
);
let params = shortVideo.match(domain);
if (params) options.videoId = params.videoId;
params = directVideo.match(domain);
if (params) options.videoId = params.videoId;
params = embedVideo.match(domain);
if (params) options.videoId = params.videoId;
}
// Check for start and end times for single videos.
if (options.videoId) {
// Start times can be set with &start= for embed urls or
// &t= for short urls.
if (query.start) {
options.start = parseInt(query.start, 10);
} else if (query.t) {
options.start = parseInt(query.t, 10);
}
if (query.end) {
options.end = parseInt(query.end, 10);
}
}
return options;
}
import parseYouTubeUrl from './parseYouTubeUrl';
test('Returns playlist id', () => {
const result = parseYouTubeUrl(
'https://www.youtube.com/watch?v=kfchvCyHmsc&list=PLDyKn8uKYtRalFdBWtv_EjDtUo2UEbu-a',
);
expect(result).toEqual({ playlistId: 'PLDyKn8uKYtRalFdBWtv_EjDtUo2UEbu-a' });
});
test('Returns video id for direct url', () => {
const result = parseYouTubeUrl('https://www.youtube.com/v/vLfAtCbE_Jc');
expect(result).toEqual({ videoId: 'vLfAtCbE_Jc' });
});
test('Returns video id for standard url', () => {
const result = parseYouTubeUrl('https://www.youtube.com/watch?v=vLfAtCbE_Jc');
expect(result).toEqual({ videoId: 'vLfAtCbE_Jc' });
});
test('Returns video id for short url', () => {
const result = parseYouTubeUrl('https://youtu.be/vLfAtCbE_Jc');
expect(result).toEqual({ videoId: 'vLfAtCbE_Jc' });
});
test('Returns video id for embed url', () => {
const result = parseYouTubeUrl('https://www.youtube.com/embed/vLfAtCbE_Jc');
expect(result).toEqual({ videoId: 'vLfAtCbE_Jc' });
});
test('Returns start time for short urls', () => {
const result = parseYouTubeUrl('https://youtu.be/vLfAtCbE_Jc?t=1s');
expect(result).toEqual({ videoId: 'vLfAtCbE_Jc', start: 1 });
});
test('Returns start time for embed urls', () => {
const result = parseYouTubeUrl(
'https://www.youtube.com/embed/vLfAtCbE_Jc?start=1',
);
expect(result).toEqual({ videoId: 'vLfAtCbE_Jc', start: 1 });
});
test('Returns start and end time for embed urls', () => {
const result = parseYouTubeUrl(
'https://www.youtube.com/embed/vLfAtCbE_Jc?start=1&end=6',
);
expect(result).toEqual({ videoId: 'vLfAtCbE_Jc', start: 1, end: 6 });
});
@spookyuser
Copy link

ily

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment