Plataforma completa de generación automática de clips cortos desde videos de YouTube usando IA. Diseñada para creadores de contenido que quieren maximizar su alcance en plataformas como TikTok, YouTube Shorts e Instagram Reels.
- 🎥 Descarga inteligente - Videos de YouTube en alta calidad con yt-dlp
- 🎤 Transcripción automática - OpenAI Whisper API con timestamps precisos
- 🤖 Análisis con IA - DeepSeek identifica los mejores momentos virales (5-8 clips sugeridos)
- 🎨 Editor visual premium - Interfaz moderna con glassmorphism y animaciones fluidas
- 📝 Subtítulos personalizables - Editor completo con plantillas, estilos y posicionamiento
- 🎬 Renderizado en cliente - FFmpeg.wasm procesa video directamente en el navegador
- � SEO profesional para YouTube - Genera títulos, descripciones y tags optimizados con IA
- ⚡ Cache inteligente - Redis evita regenerar contenido con DeepSeek
- 📊 Progreso en tiempo real - WebSockets muestran el estado de cada fase
- 💎 Diseño moderno - Grid animado, efectos de cristal, fuente Inter, selección púrpura
- Framework: SvelteKit (Svelte 5) + TypeScript
- Estilos: Tailwind CSS con configuración personalizada
- Tipografía: Inter font family
- Video Processing: FFmpeg.wasm para renderizado en cliente
- UI/UX: Glassmorphism, grid animado, efectos de profundidad
- Editor: Canvas-based subtitle renderer con preview en tiempo real
- Runtime: Go 1.21+ (Golang)
- Framework: Gin Web Framework
- Base de datos: SQLite con migraciones automáticas
- Cache: Redis 7-alpine con persistencia
- WebSockets: Gorilla WebSocket para actualizaciones en tiempo real
- APIs:
- DeepSeek API para análisis de contenido y SEO
- OpenAI Whisper API para transcripción
- Soporte opcional para Ollama (AI local)
- FFmpeg - Procesamiento de video y audio
- yt-dlp - Descarga optimizada de YouTube
- OpenAI Whisper API - Transcripción con timestamps
- DeepSeek Chat - Análisis de contenido viral y generación de SEO
- Redis - Cache de respuestas de IA (TTL: 24h)
- Docker & Docker Compose - Containerización completa
- Multi-stage builds - Imágenes optimizadas
- Health checks - Monitoreo de servicios
- Persistent volumes - Storage y cache persistentes
- Go 1.21 o superior
- Node.js 18+ y npm
- FFmpeg instalado en el sistema
- yt-dlp instalado globalmente
- (Opcional) Redis para cache local
- Docker 20.10+
- Docker Compose 2.0+
- OpenAI API Key - Para transcripción con Whisper
- DeepSeek API Key - Para análisis de contenido y SEO
- Alternativa: Ollama local (descomenta servicio en docker-compose.yml)
- Clonar el repositorio
git clone https://github.com/backsoul/shortia.git
cd shortia- Configurar variables de entorno
# Crea el archivo .env en la raíz
cp .env.example .envEdita .env con tus credenciales:
# === APIs de IA ===
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx
# === Configuración de Redis ===
REDIS_PASSWORD=
CACHE_TTL=86400
# === Opciones de IA Local (Opcional) ===
USE_OLLAMA=false
OLLAMA_URL=http://ollama:11434
OLLAMA_MODEL=deepseek-r1:latest- Levantar servicios
docker-compose up -d --build- Verificar servicios
docker-compose ps
# Deberías ver: backend (8080), redis (6379)- Acceder a la aplicación
- Frontend: Configurar en tu servidor web o usar desarrollo local
- Backend API: http://localhost:8080
- Redis: localhost:6379
cd backend
go mod download
go run main.gocd frontend
npm install
npm run devEl frontend estará en: http://localhost:5173 El backend API en: http://localhost:8080
- Pega una URL de YouTube en el input principal
- El sistema descarga automáticamente el video
- Progreso visible en tiempo real vía WebSocket
- OpenAI Whisper transcribe el audio completo
- Genera timestamps precisos para cada segmento
- Almacena transcripción en base de datos
- DeepSeek analiza la transcripción completa
- Identifica 5-8 momentos con mayor potencial viral
- Cada clip sugerido incluye:
- Timestamps de inicio y fin (15-60 segundos)
- Título atractivo
- Descripción del contenido
- Score de viralidad (0-100)
- Razón detallada de por qué funciona
- Visualización de todos los clips sugeridos
- Editor visual con:
- Preview del video en tiempo real
- Subtítulos personalizables (fuente, color, posición)
- Plantillas predefinidas
- Canvas renderer para preview exacto
- Ajuste fino de timestamps
- Botón "Generar sugerencias de YouTube"
- DeepSeek genera profesionalmente:
- Título optimizado (60-70 caracteres)
- Descripción rica (600 caracteres con keywords)
- 15-20 tags específicos para el algoritmo
- Resultado cacheado en Redis (no regenera mismo clip)
- Un clic para copiar todos los tags
- Renderizado en cliente con FFmpeg.wasm
- Subtítulos quemados en el video
- Descarga automática en formato MP4
- Progreso visible durante exportación
shortia/
├── backend/ # API en Go + Gin
│ ├── api/
│ │ ├── handlers.go # HTTP handlers para todos los endpoints
│ │ └── websocket.go # WebSocket para progreso en tiempo real
│ ├── services/
│ │ ├── video_service.go # Gestión de videos y base de datos
│ │ ├── processing_service.go # FFmpeg, yt-dlp, Whisper, DeepSeek
│ │ ├── clip_service.go # CRUD de clips generados
│ │ ├── seo_service.go # Generación de SEO con DeepSeek
│ │ └── cache_service.go # Redis cache para APIs de IA
│ ├── models/
│ │ └── models.go # Structs de Video, Clip, Transcript, SEO
│ ├── database/
│ │ └── database.go # SQLite setup y migraciones
│ ├── Dockerfile # Multi-stage build optimizado
│ ├── go.mod # Dependencias Go
│ └── main.go # Entry point + routing
│
├── frontend/ # SvelteKit App
│ ├── src/
│ │ ├── routes/
│ │ │ ├── +page.svelte # Landing page con grid animado
│ │ │ ├── +layout.svelte # Layout global
│ │ │ └── video/[id]/+page.svelte # Vista de video individual
│ │ ├── lib/
│ │ │ ├── components/
│ │ │ │ ├── VideoUpload.svelte # Upload/URL input
│ │ │ │ ├── VideoList.svelte # Lista de videos procesados
│ │ │ │ ├── VideoPlayer.svelte # Player con controles
│ │ │ │ ├── ClipEditor.svelte # Editor principal (2700+ líneas)
│ │ │ │ ├── SubtitleEditor.svelte # Editor de texto de subs
│ │ │ │ ├── SubtitleSettings.svelte # Configuración de estilo
│ │ │ │ ├── SubtitleCanvas.svelte # Preview renderer
│ │ │ │ ├── VideoCanvasRenderer.svelte # Canvas para export
│ │ │ │ ├── TemplateGallery.svelte # Plantillas predefinidas
│ │ │ │ └── ExportProgress.svelte # Barra de progreso
│ │ │ ├── services/
│ │ │ │ └── ffmpeg.ts # FFmpeg.wasm wrapper
│ │ │ ├── data/
│ │ │ │ └── templates.ts # Plantillas de subtítulos
│ │ │ └── types.ts # TypeScript interfaces
│ │ ├── app.css # Estilos globales + Inter font
│ │ └── app.html # HTML template
│ ├── static/
│ │ └── ffmpeg/ # FFmpeg.wasm core files
│ ├── tailwind.config.js # Tailwind con Inter
│ ├── svelte.config.js # SvelteKit config
│ ├── vite.config.ts # Vite bundler config
│ └── package.json
│
├── storage/ # Datos persistentes (volumen Docker)
│ ├── videos/ # Videos descargados de YouTube
│ ├── clips/ # Clips generados (legacy backend-rendered)
│ ├── transcripts/ # Transcripciones JSON
│ └── database.db # SQLite database
│
├── binaries/ # Binarios externos (opcional para local dev)
│ └── whisper/ # Whisper binaries (si usas local)
│
├── docker-compose.yml # Orquestación multi-container
├── .env.example # Template de variables de entorno
├── .env # Variables de entorno (no commitear)
└── README.md # Este archivo
Procesa una URL de YouTube: descarga, transcribe y analiza con IA.
Body:
{
"url": "https://www.youtube.com/watch?v=VIDEO_ID"
}Response:
{
"id": "uuid-v4",
"url": "https://youtube.com/...",
"title": "Video Title",
"duration": 1234.5,
"status": "processing",
"created_at": "2025-11-20T..."
}WebSocket: Conectarse a ws://localhost:8080/api/videos/{id}/ws para recibir actualizaciones:
{
"type": "progress",
"step": "download",
"status": "processing",
"message": "Descargando video..."
}Lista todos los videos procesados.
Response:
[
{
"id": "uuid",
"title": "Video Title",
"duration": 1234.5,
"status": "completed",
"thumbnail_url": "https://...",
"created_at": "2025-11-20T..."
}
]Obtiene detalles de un video específico.
Response:
{
"id": "uuid",
"url": "https://youtube.com/...",
"title": "Video Title",
"duration": 1234.5,
"status": "completed",
"file_path": "/app/storage/videos/video.mp4",
"thumbnail_url": "https://...",
"created_at": "2025-11-20T..."
}Stream del video para reproducción (HTTP range requests soportados).
Response: Video file stream
Obtiene la transcripción completa con timestamps.
Response:
{
"video_id": "uuid",
"full_text": "Transcripción completa...",
"language": "es",
"segments": [
{
"start": 0.0,
"end": 5.2,
"text": "Hola, bienvenidos..."
}
]
}Obtiene clips sugeridos por IA (5-8 mejores momentos).
Response:
[
{
"start_time": 10.5,
"end_time": 45.2,
"title": "Cómo ganar dinero con IA",
"description": "Explicación completa del método...",
"score": 92,
"reason": "Contenido viral porque..."
}
]Extrae un clip raw (sin subtítulos) del video original.
Body:
{
"clip_start_time": 10.5,
"clip_end_time": 45.2
}Response:
{
"clip_path": "/app/storage/clips/clip_uuid.mp4",
"duration": 34.7
}Genera SEO profesional para YouTube con DeepSeek (cacheado en Redis).
Body:
{
"video_id": "uuid",
"clip_start_time": 10.5,
"clip_end_time": 45.2,
"clip_title": "Título del clip"
}Response:
{
"title": "💰 Cómo GANAR DINERO con IA en 2025 | Método Paso a Paso",
"description": "Descubre el método exacto que uso para generar ingresos con inteligencia artificial. En este clip te muestro: ✅ Las mejores herramientas ✅ Estrategias probadas ✅ Resultados reales...",
"tags": [
"ganar dinero online",
"inteligencia artificial",
"ia para emprendedores",
"como ganar dinero con ia",
"metodos 2025",
...
]
}Cache: Si ya se generó SEO para los mismos parámetros, devuelve resultado cacheado instantáneamente.
Crea un clip con subtítulos procesados en backend.
Body:
{
"video_id": "uuid",
"start_time": 10.5,
"end_time": 45.2,
"title": "Mi Clip",
"subtitles": {
"text": "Texto del subtítulo",
"font_family": "Arial",
"font_size": 24,
"color": "#FFFFFF",
"position": "bottom"
}
}Exporta clip con subtítulos (backend processing).
Obtiene información de un clip.
Descarga el clip exportado.
Elimina un clip.
Convierte video WebM a MP4 usando FFmpeg nativo.
Body: Multipart form con archivo WebM
Response:
{
"file_path": "/app/storage/clips/converted.mp4"
}WebSocket para recibir actualizaciones de progreso en tiempo real.
Mensajes:
{"type": "progress", "step": "download", "status": "processing"}{"type": "progress", "step": "transcription", "status": "processing"}{"type": "progress", "step": "analysis", "status": "processing"}{"type": "complete", "video_id": "uuid"}{"type": "error", "message": "Error description"}
El editor incluye un sistema completo de personalización de subtítulos:
- Fuentes: Arial, Impact, Montserrat, Bebas Neue, Poppins, Roboto, etc.
- Tamaño: 12-120px
- Colores: Selector de color completo para texto, borde y fondo
- Grosor de borde: 0-10px
- Opacidad de fondo: 0-100%
- Padding: Espaciado interno personalizable
- Vertical: Top, Center, Bottom
- Horizontal: Left, Center, Right
- Offset personalizado: Ajuste fino en píxeles
- Classic White - Texto blanco con borde negro (estilo tradicional)
- Bold Impact - Texto amarillo con borde negro (alta visibilidad)
- Modern Minimal - Sin borde, fondo semitransparente
- Neon Glow - Efectos de brillo para contenido moderno
- Elegant Serif - Tipografía serif para contenido profesional
- Canvas renderer que muestra exactamente cómo se verá el subtítulo
- Sincronización con el video player
- Ajustes instantáneos sin necesidad de exportar
Prompt Optimizado: El sistema envía la transcripción completa a DeepSeek con un prompt especializado que:
- Prioriza coherencia narrativa: Los clips deben tener inicio, desarrollo y cierre completo
- Duración inteligente: 15-60 segundos según la complejidad de la idea
- Identifica valor: Busca momentos que enseñen, entretengan o sorprendan
- Evalúa potencial viral: Score basado en curiosidad, trending topics, shareability
Criterios de Selección:
✅ Historias completas con setup y punchline
✅ Tips o consejos con explicación completa
✅ Revelaciones o insights completos
✅ Momentos emotivos con contexto
✅ Contenido trending o contra-intuitivo
Output: Array de 5-8 clips ordenados por score de viralidad (0-100)
Para cada clip, DeepSeek genera:
- Título optimizado (60-70 caracteres):
- Keywords en los primeros 40 caracteres
- Emojis estratégicos para CTR
- Gancho emocional o curiosidad
- Descripción rica (600 caracteres):
- Resumen del contenido con keywords
- Call-to-action
- Contexto adicional
- Hashtags relevantes
- 15-20 Tags específicos:
- Mix de keywords genéricas y específicas
- Términos de búsqueda de cola larga
- Tags trending relacionados
Cache en Redis:
- Key: SHA256 hash de
video_id:start_time:end_time:title - TTL: 24 horas (86400 segundos)
- Evita regenerar SEO para el mismo clip
Proceso:
- FFmpeg extrae audio del video descargado
- Audio se envía a Whisper API con
response_format: verbose_json - Whisper devuelve:
- Texto completo
- Idioma detectado
- Segmentos con timestamps precisos (start/end)
- Se almacena en base de datos y archivo JSON
Ventajas de Whisper API:
- Alta precisión en múltiples idiomas
- Timestamps precisos para sincronización
- Manejo de ruido y múltiples hablantes
- Detección automática de idioma
Implementación:
// cache_service.go
type CacheService struct {
client *redis.Client
ctx context.Context
ttl time.Duration
}Métodos disponibles:
GetSEO()/SetSEO()- Cache de contenido SEOGetTranscript()/SetTranscript()- Cache de transcripcionesGetSuggestedClips()/SetSuggestedClips()- Cache de análisis de clipsInvalidateVideo()- Limpia todo el cache de un video
Generación de Keys:
// Genera SHA256 hash para keys consistentes
func generateCacheKey(prefix string, params ...string) string {
combined := prefix + strings.Join(params, ":")
hash := sha256.Sum256([]byte(combined))
return prefix + ":" + hex.EncodeToString(hash[:])
}Beneficios:
- ✅ Reduce costos de API (DeepSeek es pagado)
- ✅ Respuestas instantáneas en cache HIT
- ✅ Persistencia entre reinicios (AOF enabled)
- ✅ TTL configurable por tipo de contenido
services:
backend: # Go API + FFmpeg + yt-dlp
redis: # Cache layer
# ollama: # Optional local AI- Base:
golang:1.21-alpine(build) →alpine:latest(runtime) - Multi-stage build: Reduce imagen final de ~1GB a ~200MB
- Instalaciones:
- FFmpeg (procesamiento de video)
- Python3 + yt-dlp (descargas de YouTube)
- Fuentes del sistema para subtítulos
- Volúmenes:
./storage:/app/storage- Videos, clips, DB./binaries:/app/binaries- Binarios opcionales
- Image:
redis:7-alpine - Persistencia: Append-only file (AOF)
- Volume:
redis-data:/data - Health check:
redis-cli pingcada 5s - Networking: Accesible como
redis:6379dentro de la red Docker
Backend (.env):
# IA APIs
DEEPSEEK_API_KEY=sk-xxx
OPENAI_API_KEY=sk-xxx
# Redis
REDIS_HOST=redis
REDIS_PORT=6379
CACHE_TTL=86400
# Storage
STORAGE_PATH=/app/storage
DB_PATH=/app/storage/database.db
# Processing
MAX_VIDEO_DURATION=3600
MAX_CONCURRENT_JOBS=2
WHISPER_MODEL=base# Verificar que Redis está corriendo
docker-compose ps
# Ver logs de Redis
docker-compose logs redis
# Verificar conectividad
docker-compose exec backend ping redis- Verificar
OPENAI_API_KEYen.env - Comprobar límites de API de OpenAI
- Revisar logs:
docker-compose logs backend | grep Whisper
- Aumentar
CACHE_TTLsi expira muy rápido - Verificar
DEEPSEEK_API_KEYválido - Revisar logs con:
docker-compose logs backend | grep DeepSeek - El prompt puede ser muy largo (>16k tokens) - reducir duración de video
- Verificar que el navegador soporta SharedArrayBuffer
- Usar Chrome/Edge/Firefox moderno
- Limpiar cache del navegador
- Verificar que
static/ffmpeg/tiene los archivos core
- Verificar que yt-dlp está actualizado en el container
- Algunas URLs de YouTube requieren autenticación
- Revisar logs:
docker-compose logs backend | grep yt-dlp
- Soporte para múltiples videos en batch
- Templates de subtítulos animados (kinetic typography)
- Export directo a TikTok/Instagram/YouTube
- Dashboard de analytics de clips exportados
- Multi-language support (UI en inglés, español, etc.)
- Background music library integration
- Auto B-roll suggestions
- Face detection para auto-framing
- Voice cloning para doblajes
- A/B testing de títulos y thumbnails
MIT License - Ver archivo LICENSE para más detalles.
Las contribuciones son bienvenidas! Por favor:
- Fork el repositorio
- Crea una rama para tu feature (
git checkout -b feature/AmazingFeature) - Commit tus cambios (
git commit -m 'Add: AmazingFeature') - Push a la rama (
git push origin feature/AmazingFeature) - Abre un Pull Request
- Mantén el código limpio y bien documentado
- Añade tests para nuevas funcionalidades
- Actualiza el README si añades endpoints o features
- Sigue los estilos de código existentes (gofmt para Go, prettier para TS)
backsoul
- GitHub: @backsoul
- OpenAI por Whisper API
- DeepSeek por su excelente modelo de chat
- La comunidad de SvelteKit y Go
- FFmpeg y yt-dlp por hacer posible el procesamiento de video
Hecho con ❤️ para creadores de contenido que quieren maximizar su alcance en plataformas de video corto.