mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 20:54:11 +00:00
Complete YouTube content management system: - YouTubeChannels: Channel management with branding and metrics - YouTubeContent: Video pipeline with workflow, approvals, scheduling - YtSeries: Dedicated series management per channel (NEW) - YtBatches: Production batch tracking with targets and progress - YtTasks: Task management with notifications - YtNotifications: User notification system - YtMonthlyGoals: Monthly production goals per channel - YtScriptTemplates: Reusable script templates - YtChecklistTemplates: Checklist templates for workflows Features: - Role-based access (YouTubeManager, YouTubeCreator, YouTubeViewer) - Auto-task generation on status changes - Series relationship with channel-based filtering - API endpoints for dashboard, tasks, and task completion - German/English localization support Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
167 lines
4.7 KiB
TypeScript
167 lines
4.7 KiB
TypeScript
// src/lib/utils/youtube.ts
|
|
|
|
/**
|
|
* YouTube URL Parser and Utilities
|
|
*
|
|
* Hilfsfunktionen zum Parsen von YouTube-URLs und Generieren von Embed-URLs.
|
|
* Unterstützt verschiedene YouTube-URL-Formate:
|
|
* - youtube.com/watch?v=VIDEO_ID
|
|
* - youtu.be/VIDEO_ID
|
|
* - youtube.com/embed/VIDEO_ID
|
|
* - youtube.com/shorts/VIDEO_ID
|
|
*/
|
|
|
|
/**
|
|
* Extrahiert die Video-ID aus einer YouTube-URL.
|
|
*
|
|
* @param url - Die YouTube-URL
|
|
* @returns Die Video-ID oder null wenn nicht gefunden
|
|
*
|
|
* @example
|
|
* extractYouTubeId('https://www.youtube.com/watch?v=dQw4w9WgXcQ') // 'dQw4w9WgXcQ'
|
|
* extractYouTubeId('https://youtu.be/dQw4w9WgXcQ') // 'dQw4w9WgXcQ'
|
|
* extractYouTubeId('https://www.youtube.com/shorts/VIDEO_ID') // 'VIDEO_ID'
|
|
*/
|
|
export function extractYouTubeId(url: string): string | null {
|
|
if (!url) return null
|
|
|
|
const patterns = [
|
|
/youtube\.com\/watch\?v=([^&]+)/,
|
|
/youtu\.be\/([^?]+)/,
|
|
/youtube\.com\/embed\/([^?]+)/,
|
|
/youtube\.com\/shorts\/([^?]+)/,
|
|
/youtube-nocookie\.com\/embed\/([^?]+)/,
|
|
]
|
|
|
|
for (const pattern of patterns) {
|
|
const match = url.match(pattern)
|
|
if (match) return match[1]
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* Generiert eine YouTube Embed-URL.
|
|
*
|
|
* @param videoId - Die YouTube Video-ID
|
|
* @param privacyMode - Wenn true, wird youtube-nocookie.com verwendet (DSGVO-konform)
|
|
* @param options - Zusätzliche Embed-Optionen
|
|
* @returns Die vollständige Embed-URL
|
|
*
|
|
* @example
|
|
* getYouTubeEmbedUrl('dQw4w9WgXcQ') // 'https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ'
|
|
* getYouTubeEmbedUrl('dQw4w9WgXcQ', false) // 'https://www.youtube.com/embed/dQw4w9WgXcQ'
|
|
*/
|
|
export function getYouTubeEmbedUrl(
|
|
videoId: string,
|
|
privacyMode = true,
|
|
options?: {
|
|
autoplay?: boolean
|
|
muted?: boolean
|
|
loop?: boolean
|
|
controls?: boolean
|
|
startTime?: number
|
|
}
|
|
): string {
|
|
const domain = privacyMode ? 'www.youtube-nocookie.com' : 'www.youtube.com'
|
|
const baseUrl = `https://${domain}/embed/${videoId}`
|
|
|
|
// Build query parameters
|
|
const params = new URLSearchParams()
|
|
|
|
if (options?.autoplay) params.set('autoplay', '1')
|
|
if (options?.muted) params.set('mute', '1')
|
|
if (options?.loop) {
|
|
params.set('loop', '1')
|
|
params.set('playlist', videoId) // Required for loop to work
|
|
}
|
|
if (options?.controls === false) params.set('controls', '0')
|
|
if (options?.startTime) params.set('start', String(options.startTime))
|
|
|
|
const queryString = params.toString()
|
|
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
|
}
|
|
|
|
/**
|
|
* Generiert eine YouTube Thumbnail-URL.
|
|
*
|
|
* @param videoId - Die YouTube Video-ID
|
|
* @param quality - Die gewünschte Qualität
|
|
* @returns Die Thumbnail-URL
|
|
*
|
|
* @example
|
|
* getYouTubeThumbnail('dQw4w9WgXcQ') // 'https://img.youtube.com/vi/dQw4w9WgXcQ/hqdefault.jpg'
|
|
* getYouTubeThumbnail('dQw4w9WgXcQ', 'maxres') // 'https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg'
|
|
*/
|
|
export function getYouTubeThumbnail(
|
|
videoId: string,
|
|
quality: 'default' | 'mq' | 'hq' | 'sd' | 'maxres' = 'hq'
|
|
): string {
|
|
const qualityMap: Record<string, string> = {
|
|
default: 'default',
|
|
mq: 'mqdefault',
|
|
hq: 'hqdefault',
|
|
sd: 'sddefault',
|
|
maxres: 'maxresdefault',
|
|
}
|
|
|
|
return `https://img.youtube.com/vi/${videoId}/${qualityMap[quality]}.jpg`
|
|
}
|
|
|
|
/**
|
|
* Prüft, ob eine URL eine gültige YouTube-URL ist.
|
|
*
|
|
* @param url - Die zu prüfende URL
|
|
* @returns true wenn die URL eine gültige YouTube-URL ist
|
|
*/
|
|
export function isValidYouTubeUrl(url: string): boolean {
|
|
if (!url) return false
|
|
|
|
const youtubePatterns = [
|
|
/youtube\.com\/watch\?v=/,
|
|
/youtu\.be\//,
|
|
/youtube\.com\/embed\//,
|
|
/youtube\.com\/shorts\//,
|
|
/youtube-nocookie\.com\/embed\//,
|
|
]
|
|
|
|
return youtubePatterns.some((pattern) => pattern.test(url))
|
|
}
|
|
|
|
/**
|
|
* Extrahiert die Playlist-ID aus einer YouTube-Playlist-URL.
|
|
*
|
|
* @param url - Die YouTube-Playlist-URL
|
|
* @returns Die Playlist-ID oder null wenn nicht gefunden
|
|
*
|
|
* @example
|
|
* extractYouTubePlaylistId('https://www.youtube.com/playlist?list=PLxxxxxx') // 'PLxxxxxx'
|
|
*/
|
|
export function extractYouTubePlaylistId(url: string): string | null {
|
|
if (!url) return null
|
|
|
|
const patterns = [
|
|
/youtube\.com\/playlist\?list=([^&]+)/,
|
|
/youtube\.com\/watch\?.*list=([^&]+)/,
|
|
]
|
|
|
|
for (const pattern of patterns) {
|
|
const match = url.match(pattern)
|
|
if (match) return match[1]
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* Generiert eine YouTube Playlist Embed-URL.
|
|
*
|
|
* @param playlistId - Die YouTube Playlist-ID
|
|
* @param privacyMode - Wenn true, wird youtube-nocookie.com verwendet
|
|
* @returns Die vollständige Playlist Embed-URL
|
|
*/
|
|
export function getYouTubePlaylistEmbedUrl(playlistId: string, privacyMode = true): string {
|
|
const domain = privacyMode ? 'www.youtube-nocookie.com' : 'www.youtube.com'
|
|
return `https://${domain}/embed/videoseries?list=${playlistId}`
|
|
}
|