529 lines
11 KiB
Markdown
529 lines
11 KiB
Markdown
# 🔌 API Endpoints - Ejemplos de Uso
|
|
|
|
Esta guía muestra cómo usar la API de TubeScript desde la línea de comandos, scripts o aplicaciones externas.
|
|
|
|
## 🌐 Base URL
|
|
|
|
```
|
|
http://localhost:8080
|
|
```
|
|
|
|
O en producción:
|
|
```
|
|
https://api.tudominio.com
|
|
```
|
|
|
|
---
|
|
|
|
## 📡 Endpoints Disponibles
|
|
|
|
### 1. Obtener URL de Stream (m3u8)
|
|
|
|
**Endpoint:**
|
|
```
|
|
GET /stream/{video_id}
|
|
```
|
|
|
|
**Descripción:**
|
|
Obtiene la URL HLS/m3u8 de un video en vivo de YouTube para usar con FFmpeg.
|
|
|
|
**Parámetros:**
|
|
- `video_id` (path): ID del video de YouTube
|
|
|
|
**Ejemplo con cURL:**
|
|
```bash
|
|
# Video ID de ejemplo
|
|
VIDEO_ID="G01-33V6I2g"
|
|
|
|
# Obtener URL del stream
|
|
curl -X GET "http://localhost:8080/stream/${VIDEO_ID}"
|
|
```
|
|
|
|
**Respuesta exitosa (200):**
|
|
```json
|
|
{
|
|
"video_id": "G01-33V6I2g",
|
|
"stream_url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/...",
|
|
"url_type": "m3u8/hls",
|
|
"youtube_url": "https://www.youtube.com/watch?v=G01-33V6I2g",
|
|
"ffmpeg_example": "ffmpeg -re -i \"https://manifest.googlevideo.com/...\" -c copy -f flv rtmp://destino/stream_key",
|
|
"usage": {
|
|
"description": "Usa stream_url con FFmpeg para retransmitir",
|
|
"command_template": "ffmpeg -re -i \"{stream_url}\" -c copy -f flv {rtmp_url}/{stream_key}",
|
|
"platforms": {
|
|
"youtube": "rtmp://a.rtmp.youtube.com/live2/YOUR_STREAM_KEY",
|
|
"facebook": "rtmps://live-api-s.facebook.com:443/rtmp/YOUR_STREAM_KEY",
|
|
"twitch": "rtmp://live.twitch.tv/app/YOUR_STREAM_KEY",
|
|
"twitter": "rtmps://fa.contribute.live-video.net/app/YOUR_STREAM_KEY"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Respuesta de error (400):**
|
|
```json
|
|
{
|
|
"detail": "No se pudo obtener la URL del stream. Verifica que el video esté EN VIVO (🔴) y no tenga restricciones."
|
|
}
|
|
```
|
|
|
|
### 2. Obtener Transcripción/Subtítulos
|
|
|
|
**Endpoint:**
|
|
```
|
|
GET /transcript/{video_id}?lang={idioma}
|
|
```
|
|
|
|
**Descripción:**
|
|
Obtiene los subtítulos/transcripción de un video de YouTube.
|
|
|
|
**Parámetros:**
|
|
- `video_id` (path): ID del video de YouTube
|
|
- `lang` (query, opcional): Código de idioma (default: "es")
|
|
|
|
**Ejemplo con cURL:**
|
|
```bash
|
|
# Subtítulos en español
|
|
curl -X GET "http://localhost:8080/transcript/WODSeZfCnUg?lang=es"
|
|
|
|
# Subtítulos en inglés
|
|
curl -X GET "http://localhost:8080/transcript/WODSeZfCnUg?lang=en"
|
|
```
|
|
|
|
**Respuesta exitosa (200):**
|
|
```json
|
|
{
|
|
"video_id": "WODSeZfCnUg",
|
|
"count": 150,
|
|
"segments": [
|
|
{
|
|
"start": 0.0,
|
|
"duration": 2.5,
|
|
"text": "Hola y bienvenidos"
|
|
},
|
|
{
|
|
"start": 2.5,
|
|
"duration": 3.0,
|
|
"text": "al video de hoy"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**Respuesta de error (400):**
|
|
```json
|
|
{
|
|
"detail": "No se encontraron subtítulos para el idioma 'es'. El video puede no tener subtítulos disponibles."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 Casos de Uso
|
|
|
|
### Caso 1: Retransmitir a Facebook
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
# 1. Obtener URL del stream
|
|
VIDEO_ID="G01-33V6I2g"
|
|
RESPONSE=$(curl -s "http://localhost:8080/stream/${VIDEO_ID}")
|
|
|
|
# 2. Extraer la URL del stream
|
|
STREAM_URL=$(echo "$RESPONSE" | jq -r '.stream_url')
|
|
|
|
# 3. Configurar destino
|
|
FACEBOOK_RTMP="rtmps://live-api-s.facebook.com:443/rtmp/"
|
|
STREAM_KEY="TU_STREAM_KEY_DE_FACEBOOK"
|
|
|
|
# 4. Iniciar transmisión con FFmpeg
|
|
ffmpeg -re -i "$STREAM_URL" \
|
|
-c copy \
|
|
-f flv \
|
|
"${FACEBOOK_RTMP}${STREAM_KEY}"
|
|
```
|
|
|
|
### Caso 2: Retransmitir a Múltiples Plataformas
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
# Obtener URL del stream
|
|
VIDEO_ID="G01-33V6I2g"
|
|
RESPONSE=$(curl -s "http://localhost:8080/stream/${VIDEO_ID}")
|
|
STREAM_URL=$(echo "$RESPONSE" | jq -r '.stream_url')
|
|
|
|
# Configuración de plataformas
|
|
YOUTUBE_KEY="tu_youtube_key"
|
|
FACEBOOK_KEY="tu_facebook_key"
|
|
TWITCH_KEY="tu_twitch_key"
|
|
|
|
# Iniciar transmisiones en segundo plano
|
|
ffmpeg -re -i "$STREAM_URL" -c copy -f flv \
|
|
"rtmp://a.rtmp.youtube.com/live2/${YOUTUBE_KEY}" &
|
|
|
|
ffmpeg -re -i "$STREAM_URL" -c copy -f flv \
|
|
"rtmps://live-api-s.facebook.com:443/rtmp/${FACEBOOK_KEY}" &
|
|
|
|
ffmpeg -re -i "$STREAM_URL" -c copy -f flv \
|
|
"rtmp://live.twitch.tv/app/${TWITCH_KEY}" &
|
|
|
|
echo "Transmisiones iniciadas en segundo plano"
|
|
```
|
|
|
|
### Caso 3: Obtener Transcripción para Análisis
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
# Obtener transcripción
|
|
VIDEO_ID="WODSeZfCnUg"
|
|
curl -s "http://localhost:8080/transcript/${VIDEO_ID}?lang=es" \
|
|
| jq '.segments[] | "\(.start)s: \(.text)"' \
|
|
> transcripcion.txt
|
|
|
|
echo "Transcripción guardada en transcripcion.txt"
|
|
```
|
|
|
|
### Caso 4: Verificar si un Video Está en Vivo
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
VIDEO_ID="G01-33V6I2g"
|
|
|
|
# Intentar obtener stream
|
|
RESPONSE=$(curl -s -w "\n%{http_code}" "http://localhost:8080/stream/${VIDEO_ID}")
|
|
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
|
|
|
if [ "$HTTP_CODE" -eq 200 ]; then
|
|
echo "✅ Video está en vivo"
|
|
echo "$RESPONSE" | head -n-1 | jq .
|
|
else
|
|
echo "❌ Video no está en vivo o hay un error"
|
|
echo "$RESPONSE" | head -n-1 | jq .
|
|
fi
|
|
```
|
|
|
|
---
|
|
|
|
## 🐍 Ejemplos en Python
|
|
|
|
### Obtener Stream URL
|
|
|
|
```python
|
|
import requests
|
|
import json
|
|
|
|
def get_stream_url(video_id):
|
|
"""Obtiene la URL del stream m3u8 de YouTube"""
|
|
url = f"http://localhost:8080/stream/{video_id}"
|
|
|
|
try:
|
|
response = requests.get(url)
|
|
response.raise_for_status()
|
|
|
|
data = response.json()
|
|
return data['stream_url']
|
|
|
|
except requests.exceptions.HTTPError as e:
|
|
print(f"Error: {e}")
|
|
print(f"Detalle: {response.json().get('detail')}")
|
|
return None
|
|
|
|
# Uso
|
|
video_id = "G01-33V6I2g"
|
|
stream_url = get_stream_url(video_id)
|
|
|
|
if stream_url:
|
|
print(f"Stream URL: {stream_url}")
|
|
```
|
|
|
|
### Iniciar Transmisión con subprocess
|
|
|
|
```python
|
|
import requests
|
|
import subprocess
|
|
import json
|
|
|
|
def start_restream(video_id, rtmp_url, stream_key):
|
|
"""Inicia una retransmisión usando FFmpeg"""
|
|
|
|
# 1. Obtener URL del stream
|
|
api_url = f"http://localhost:8080/stream/{video_id}"
|
|
response = requests.get(api_url)
|
|
|
|
if response.status_code != 200:
|
|
print(f"Error: {response.json().get('detail')}")
|
|
return None
|
|
|
|
stream_url = response.json()['stream_url']
|
|
|
|
# 2. Construir comando FFmpeg
|
|
full_rtmp = f"{rtmp_url}/{stream_key}"
|
|
|
|
command = [
|
|
'ffmpeg',
|
|
'-re',
|
|
'-i', stream_url,
|
|
'-c', 'copy',
|
|
'-f', 'flv',
|
|
full_rtmp
|
|
]
|
|
|
|
# 3. Iniciar proceso
|
|
process = subprocess.Popen(
|
|
command,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE
|
|
)
|
|
|
|
print(f"Transmisión iniciada (PID: {process.pid})")
|
|
return process
|
|
|
|
# Uso
|
|
video_id = "G01-33V6I2g"
|
|
rtmp_url = "rtmps://live-api-s.facebook.com:443/rtmp"
|
|
stream_key = "TU_STREAM_KEY"
|
|
|
|
process = start_restream(video_id, rtmp_url, stream_key)
|
|
|
|
# Mantener el proceso corriendo
|
|
if process:
|
|
try:
|
|
process.wait()
|
|
except KeyboardInterrupt:
|
|
print("Deteniendo transmisión...")
|
|
process.terminate()
|
|
```
|
|
|
|
### Obtener Transcripción
|
|
|
|
```python
|
|
import requests
|
|
|
|
def get_transcript(video_id, lang='es'):
|
|
"""Obtiene la transcripción de un video"""
|
|
url = f"http://localhost:8080/transcript/{video_id}"
|
|
params = {'lang': lang}
|
|
|
|
try:
|
|
response = requests.get(url, params=params)
|
|
response.raise_for_status()
|
|
|
|
data = response.json()
|
|
return data['segments']
|
|
|
|
except requests.exceptions.HTTPError as e:
|
|
print(f"Error: {e}")
|
|
print(f"Detalle: {response.json().get('detail')}")
|
|
return None
|
|
|
|
# Uso
|
|
video_id = "WODSeZfCnUg"
|
|
segments = get_transcript(video_id)
|
|
|
|
if segments:
|
|
for segment in segments:
|
|
print(f"{segment['start']:.1f}s: {segment['text']}")
|
|
```
|
|
|
|
---
|
|
|
|
## 📱 Ejemplos en Node.js
|
|
|
|
### Obtener Stream URL
|
|
|
|
```javascript
|
|
const axios = require('axios');
|
|
|
|
async function getStreamUrl(videoId) {
|
|
try {
|
|
const response = await axios.get(`http://localhost:8080/stream/${videoId}`);
|
|
return response.data.stream_url;
|
|
} catch (error) {
|
|
console.error('Error:', error.response?.data?.detail || error.message);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Uso
|
|
getStreamUrl('G01-33V6I2g').then(url => {
|
|
if (url) {
|
|
console.log('Stream URL:', url);
|
|
}
|
|
});
|
|
```
|
|
|
|
### Iniciar Transmisión
|
|
|
|
```javascript
|
|
const axios = require('axios');
|
|
const { spawn } = require('child_process');
|
|
|
|
async function startRestream(videoId, rtmpUrl, streamKey) {
|
|
try {
|
|
// 1. Obtener URL del stream
|
|
const response = await axios.get(`http://localhost:8080/stream/${videoId}`);
|
|
const streamUrl = response.data.stream_url;
|
|
|
|
// 2. Iniciar FFmpeg
|
|
const fullRtmp = `${rtmpUrl}/${streamKey}`;
|
|
|
|
const ffmpeg = spawn('ffmpeg', [
|
|
'-re',
|
|
'-i', streamUrl,
|
|
'-c', 'copy',
|
|
'-f', 'flv',
|
|
fullRtmp
|
|
]);
|
|
|
|
console.log(`Transmisión iniciada (PID: ${ffmpeg.pid})`);
|
|
|
|
// 3. Manejar salida
|
|
ffmpeg.stderr.on('data', (data) => {
|
|
console.error(`FFmpeg: ${data}`);
|
|
});
|
|
|
|
ffmpeg.on('close', (code) => {
|
|
console.log(`Proceso FFmpeg terminado con código ${code}`);
|
|
});
|
|
|
|
return ffmpeg;
|
|
|
|
} catch (error) {
|
|
console.error('Error:', error.response?.data?.detail || error.message);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Uso
|
|
startRestream(
|
|
'G01-33V6I2g',
|
|
'rtmps://live-api-s.facebook.com:443/rtmp',
|
|
'TU_STREAM_KEY'
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## 🧪 Testing con HTTPie
|
|
|
|
```bash
|
|
# Instalar HTTPie
|
|
pip install httpie
|
|
|
|
# Obtener stream
|
|
http GET localhost:8080/stream/G01-33V6I2g
|
|
|
|
# Obtener transcripción
|
|
http GET localhost:8080/transcript/WODSeZfCnUg lang==es
|
|
|
|
# Ver solo la URL del stream
|
|
http GET localhost:8080/stream/G01-33V6I2g | jq -r '.stream_url'
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Códigos de Estado HTTP
|
|
|
|
| Código | Significado | Descripción |
|
|
|--------|-------------|-------------|
|
|
| 200 | OK | Solicitud exitosa |
|
|
| 400 | Bad Request | Error en la solicitud (video no disponible, etc.) |
|
|
| 404 | Not Found | Endpoint no existe |
|
|
| 500 | Internal Server Error | Error del servidor |
|
|
|
|
---
|
|
|
|
## 🔒 Consideraciones de Seguridad
|
|
|
|
### Rate Limiting
|
|
|
|
Si vas a usar la API en producción, considera implementar rate limiting:
|
|
|
|
```python
|
|
from fastapi import FastAPI
|
|
from slowapi import Limiter, _rate_limit_exceeded_handler
|
|
from slowapi.util import get_remote_address
|
|
|
|
limiter = Limiter(key_func=get_remote_address)
|
|
app = FastAPI()
|
|
app.state.limiter = limiter
|
|
|
|
@app.get("/stream/{video_id}")
|
|
@limiter.limit("10/minute")
|
|
async def stream_endpoint(video_id: str):
|
|
# ...
|
|
```
|
|
|
|
### CORS
|
|
|
|
Para usar desde aplicaciones web:
|
|
|
|
```python
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"], # En producción, especifica dominios
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## 📚 Documentación Interactiva
|
|
|
|
La API incluye documentación interactiva:
|
|
|
|
- **Swagger UI**: http://localhost:8080/docs
|
|
- **ReDoc**: http://localhost:8080/redoc
|
|
|
|
Aquí puedes probar los endpoints directamente desde el navegador.
|
|
|
|
---
|
|
|
|
## 💡 Tips y Trucos
|
|
|
|
### Extraer solo el video_id de una URL
|
|
|
|
```bash
|
|
# Desde URL completa
|
|
URL="https://www.youtube.com/watch?v=G01-33V6I2g"
|
|
VIDEO_ID=$(echo "$URL" | grep -oP '(?<=v=)[^&]+')
|
|
echo "$VIDEO_ID"
|
|
# Salida: G01-33V6I2g
|
|
```
|
|
|
|
### Verificar que FFmpeg esté funcionando
|
|
|
|
```bash
|
|
# Iniciar transmisión y verificar proceso
|
|
ffmpeg -re -i "$STREAM_URL" -c copy -f flv "$RTMP_URL" &
|
|
PID=$!
|
|
|
|
# Verificar que esté corriendo
|
|
if ps -p $PID > /dev/null; then
|
|
echo "✅ FFmpeg está corriendo (PID: $PID)"
|
|
else
|
|
echo "❌ FFmpeg no está corriendo"
|
|
fi
|
|
```
|
|
|
|
### Guardar logs de FFmpeg
|
|
|
|
```bash
|
|
ffmpeg -re -i "$STREAM_URL" \
|
|
-c copy \
|
|
-f flv "$RTMP_URL" \
|
|
2>&1 | tee ffmpeg_$(date +%Y%m%d_%H%M%S).log
|
|
```
|
|
|
|
---
|
|
|
|
**TubeScript API © 2026**
|