143 lines
4.0 KiB
TypeScript
143 lines
4.0 KiB
TypeScript
/**
|
||
* 视频平台URL检测工具
|
||
* 支持多种主流视频平台的URL识别
|
||
*/
|
||
|
||
// 各种视频平台的正则表达式
|
||
const VIDEO_PATTERNS = {
|
||
// YouTube
|
||
youtube: /(?:youtube\.com\/(?:[^/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?/\s]{11})/i,
|
||
|
||
// Bilibili
|
||
bilibili: /(?:bilibili\.com\/video\/|b23\.tv\/)[A-Za-z0-9]+/i,
|
||
|
||
// Vimeo
|
||
vimeo: /(?:vimeo\.com\/)([0-9]+)/i,
|
||
|
||
// Dailymotion
|
||
dailymotion: /(?:dailymotion\.com\/video\/|dai\.ly\/)([A-Za-z0-9]+)/i,
|
||
|
||
// TikTok
|
||
tiktok: /(?:tiktok\.com\/@[^/]+\/video\/|vm\.tiktok\.com\/)[A-Za-z0-9]+/i,
|
||
|
||
// Twitch
|
||
twitch: /(?:twitch\.tv\/videos\/|clips\.twitch\.tv\/)[A-Za-z0-9]+/i,
|
||
|
||
// 腾讯视频
|
||
tencent: /(?:v\.qq\.com\/x\/cover\/|v\.qq\.com\/x\/page\/)[A-Za-z0-9]+/i,
|
||
|
||
// 爱奇艺
|
||
iqiyi: /(?:iqiyi\.com\/v_)[A-Za-z0-9]+/i,
|
||
|
||
// 优酷
|
||
youku: /(?:youku\.com\/v_show\/id_)[A-Za-z0-9]+/i,
|
||
|
||
// Facebook/Meta
|
||
facebook: /(?:facebook\.com\/watch\/|fb\.watch\/)[A-Za-z0-9]+/i,
|
||
|
||
// Instagram
|
||
instagram: /(?:instagram\.com\/(?:p|reel)\/)[A-Za-z0-9_-]+/i,
|
||
|
||
// Twitter/X
|
||
twitter: /(?:twitter\.com\/[^/]+\/status\/|x\.com\/[^/]+\/status\/)[0-9]+/i,
|
||
|
||
// 抖音
|
||
douyin: /(?:douyin\.com\/video\/)[0-9]+/i,
|
||
|
||
// 快手
|
||
kuaishou: /(?:kuaishou\.com\/short-video\/)[A-Za-z0-9]+/i,
|
||
|
||
// 小红书
|
||
xiaohongshu: /(?:xiaohongshu\.com\/explore\/)[A-Za-z0-9]+/i,
|
||
|
||
// 微博视频
|
||
weibo: /(?:weibo\.com\/[^/]+\/[A-Za-z0-9]+|weibo\.cn\/sinaurl)/i,
|
||
|
||
// Rumble
|
||
rumble: /(?:rumble\.com\/)[A-Za-z0-9_-]+/i,
|
||
|
||
// Odysee
|
||
odysee: /(?:odysee\.com\/@[^/]+\/)[A-Za-z0-9_-]+/i,
|
||
|
||
// JW Player (通用嵌入式播放器)
|
||
jwplayer: /(?:jwplayer\.com\/players\/)[A-Za-z0-9_-]+/i,
|
||
|
||
// 通用视频文件扩展名
|
||
videoFile: /\.(mp4|avi|mov|wmv|flv|webm|mkv|m4v|3gp|ogv)(\?.*)?$/i,
|
||
|
||
// 通用视频流媒体
|
||
streaming: /(?:stream|live|video|watch|play).*\.(m3u8|mpd|f4m)(\?.*)?$/i
|
||
}
|
||
|
||
export type VideoProvider = keyof typeof VIDEO_PATTERNS
|
||
|
||
/**
|
||
* 检测URL是否为视频内容
|
||
* @param url 要检测的URL
|
||
* @returns 是否为视频URL
|
||
*/
|
||
export function isVideoUrl(url: string): boolean {
|
||
return Object.values(VIDEO_PATTERNS).some(pattern => pattern.test(url))
|
||
}
|
||
|
||
/**
|
||
* 检测URL属于哪个视频平台
|
||
* @param url 要检测的URL
|
||
* @returns 视频平台名称,如果不是视频URL则返回null
|
||
*/
|
||
export function getVideoProvider(url: string): VideoProvider | null {
|
||
for (const [provider, pattern] of Object.entries(VIDEO_PATTERNS)) {
|
||
if (pattern.test(url)) {
|
||
return provider as VideoProvider
|
||
}
|
||
}
|
||
return null
|
||
}
|
||
|
||
/**
|
||
* 检测特定平台的视频URL
|
||
* @param url 要检测的URL
|
||
* @param provider 视频平台
|
||
* @returns 是否为指定平台的视频URL
|
||
*/
|
||
export function isVideoUrlFromProvider(url: string, provider: VideoProvider): boolean {
|
||
const pattern = VIDEO_PATTERNS[provider]
|
||
return pattern ? pattern.test(url) : false
|
||
}
|
||
|
||
/**
|
||
* 从URL中提取视频ID(如果可能)
|
||
* @param url 视频URL
|
||
* @returns 视频ID或null
|
||
*/
|
||
export function extractVideoId(url: string): string | null {
|
||
const provider = getVideoProvider(url)
|
||
if (!provider) return null
|
||
|
||
const pattern = VIDEO_PATTERNS[provider]
|
||
const match = url.match(pattern)
|
||
|
||
// 返回第一个捕获组(如果存在)
|
||
return match && match[1] ? match[1] : null
|
||
}
|
||
|
||
/**
|
||
* 获取支持的视频平台列表
|
||
* @returns 支持的视频平台名称数组
|
||
*/
|
||
export function getSupportedVideoProviders(): VideoProvider[] {
|
||
return Object.keys(VIDEO_PATTERNS) as VideoProvider[]
|
||
}
|
||
|
||
// 为了向后兼容,保留原有的YouTube检测函数
|
||
export function isYoutubeUrl(url: string): boolean {
|
||
return isVideoUrlFromProvider(url, 'youtube')
|
||
}
|
||
|
||
// 导出常用的视频平台检测函数
|
||
export const isYouTubeUrl = isYoutubeUrl // 别名
|
||
export const isBilibiliUrl = (url: string) => isVideoUrlFromProvider(url, 'bilibili')
|
||
export const isVimeoUrl = (url: string) => isVideoUrlFromProvider(url, 'vimeo')
|
||
export const isTikTokUrl = (url: string) => isVideoUrlFromProvider(url, 'tiktok')
|
||
export const isTwitchUrl = (url: string) => isVideoUrlFromProvider(url, 'twitch')
|