import { promises as fs } from 'fs' import { join } from 'path' import { stat } from 'fs/promises' export default defineEventHandler(async (event) => { try { const videosPath = join(process.cwd(), 'videos') // Verificar si existe la carpeta try { await fs.access(videosPath) } catch { return { videos: [] } } const files = await fs.readdir(videosPath) // Detectar videos originales (archivos de video sin sufijos de calidad) const videoExtensions = ['.mp4', '.webm', '.ogg', '.mov', '.avi', '.mkv'] const videoFiles = files.filter(file => { const ext = file.toLowerCase().substring(file.lastIndexOf('.')) const nameWithoutExt = file.substring(0, file.lastIndexOf('.')) const hasQualitySuffix = /_(4k|2k|1080p|720p|480p|360p)$/i.test(nameWithoutExt) return videoExtensions.includes(ext) && !hasQualitySuffix }) const videoMap = new Map() // Procesar cada video original for (const file of videoFiles) { const ext = file.substring(file.lastIndexOf('.')) const baseName = file.substring(0, file.lastIndexOf('.')) // Verificar si existe carpeta HLS const hlsDir = join(videosPath, `${baseName}_hls`) let isHLS = false let hlsQualities: any[] = [] try { const hlsStat = await stat(hlsDir) if (hlsStat.isDirectory()) { // Buscar archivos .m3u8 para detectar calidades disponibles const hlsFiles = await fs.readdir(hlsDir) const qualityFiles = hlsFiles.filter(f => f.endsWith('.m3u8') && f !== 'master.m3u8' && !f.includes('_vtt') // Excluir archivos de subtítulos ) qualityFiles.forEach(qFile => { const quality = qFile.replace('.m3u8', '') hlsQualities.push({ quality, label: quality.toUpperCase(), url: `/videos/${baseName}_hls/${qFile}`, file: qFile, isHLS: true }) }) if (hlsQualities.length > 0) { isHLS = true } } } catch { // No existe HLS para este video } if (isHLS) { // Video con HLS videoMap.set(baseName, { id: baseName, name: baseName, extension: ext.toLowerCase(), isHLS: true, qualities: hlsQualities, url: `/videos/${baseName}_hls/master.m3u8` }) } else { // Video sin HLS, buscar versiones de calidad tradicionales const qualities = [ { quality: 'auto', label: 'Original', url: `/videos/${file}`, file, isHLS: false } ] // Buscar versiones con sufijos de calidad for (const qualitySuffix of ['4k', '2k', '1080p', '720p', '480p', '360p']) { const qualityFile = `${baseName}_${qualitySuffix}${ext}` if (files.includes(qualityFile)) { qualities.push({ quality: qualitySuffix, label: qualitySuffix.toUpperCase(), url: `/videos/${qualityFile}`, file: qualityFile, isHLS: false }) } } videoMap.set(baseName, { id: baseName, name: baseName, extension: ext.toLowerCase(), isHLS: false, qualities, url: `/videos/${file}` }) } } // Convertir a array y ordenar calidades const videos = Array.from(videoMap.values()).map(video => { // Ordenar calidades de mayor a menor const qualityOrder = { '4k': 0, '2k': 1, '1080p': 2, '720p': 3, '480p': 4, '360p': 5, 'auto': 6 } video.qualities.sort((a: any, b: any) => { return (qualityOrder[a.quality as keyof typeof qualityOrder] || 999) - (qualityOrder[b.quality as keyof typeof qualityOrder] || 999) }) // Establecer la URL por defecto (la mejor calidad disponible) if (video.isHLS) { video.url = `/videos/${video.name}_hls/master.m3u8` } else { video.url = video.qualities[0].url } return video }) return { videos } } catch (error) { console.error('Error reading videos:', error) return { videos: [], error: 'Failed to load videos' } } })