// ============================================================================ // 유튜브 관련 유틸리티 // ============================================================================ /** * 유튜브 URL에서 비디오 ID를 추출합니다. * @param url - 유튜브 URL (watch, embed, youtu.be 등 다양한 형태 지원) * @returns 비디오 ID 또는 빈 문자열 */ export const getYouTubeVideoId = (url: string): string => { if (!url) return '' // 다양한 유튜브 URL 패턴 지원 const patterns = [ /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/|youtube\.com\/shorts\/)([^&\n?#]+)/, /youtube\.com\/watch\?.*v=([^&\n?#]+)/, /youtube\.com\/embed\/([^&\n?#]+)/, /youtube\.com\/shorts\/([^&\n?#]+)/, ] for (const pattern of patterns) { const match = url.match(pattern) if (match && match[1]) { return match[1] } } return '' } /** * 유튜브 임베드 URL을 생성합니다. * @param url - 유튜브 URL * @param autoplay - 자동재생 여부 * @param rel - 관련 비디오 표시 여부 * @returns 임베드 URL */ /** [TODO] 임베드 형태로 넘어오도록 데이터 수정 후 이부분 사용 필요 없음 */ export const getYouTubeEmbedUrl = ( url: string, autoplay: boolean = false, rel: boolean = false ): string => { const videoId = getYouTubeVideoId(url) if (!videoId) return '' const params = new URLSearchParams() if (autoplay) params.append('autoplay', '1') if (!rel) params.append('rel', '0') const queryString = params.toString() return `https://www.youtube.com/embed/${videoId}${queryString ? `?${queryString}` : ''}` } /** * 유튜브 비디오 ID로부터 썸네일 URL을 생성합니다. * @param videoId - 유튜브 비디오 ID * @param quality - 썸네일 품질 ('default', 'medium', 'high', 'standard', 'maxres') * @returns 썸네일 URL */ export const getYouTubeThumbnail = ( videoId: string, quality: 'default' | 'medium' | 'high' | 'standard' | 'maxres' = 'high' ): string => { if (!videoId) return '' const qualityMap = { default: 'default', medium: 'mqdefault', high: 'hqdefault', standard: 'sddefault', maxres: 'maxresdefault', } return `https://img.youtube.com/vi/${videoId}/${qualityMap[quality]}.jpg` } /** * 유튜브 URL에서 직접 썸네일 URL을 추출합니다. * @param url - 유튜브 URL * @param quality - 썸네일 품질 * @returns 썸네일 URL */ export const getYouTubeThumbnailFromUrl = ( url: string, quality: 'default' | 'medium' | 'high' | 'standard' | 'maxres' = 'high' ): string => { const videoId = getYouTubeVideoId(url) return getYouTubeThumbnail(videoId, quality) } /** * 미디어 text(src)를 추출합니다. * @param source - 미디어 소스 객체 * @returns 미디어 text(src) */ export const getMediaText = (source: Record): string => { if (!source) return '' const resource = source.groups?.[0] const mediaUrl = resource?.display?.text return mediaUrl || '' } /** * 미디어 이미지를 추출합니다. (유튜브인 경우 썸네일) * @param source - 미디어 소스 객체 * @param quality - 썸네일 품질 * @returns 미디어 이미지 소스 */ export const getMediaImgSrc = ( source: Record, quality: 'default' | 'medium' | 'high' | 'standard' | 'maxres' = 'high' ): string => { if (!source) return '' const resource = source.groups?.[0] const mediaType = resource?.group_type const mediaUrl = resource?.display?.text if (mediaType === 'video' && mediaUrl) { const videoId = getYouTubeVideoId(mediaUrl) const thumbnailUrl = getYouTubeThumbnail(videoId, quality) return thumbnailUrl } return mediaUrl || '' } /** * 미디어 타입을 확인합니다. * @param source - 미디어 소스 객체 * @returns 미디어 타입 ('video' | 'image' | '') */ export const getMediaType = (source: Record): string => { if (!source) return '' const resource = source.groups?.[0] const mediaType = resource?.group_type return mediaType || '' } /** * 비디오 아이템인지 확인합니다. * @param source - 미디어 소스 객체 * @returns 비디오 여부 */ export const isVideoItem = (source: Record): boolean => { return getMediaType(source) === 'video' }