You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复正则以从各类YouTube URL提取Video Id与start time并兼容播放列表?

YouTube URL提取Video ID与起始时间的完整解决方案

一、多格式兼容的preg_match正则实现

以下正则可适配绝大多数YouTube URL,精准提取11位Video ID和start参数对应的起始时间(单位秒),解决了URL尾部解析不当的问题:

$pattern = '/^(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:watch\?v=|embed\/|v\/|shorts\/|playlist\?list=.*?&v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})(?:\?.*?start=(\d+))?(?:&.*|$)/i';

// 测试示例
$testUrls = [
    'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
    'https://youtu.be/dQw4w9WgXcQ?start=30',
    'https://www.youtube.com/embed/dQw4w9WgXcQ?start=15&autoplay=1',
    'https://www.youtube.com/v/dQw4w9WgXcQ',
    'https://www.youtube.com/shorts/dQw4w9WgXcQ?start=5',
    'https://www.youtube.com/playlist?list=PLxyz&v=dQw4w9WgXcQ&start=10'
];

foreach ($testUrls as $url) {
    if (preg_match($pattern, $url, $matches)) {
        $videoId = $matches[1];
        $startTime = isset($matches[2]) ? (int)$matches[2] : 0;
        echo "视频ID: {$videoId}, 起始时间: {$startTime} 秒\n";
    }
}

正则各部分解析

  • ^(?:https?:\/\/)?(?:www\.)?:匹配可选的HTTP/HTTPS协议和www前缀,兼容无协议或无www的URL
  • (?:youtube\.com\/(?:watch\?v=|embed\/|v\/|shorts\/|playlist\?list=.*?&v=)|youtu\.be\/):覆盖YouTube核心路径,包括普通观看页、嵌入页、旧版路径、短视频页、播放列表内嵌视频链接
  • ([a-zA-Z0-9_-]{11}):强制捕获11位的Video ID(YouTube视频ID长度固定为11位,确保匹配精准)
  • (?:\?.*?start=(\d+))?:非贪婪匹配并捕获start参数的数值,避免被后续URL参数干扰
  • (?:&.*|$):匹配剩余URL参数或结尾,解决尾部解析混乱问题
  • i修饰符:忽略大小写,兼容大小写混合的URL

二、已覆盖的URL格式

上述正则支持所有主流YouTube URL格式:

  • 标准观看页:https://www.youtube.com/watch?v=XXX
  • 短域名跳转链接:https://youtu.be/XXX
  • 嵌入页链接:https://www.youtube.com/embed/XXX
  • 旧版视频路径:https://www.youtube.com/v/XXX
  • Shorts短视频链接:https://www.youtube.com/shorts/XXX
  • 播放列表内嵌视频链接:https://www.youtube.com/playlist?list=PLxxx&v=XXX
  • 带任意额外参数的上述格式(如autoplay、loop等)

可扩展的边缘格式

若需覆盖更小众的场景,可对正则进行扩展:

  • 锚点时间戳:如https://www.youtube.com/watch?v=XXX#t=1m30s,可在正则末尾添加(?:#t=(\d+m?\d+s?))?,再将时分秒格式转换为总秒数
  • 无Cookie域名:https://www.youtube-nocookie.com/embed/XXX,可在域名匹配段加入|youtube-nocookie\.com
  • 自定义协议:如youtube://watch?v=XXX,可在开头添加(?:youtube:\/\/)?

三、播放列表场景处理

若需同时提取播放列表ID和当前视频信息,可使用以下扩展正则:

$playlistPattern = '/^(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:watch\?v=([a-zA-Z0-9_-]{11})&list=([a-zA-Z0-9_-]+)|playlist\?list=([a-zA-Z0-9_-]+)(?:&v=([a-zA-Z0-9_-]{11}))?)|youtu\.be\/([a-zA-Z0-9_-]{11}))(?:\?.*?start=(\d+))?(?:&.*|$)/i';

该正则可适配两种播放列表链接格式:

  1. 观看页带播放列表参数:https://www.youtube.com/watch?v=XXX&list=PLxxx
  2. 播放列表页指定视频:https://www.youtube.com/playlist?list=PLxxx&v=XXX

四、兼容PHPStan的代码实现

为通过PHPStan静态分析,需明确变量类型、处理可选捕获组,示例代码如下:

/**
 * 从YouTube URL提取视频ID和起始时间
 * @param string $url
 * @return array{videoId: string|null, startTime: int}
 */
function extractYoutubeVideoInfo(string $url): array
{
    $pattern = '/^(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:watch\?v=|embed\/|v\/|shorts\/|playlist\?list=.*?&v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})(?:\?.*?start=(\d+))?(?:&.*|$)/i';
    
    if (preg_match($pattern, $url, $matches)) {
        $videoId = $matches[1];
        $startTime = isset($matches[2]) ? (int)$matches[2] : 0;
        return ['videoId' => $videoId, 'startTime' => $startTime];
    }
    
    return ['videoId' => null, 'startTime' => 0];
}

内容的提问来源于stack exchange,提问作者Zoltán Süle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 00:37:03