134 lines
3.8 KiB
TypeScript
134 lines
3.8 KiB
TypeScript
/**
|
|
* 유튜브 유틸리티 함수
|
|
* @description 유튜브 관련 유틸리티 함수를 제공합니다.
|
|
*/
|
|
|
|
import { getFirstGroup, isTypeVideo } from '#layers/utils/dataUtil'
|
|
import type {
|
|
PageDataResourceGroups,
|
|
PageDataResourceGroup,
|
|
} from '#layers/types/api/pageData'
|
|
|
|
/**
|
|
* 유튜브 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 getMediaSrc = (resourceGroup: PageDataResourceGroup): string => {
|
|
if (!resourceGroup) return ''
|
|
const mediaSrc = resourceGroup?.display?.text
|
|
return mediaSrc || ''
|
|
}
|
|
|
|
/**
|
|
* 미디어 이미지를 추출합니다. (유튜브인 경우 썸네일)
|
|
* @param source - 미디어 소스 객체
|
|
* @param quality - 썸네일 품질
|
|
* @returns 미디어 이미지 소스
|
|
*/
|
|
export const getMediaImgSrc = (
|
|
resourceGroups: PageDataResourceGroups,
|
|
quality: 'default' | 'medium' | 'high' | 'standard' | 'maxres' = 'high'
|
|
): string => {
|
|
if (!resourceGroups) return ''
|
|
|
|
const resourceGroup = getFirstGroup(resourceGroups)
|
|
const mediaSrc = getMediaSrc(resourceGroup)
|
|
const mediaType = resourceGroup?.resource_type
|
|
|
|
if (isTypeVideo(mediaType) && mediaSrc) {
|
|
const videoId = getYouTubeVideoId(mediaSrc)
|
|
const thumbnailUrl = getYouTubeThumbnail(videoId, quality)
|
|
return thumbnailUrl
|
|
}
|
|
|
|
return mediaSrc || ''
|
|
}
|