API para análise de vídeos usando OpenRouter e processamento assíncrono com Celery + Redis.
- Docker & Docker Compose instalados
- OpenRouter API Key (obtém em https://openrouter.ai)
- Clone o repositório ou navegue até o diretório
cd video-to-text- Crie arquivo
.envcom sua API key
cp .env.example .env
# Edite .env e adicione sua OPENROUTER_API_KEYArquivo .env:
OPENROUTER_API_KEY=sk-or-xxxxx-xxxxx
OPENROUTER_MODEL=google/gemini-2.5-flash-lite
REDIS_HOST=redis
DEBUG=true- Inicie os containers
docker-compose up -dIsso vai iniciar:
- Redis (porta 6379) - Cache e message broker
- FastAPI (porta 8000) - API principal
- Celery Worker - Processamento de vídeos em background
- Flower (porta 5555) - Dashboard de monitoramento (opcional)
- Verifique que tudo está rodando
# Health check da API
curl http://localhost:8000/health
# Documentação da API
# Abra: http://localhost:8000/docscurl -X POST http://localhost:8000/api/v1/jobs \
-H "Content-Type: application/json" \
-d '{
"video_url": "http://localhost:8000/api/v1/videos/sample.mp4",
"options": {
"analysis_depth": "detailed",
"include_timestamps": true,
"language": "pt-BR",
"extract_entities": true,
"detect_sentiment": false
}
}'Opções disponíveis:
analysis_depth:quick(concisa) |standard(padrão) |detailed(muito detalhada)include_timestamps:true|false- Incluir timestamps de momentos-chavelanguage:pt-BR,en-US,es-ES, etc. - Idioma da análiseextract_entities:true|false- Extrair pessoas, objetos, locaisdetect_sentiment:true|false- Detectar sentimento/tom do vídeo
curl -X POST http://localhost:8000/api/v1/jobs \
-H "Content-Type: application/json" \
-d '{
"video_url": "http://localhost:8000/api/v1/videos/sample.mp4",
"custom_prompt": "Analise este vídeo e forneça: 1) Resumo em 3 frases, 2) Tópicos principais em bullet points, 3) Conclusão. Seja conciso e direto."
}'Quando usar custom_prompt:
- Você quer controle total sobre as instruções de análise
- Precisa de um formato específico que não se encaixa nas opções predefinidas
- Quer instruções em múltiplos idiomas ou com lógica customizada
- Se
custom_promptfor fornecido, as opçõesoptionsserão ignoradas
file:///
Resposta:
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"created_at": "2025-11-28T10:30:00Z",
"estimated_time_seconds": 180,
"_links": {
"self": "/api/v1/jobs/550e8400-e29b-41d4-a716-446655440000",
"status": "/api/v1/jobs/550e8400-e29b-41d4-a716-446655440000",
"cancel": "/api/v1/jobs/550e8400-e29b-41d4-a716-446655440000/cancel"
}
}curl http://localhost:8000/api/v1/jobs/550e8400-e29b-41d4-a716-446655440000Resposta (quando processing):
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "processing",
"created_at": "2025-11-28T10:30:00Z",
...
}Resposta (quando completed):
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"created_at": "2025-11-28T10:30:00Z",
"completed_at": "2025-11-28T10:32:30Z",
"processing_time_seconds": 150.5,
"result": {
"video_metadata": {
"duration_seconds": 180.0,
"resolution": "1920x1080",
"format": "mp4",
"size_bytes": 45000000,
"fps": 30.0,
"codec": "h264"
},
"analysis": {
"markdown": "# Análise do Vídeo\n\n## Resumo\n\n...",
"summary": "Vídeo tutorial sobre programação...",
"metadata": {
"language_detected": "pt-BR",
"topics": ["tecnologia", "programação"],
"sentiment": "positive"
}
},
"ai_provider": {
"provider": "openrouter",
"model": "google/gemini-2.5-flash-lite",
"tokens_used": 1523,
"processing_time_ms": 3200
}
},
"_links": { ... }
}curl -X DELETE http://localhost:8000/api/v1/jobs/550e8400-e29b-41d4-a716-446655440000curl http://localhost:8000/api/v1/jobsAcesse a documentação interativa em:
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
Para monitorar workers e tasks em tempo real:
http://localhost:5555
# Logs da API
docker-compose logs api -f
# Logs do worker
docker-compose logs celery_worker -f
# Logs do Redis
docker-compose logs redis -f# Cria virtual env
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# Instala dependências
pip install -r requirements.txt
# Instala redis (macOS): brew install redis
# Windows: choco install redis-64 ou use docker pull redis
# Inicia Redis (se local)
redis-server
# Inicia API (terminal 1)
uvicorn app.main:app --reload
# Inicia Celery worker (terminal 2)
celery -A app.workers.tasks worker --loglevel=infovideo-to-text/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI app
│ ├── config.py # Configurações
│ ├── core/
│ │ ├── exceptions.py # Exceções customizadas
│ │ └── circuit_breaker.py # Circuit breaker
│ ├── models/
│ │ ├── requests.py # Schemas de entrada
│ │ └── responses.py # Schemas de saída
│ ├── services/
│ │ ├── openrouter_client.py # Cliente OpenRouter
│ │ └── video_processor.py # Processamento de vídeo
│ ├── api/
│ │ └── v1/
│ │ └── routes/
│ │ └── videos.py # Endpoints
│ └── workers/
│ ├── celery_app.py # Config Celery
│ └── tasks.py # Tasks assíncronas
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── .env.example
└── README.md
| Variável | Padrão | Descrição |
|---|---|---|
OPENROUTER_API_KEY |
- | Sua chave da API OpenRouter (obrigatório) |
OPENROUTER_MODEL |
google/gemini-2.5-flash-lite |
Modelo a usar (com suporte a vídeo) |
REDIS_HOST |
redis |
Host do Redis |
REDIS_PORT |
6379 |
Porta do Redis |
DEBUG |
true |
Modo debug |
MAX_VIDEO_SIZE_MB |
500 |
Tamanho máximo de vídeo |
Certifique-se que o Redis está rodando:
docker-compose up redis -dAdicione sua API key no arquivo .env:
OPENROUTER_API_KEY=sk-or-xxxxx-xxxxxInstale através de pip:
pip install opencv-pythonVerifique se a URL está correta. Deve usar protocolo HTTP ou HTTPS:
- ✅
http://localhost:8000/api/v1/videos/sample.mp4(local) - ✅
https://example.com/videos/sample.mp4(remoto) - ✅
http://example.com/videos/sample.mp4(remoto) - ❌
file:///C:/videos/sample.mp4(não suportado) - ❌
C:/videos/sample.mp4(não suportado)
Para servir vídeos localmente, use o endpoint de files da API:
# Listar vídeos disponíveis
curl http://localhost:8000/api/v1/videos
# Fazer download
curl http://localhost:8000/api/v1/videos/sample.mp4 -o sample.mp41. Cliente submete vídeo → POST /api/v1/jobs
↓
2. API enfileira task → Celery + Redis
↓
3. Retorna job_id → HTTP 202 (Accepted)
↓
4. Worker processa em background:
a. Valida vídeo
b. Extrai metadados
c. Chama OpenRouter API
d. Armazena resultado no Redis
↓
5. Cliente consulta → GET /api/v1/jobs/{job_id}
↓
6. Retorna resultado quando pronto
A API aceita URLs HTTP/HTTPS para vídeos:
- Local:
http://localhost:8000/api/v1/videos/sample.mp4(servido pela própria API) - Remoto:
https://example.com/videos/sample.mp4(qualquer servidor HTTP/HTTPS)
file:// não são suportadas. A API trabalha apenas com URLs HTTP/HTTPS.
O modelo google/gemini-2.5-flash-lite tem limite de tokens. Para análises mais detalhadas, vídeos muito longos podem resultar em análises resumidas.
- Vídeos pequenos (< 30s): ~30-60 segundos
- Vídeos médios (30s-5m): 1-3 minutos
- Vídeos grandes (> 5m): 3-10 minutos
Sinta-se livre para abrir issues ou PRs para melhorias!
MIT