No description
- Python 61.7%
- JavaScript 17.6%
- CSS 11.2%
- HTML 7.6%
- Dockerfile 1.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| backend | ||
| frontend | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| README.md | ||
MediaForgeRG
MVP self-hosted para obter metadados e converter URLs de plataformas suportadas e ficheiros locais para MP3 ou MP4, pensado para publicação futura em:
https://tools.ruiguimaraes.net/mediaforgerg/
Funcionalidades
| Área | Estado |
|---|---|
| Frontend HTML/CSS/JS servido pela app FastAPI | Implementado |
Preview/metadados via yt-dlp e ffprobe |
Implementado |
| Origem por URL online ou ficheiro local | Implementado |
| MP3 128/192/256/320 kbps | Implementado |
| MP4 720p/1080p/best | Implementado |
| Progresso e estado por job | Implementado |
Ficheiros temporários em tmpfs |
Implementado no Compose |
| Limpeza automática por TTL | Implementado |
| Health endpoint | GET /healthz |
| Reverse proxy em subpath | Preparado com MEDIAFORGERG_ROOT_PATH=/mediaforgerg |
| SSRF básico | Bloqueio de hosts não permitidos e IPs privados/locais |
Execução local
cd D:\Git\it-tools\mediaforgerg
docker compose up --build
Abrir:
http://localhost:8088/
O mesmo container fica preparado para receber X-Forwarded-* do reverse proxy e root_path=/mediaforgerg.
API
| Endpoint | Método | Função |
|---|---|---|
/healthz |
GET |
Healthcheck |
/api/metadata |
POST |
Obtém metadados/preview |
/api/local/metadata |
POST |
Obtém preview de ficheiro local |
/api/jobs |
POST |
Cria conversão |
/api/local/jobs |
POST |
Cria conversão a partir de ficheiro local |
/api/jobs/{id} |
GET |
Consulta progresso/estado |
/api/jobs/{id}/download |
GET |
Descarrega resultado |
Exemplo:
Invoke-RestMethod `
-Method Post `
-Uri 'http://localhost:8088/api/metadata' `
-ContentType 'application/json' `
-Body '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'
Configuração
| Variável | Default | Descrição |
|---|---|---|
MEDIAFORGERG_ROOT_PATH |
/mediaforgerg |
Base path usado atrás do reverse proxy |
MEDIAFORGERG_TEMP_ROOT |
/tmp/mediaforgerg |
Diretoria temporária |
MEDIAFORGERG_JOB_TTL_SECONDS |
3600 |
Tempo de vida dos jobs/ficheiros |
MEDIAFORGERG_CLEANUP_INTERVAL_SECONDS |
300 |
Intervalo da limpeza automática |
MEDIAFORGERG_METADATA_TIMEOUT_SECONDS |
45 |
Timeout para metadados |
MEDIAFORGERG_DOWNLOAD_TIMEOUT_SECONDS |
1800 |
Timeout para download/conversão |
MEDIAFORGERG_MAX_DURATION_SECONDS |
10800 |
Duração máxima aceite |
MEDIAFORGERG_MAX_OUTPUT_SIZE_MB |
10240 |
Tamanho máximo do ficheiro final |
MEDIAFORGERG_MAX_CONCURRENT_JOBS |
2 |
Conversões simultâneas |
MEDIAFORGERG_ALLOW_PLAYLISTS |
false |
Permitir playlists |
MEDIAFORGERG_ALLOWED_HOST_SUFFIXES |
["youtube.com","youtu.be","youtube-nocookie.com","soundcloud.com","vimeo.com","player.vimeo.com","dailymotion.com","dai.ly","twitch.tv","clips.twitch.tv","tiktok.com","vm.tiktok.com","reddit.com","redd.it","v.redd.it"] |
Hosts permitidos para URLs online |
Reverse proxy Apache em subpath
Exemplo para publicar depois em https://tools.ruiguimaraes.net/mediaforgerg/:
ProxyPreserveHost On
ProxyPass /mediaforgerg/ http://127.0.0.1:8088/
ProxyPassReverse /mediaforgerg/ http://127.0.0.1:8088/
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Prefix "/mediaforgerg"
Se o reverse proxy remover o prefixo /mediaforgerg/, manter MEDIAFORGERG_ROOT_PATH=/mediaforgerg. Se passar o prefixo até ao backend sem o remover, a configuração deve ser ajustada.
Segurança e limitações
- O serviço deve ficar atrás de autenticação no homelab, por exemplo Authentik.
- A validação SSRF implementada bloqueia IPs privados/locais e restringe hosts permitidos para URLs online, mas não substitui isolamento de rede no container/firewall.
- Playlists estão desativadas por defeito.
- Ficheiros locais são carregados para a área temporária do job e removidos no fim ou por TTL.
- Algumas origens podem exigir cookies/autenticação do lado do
yt-dlpmesmo estando na whitelist, como aconteceu no teste de Vimeo a 27 de agosto de 2026. - Os ficheiros são temporários e removidos por TTL.
- O container corre sem privilégios, com
read_only: true,no-new-privilegesecap_drop: ALL. yt-dlpdepende dos sites de origem; quebras por alterações no YouTube/SoundCloud são esperadas ao longo do tempo.- A utilização deve respeitar direitos de autor, termos dos serviços de origem e legislação aplicável.
Validação rápida
docker compose up --build -d
Invoke-RestMethod http://localhost:8088/healthz
Invoke-RestMethod `
-Method Post `
-Uri 'http://localhost:8088/api/metadata' `
-ContentType 'application/json' `
-Body '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'
docker compose logs --tail=100
docker compose down