TubeScript-API/SOLUCION_HTTP_429_TRANSCRIPT.md

292 lines
8.5 KiB
Markdown

# 🎯 Solución HTTP 429 - Extracción de Subtítulos YouTube
## 📋 Estado Actual
### ✅ Implementado
- ✅ Endpoint `/transcript/{video_id}` - Obtiene transcript parseado (segmentos + texto)
- ✅ Endpoint `/transcript_vtt/{video_id}` - Descarga VTT con yt-dlp y devuelve crudo + parseado
- ✅ Endpoint `/stream/{video_id}` - Obtiene URL m3u8 para streaming
- ✅ Endpoint `/upload_vtt/{video_id}` - Permite subir VTT manualmente y parsearlo
- ✅ Endpoint `/debug/metadata/{video_id}` - Muestra metadata de yt-dlp
- ✅ Endpoint `/debug/fetch_subs/{video_id}` - Intenta descargar con verbose y devuelve logs
- ✅ Soporte de cookies (`API_COOKIES_PATH=/app/cookies.txt`)
- ✅ Soporte de proxy (`API_PROXY=socks5h://127.0.0.1:9050`)
- ✅ Script `fetch_transcript.py` - CLI para obtener transcript y guardarlo en JSON/TXT
- ✅ Script `docker-update-ytdlp.sh` - Actualiza yt-dlp en contenedores sin rebuild
### ❌ Problema Actual
**HTTP Error 429: Too Many Requests** al intentar descargar subtítulos desde YouTube.
- **Causa**: YouTube está limitando peticiones al endpoint `timedtext` desde tu IP
- **Afectado**: Tanto `requests` como `yt-dlp` reciben 429
- **Ocurre**: Al intentar descargar subtítulos automáticos (ASR) de videos
## 🔧 Soluciones Disponibles
### Opción 1: Usar Proxy/Tor (Recomendado)
Evita el rate-limit cambiando la IP de salida.
#### Setup rápido con Tor:
```bash
# Instalar Tor
brew install tor # macOS
# sudo apt install tor # Linux
# Iniciar Tor
tor &
# Exportar proxy y arrancar API
export API_PROXY="socks5h://127.0.0.1:9050"
docker compose -f docker-compose.yml up -d --build tubescript-api
# Probar
curl "http://127.0.0.1:8000/transcript_vtt/K08TM4OVLyo?lang=es" | jq .
```
### Opción 2: Usar Cookies Directamente desde Chrome/Firefox (Recomendado)
`yt-dlp` puede leer cookies directamente desde tu navegador sin necesidad de exportarlas.
#### Opción 2A: Usar cookies del navegador directamente
```bash
# Chrome (macOS)
yt-dlp --cookies-from-browser chrome --skip-download --write-auto-sub \
--sub-lang es --sub-format vtt -o "%(id)s.%(ext)s" \
"https://www.youtube.com/watch?v=VIDEO_ID"
# Chrome con perfil específico
yt-dlp --cookies-from-browser chrome:Profile1 --skip-download --write-auto-sub \
--sub-lang es --sub-format vtt -o "%(id)s.%(ext)s" \
"https://www.youtube.com/watch?v=VIDEO_ID"
# Firefox
yt-dlp --cookies-from-browser firefox --skip-download --write-auto-sub \
--sub-lang es --sub-format vtt -o "%(id)s.%(ext)s" \
"https://www.youtube.com/watch?v=VIDEO_ID"
# Brave
yt-dlp --cookies-from-browser brave --skip-download --write-auto-sub \
--sub-lang es --sub-format vtt -o "%(id)s.%(ext)s" \
"https://www.youtube.com/watch?v=VIDEO_ID"
```
**Encontrar perfiles de Chrome:**
```bash
# macOS
ls -la ~/Library/Application\ Support/Google/Chrome/
# Linux
ls -la ~/.config/google-chrome/
# Los perfiles típicos son: Default, Profile 1, Profile 2, etc.
```
#### Opción 2B: Exportar cookies manualmente (si la opción 2A no funciona)
1. Instala extensión "cookies.txt" en Chrome/Firefox
2. Abre YouTube estando logueado en tu cuenta
3. Exporta cookies (extensión → Export → `cookies.txt`)
4. Reemplaza `./cookies.txt` en la raíz del proyecto
5. Reinicia contenedor:
```bash
docker compose down
docker compose up -d --build tubescript-api
```
### Opción 3: Cambiar de IP
- Usar VPN
- Tethering móvil (4G/5G)
- Esperar algunas horas (el rate-limit puede ser temporal)
### Opción 4: Workaround Manual (Más Rápido)
Si necesitas el transcript YA y no puedes resolver el 429:
#### Opción 4A: Subir VTT manualmente al API
```bash
# Descarga el VTT desde otro equipo/navegador donde no esté bloqueado
# o pídele a alguien que te lo pase
# Súbelo al API
curl -X POST "http://127.0.0.1:8000/upload_vtt/VIDEO_ID" \
-H "Content-Type: multipart/form-data" \
-F "file=@/ruta/al/archivo.vtt" | jq .
# El API responde con: { segments, text, count, path }
```
#### Opción 4B: Usar youtube-transcript-api (Python alternativo)
```bash
pip install youtube-transcript-api
python3 << 'EOF'
from youtube_transcript_api import YouTubeTranscriptApi
import json
video_id = "K08TM4OVLyo"
try:
transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=['es'])
with open(f"{video_id}_transcript.json", 'w', encoding='utf-8') as f:
json.dump(transcript, f, ensure_ascii=False, indent=2)
print(f"✅ Guardado: {video_id}_transcript.json")
except Exception as e:
print(f"❌ Error: {e}")
EOF
```
#### Opción 4C: Script usando cookies desde Chrome directamente
```bash
# Crear script que usa cookies del navegador
cat > get_transcript_chrome.sh << 'SCRIPT'
#!/bin/bash
VIDEO_ID="${1:-K08TM4OVLyo}"
LANG="${2:-es}"
BROWSER="${3:-chrome}" # chrome, firefox, brave, etc.
echo "🔍 Obteniendo transcript de: $VIDEO_ID"
echo " Idioma: $LANG"
echo " Navegador: $BROWSER"
yt-dlp --cookies-from-browser "$BROWSER" \
--skip-download --write-auto-sub \
--sub-lang "$LANG" --sub-format vtt \
-o "%(id)s.%(ext)s" \
"https://www.youtube.com/watch?v=$VIDEO_ID" 2>&1 | grep -E "Writing|ERROR|✓"
if [ -f "${VIDEO_ID}.${LANG}.vtt" ]; then
echo "✅ Archivo generado: ${VIDEO_ID}.${LANG}.vtt"
echo "📝 Primeras líneas:"
head -n 20 "${VIDEO_ID}.${LANG}.vtt"
else
echo "❌ No se generó el archivo VTT"
fi
SCRIPT
chmod +x get_transcript_chrome.sh
# Usar el script
./get_transcript_chrome.sh VIDEO_ID es chrome
```
## 📚 Uso de Endpoints
### 1. Obtener Transcript (intenta automáticamente con yt-dlp)
```bash
curl "http://127.0.0.1:8000/transcript/K08TM4OVLyo?lang=es" | jq .
```
Respuesta:
```json
{
"video_id": "K08TM4OVLyo",
"count": 150,
"segments": [...],
"text": "texto concatenado de todos los segmentos"
}
```
### 2. Obtener VTT Crudo + Parseado
```bash
curl "http://127.0.0.1:8000/transcript_vtt/K08TM4OVLyo?lang=es" | jq .
```
Respuesta:
```json
{
"video_id": "K08TM4OVLyo",
"vtt": "WEBVTT\n\n00:00:00.000 --> 00:00:02.000\nHola...",
"count": 150,
"segments": [...],
"text": "..."
}
```
### 3. Debug: Ver Metadata
```bash
curl "http://127.0.0.1:8000/debug/metadata/K08TM4OVLyo" | jq .
```
### 4. Debug: Intentar Descarga Verbose
```bash
curl "http://127.0.0.1:8000/debug/fetch_subs/K08TM4OVLyo?lang=es" | jq .
```
Respuesta incluye:
- `rc`: código de salida de yt-dlp
- `stdout_tail`: últimas 2000 chars de stdout
- `stderr_tail`: últimas 2000 chars de stderr (aquí verás "HTTP Error 429")
- `generated`: lista de archivos generados (si hubo éxito)
### 5. Subir VTT Manualmente
```bash
curl -X POST "http://127.0.0.1:8000/upload_vtt/K08TM4OVLyo" \
-F "file=@K08TM4OVLyo.vtt" | jq .
```
## 🐳 Docker
### Comandos útiles
```bash
# Rebuild y levantar (aplica cambios en main.py)
docker compose -f docker-compose.yml build --no-cache tubescript-api
docker compose -f docker-compose.yml up -d tubescript-api
# Ver logs
docker logs -f tubescript_api
# Actualizar yt-dlp (sin rebuild)
bash docker-update-ytdlp.sh
# Entrar al contenedor
docker exec -it tubescript_api /bin/sh
# Verificar cookies montadas
docker exec -it tubescript_api cat /app/cookies.txt | head -n 10
```
### Variables de Entorno
```yaml
environment:
- API_COOKIES_PATH=/app/cookies.txt
- API_PROXY=socks5h://127.0.0.1:9050 # opcional
```
## 🔍 Diagnóstico
### Verificar HTTP 429
```bash
# Host (local)
yt-dlp --verbose --skip-download --write-auto-sub \
--sub-lang es --sub-format vtt \
--cookies ./cookies.txt -o "%(id)s.%(ext)s" \
"https://www.youtube.com/watch?v=K08TM4OVLyo" 2>&1 | grep -i "error\|429"
# Dentro del contenedor
docker exec -it tubescript_api sh -c \
"yt-dlp --verbose --skip-download --write-auto-sub \
--sub-lang es --sub-format vtt \
--cookies /app/cookies.txt -o '/tmp/%(id)s.%(ext)s' \
'https://www.youtube.com/watch?v=K08TM4OVLyo'" 2>&1 | grep -i "error\|429"
```
### Probar con otro video
```bash
# Prueba con un video de noticias 24/7 (menos probabilidad de 429)
curl "http://127.0.0.1:8000/transcript/NNL3iiDf1HI?lang=es" | jq .
```
## 📖 Referencias
- [yt-dlp GitHub](https://github.com/yt-dlp/yt-dlp)
- [Guía PO Token (si yt-dlp requiere)](https://github.com/yt-dlp/yt-dlp/wiki/PO-Token-Guide)
- [youtube-transcript-api](https://github.com/jdepoix/youtube-transcript-api)
## 🎯 Próximos Pasos
1. **Inmediato**: Probar Opción 1 (Tor) o Opción 4B (youtube-transcript-api)
2. **Corto plazo**: Re-exportar cookies válidas (Opción 2)
3. **Mediano plazo**: Implementar rotación de IPs/proxies automática
4. **Largo plazo**: Considerar usar YouTube Data API v3 (requiere API key pero evita rate-limits)
---
**Última actualización**: 2025-02-22
**Estado**: HTTP 429 confirmado; soluciones alternativas implementadas