9.0 KiB
Transcoder para Lidarr — Documento de Requisitos
Objetivo
Desenvolver uma aplicação em Go, executada em contêiner Docker, responsável por converter álbuns de FLAC para MP3 320 kbps CBR.
A aplicação pode ser acionada automaticamente por Webhooks enviados pelo Lidarr após a importação de um álbum, ou manualmente através da interface web. Em ambos os fluxos, realiza a conversão dos arquivos, valida o resultado, remove os arquivos FLAC originais e solicita ao Lidarr a atualização da biblioteca.
1. Requisitos Funcionais
RF-001 Recebimento de Webhooks
A aplicação deverá disponibilizar um endpoint HTTP para recebimento de Webhooks enviados pelo Lidarr.
O endpoint deverá:
- aceitar requisições POST;
- validar o payload recebido;
- extrair o caminho do álbum importado;
- registrar a solicitação no log.
RF-002 Fila de Processamento
Cada webhook recebido deverá gerar uma nova tarefa de conversão.
A aplicação deverá possuir uma fila interna para impedir que uma falha interrompa o processamento de novos álbuns.
Cada tarefa possuirá estados:
- Recebido
- Em processamento
- Concluído
- Erro
RF-003 Conversão de Áudio
Para cada arquivo FLAC encontrado no diretório informado:
- converter para MP3;
- utilizar o codec libmp3lame;
- bitrate constante (CBR);
- 320 kbps;
- preservar metadados;
- preservar capa do álbum quando existir.
RF-004 Conversão Paralela
Os arquivos deverão ser convertidos em paralelo.
A quantidade máxima de conversões simultâneas deverá ser configurável.
RF-005 Validação da Conversão
Antes da remoção dos arquivos FLAC deverá ser verificado que:
- todos os MP3 esperados foram gerados;
- o ffmpeg retornou código de sucesso;
- os arquivos possuem tamanho maior que zero;
- opcionalmente executar ffprobe para validar o arquivo.
Caso qualquer verificação falhe:
- nenhum FLAC deverá ser removido;
- a tarefa será marcada como erro.
RF-006 Limpeza
Após validação:
- remover os arquivos FLAC;
- manter demais arquivos do álbum (cover.jpg, booklet.pdf, etc.).
RF-007 Atualização do Lidarr
Após a conclusão da conversão, a aplicação deverá realizar uma chamada para a API do Lidarr solicitando um rescan do diretório.
RF-008 Registro de Logs
A aplicação deverá registrar:
- início da tarefa;
- álbum processado;
- duração;
- arquivos convertidos;
- erros;
- chamadas ao Lidarr;
- notificações enviadas.
Os logs deverão ser persistidos em SQLite e permanecer disponíveis para consulta via interface web.
RF-009 Interface Web
A aplicação deverá disponibilizar uma interface web para operação e monitoramento.
A interface deverá permitir:
Dashboard (/)
- aplicação online
- número de workers
- fila atual (incluindo tarefas retidas pela janela de trabalho)
- quantidade de tarefas
- status da janela de trabalho (ativa/inativa e horário configurado, quando habilitada)
Tarefas recentes (/jobs)
Tabela contendo:
- data
- artista
- álbum
- duração
- status
- origem (webhook ou manual)
Consulta de logs (/logs)
Visualização dos logs registrados, persistidos em SQLite.
Biblioteca / Busca de FLACs (/library)
- navegação por árvore de diretórios a partir de
MUSIC_PATH - scan recursivo com detecção automática de álbuns com arquivos FLAC
- seleção individual ou em lote dos álbuns encontrados
- botão para enfileirar a conversão dos álbuns selecionados
Configurações (/settings)
Exibição e edição das configurações persistidas, incluindo:
- workers, dry run, nível de log
- janela de trabalho (ativar/desativar, horário início/fim, timezone)
- URL e chave da API do Lidarr
- demais parâmetros operacionais
As alterações têm efeito imediato e substituem os defaults definidos por variáveis de ambiente até que sejam sobrescritas novamente.
RF-010 Modo Dry Run
Quando habilitado:
- nenhuma conversão será realizada;
- nenhum arquivo será apagado;
- nenhuma chamada ao Lidarr será executada.
Todas as ações deverão apenas ser registradas no log.
RF-011 Configuração
A configuração da aplicação é definida através de variáveis de ambiente (valores default) e pode ser sobrescrita via interface web, com persistência em SQLite.
Ao iniciar, a aplicação carrega as variáveis de ambiente como valores iniciais. Se houver configurações salvas no SQLite de execuções anteriores, estas têm prioridade.
Exemplos de variáveis de ambiente:
PORT=8080
WORKERS=4
FFMPEG_BIN=/usr/bin/ffmpeg
FFPROBE_BIN=/usr/bin/ffprobe
LOG_LEVEL=INFO
DRY_RUN=false
LIDARR_URL=http://lidarr:8686
LIDARR_API_KEY=...
WEBHOOK_SECRET=...
MUSIC_PATH=/music
DB_PATH=/data/coda.db
TIMEZONE=America/Sao_Paulo
WORK_WINDOW_ENABLED=false
WORK_WINDOW_START=08:00
WORK_WINDOW_END=18:00
NTFY_ENABLED=false
NTFY_URL=
NTFY_TOPIC=
NTFY_TOKEN=
RF-012 Mapeamento de Volume de Mídia
A aplicação dependerá de um volume Docker contendo os arquivos de música, montado no mesmo caminho utilizado pelo Lidarr (MUSIC_PATH).
O webhook enviado pelo Lidarr conterá caminhos absolutos que correspondem diretamente ao ponto de montagem do container, sem necessidade de tradução.
Sem o volume montado, a aplicação deverá registrar um aviso no log e operar apenas em modo dry run (quando habilitado), ou rejeitar tarefas que tentem acessar caminhos inexistentes.
RF-013 Persistência (SQLite)
A aplicação deverá utilizar SQLite embarcado como mecanismo de persistência.
O banco de dados deverá armazenar:
- histórico completo de tarefas (jobs)
- logs estruturados
- configurações editadas via web (overrides)
O arquivo do banco (DB_PATH) deverá residir em um volume Docker persistente para garantir a durabilidade dos dados entre reinicializações do container.
Na primeira execução, a aplicação deverá criar as tabelas necessárias automaticamente (migrações).
RF-014 Janela de Trabalho
A aplicação deverá suportar uma janela de trabalho opcional, desabilitada por padrão, que restrinja o processamento a um intervalo de horário definido.
Quando habilitada:
- a aplicação só despacha tarefas da fila para os workers dentro do intervalo configurado (
WORK_WINDOW_START—WORK_WINDOW_END); - fora do intervalo, as novas tarefas são aceitas e enfileiradas, mas não processadas;
- se uma tarefa estiver em andamento quando a janela fechar, ela é finalizada normalmente; as demais aguardam a próxima abertura;
- o fuso horário é definido pela configuração
TIMEZONE(ex:America/Sao_Paulo), que pode ser sobrescrita pela web.
RF-015 Busca e Conversão Manual de FLACs
A interface web deverá permitir descobrir e converter álbuns FLAC existentes na biblioteca, sem depender de webhooks do Lidarr.
A funcionalidade deve oferecer duas formas de navegação:
- Navegação por diretórios: o usuário explora a árvore de diretórios sob
MUSIC_PATHe seleciona pastas para conversão. - Scan recursivo: a aplicação varre todo o
MUSIC_PATHatrás de arquivos FLAC, agrupa por álbum (diretório) e apresenta uma lista para seleção individual ou em lote.
Ao confirmar, os álbuns selecionados são enfileirados seguindo o pipeline completo: conversão, validação, remoção dos FLACs e rescan no Lidarr (mesmo fluxo do webhook).
RF-016 Configuração via Web
A interface web deverá expor uma página de configurações (/settings) onde o usuário pode visualizar e alterar os parâmetros operacionais.
Os valores salvos via web são persistidos no SQLite e têm precedência sobre os definidos por variáveis de ambiente.
Alterações têm efeito imediato (não exigem reinicialização do container). Caso o usuário remova um override, o valor volta ao default definido pela variável de ambiente.
RF-017 Notificações via ntfy
A aplicação deverá enviar notificações para um servidor ntfy (self-hosted ou público) ao final de cada job, informando o resultado da conversão.
- Notificação de sucesso: prioridade
default, tagwhite_check_mark, título com artista/álbum. - Notificação de falha: prioridade
high, tagx, título com artista/álbum e mensagem de erro. - Falha ao enviar notificação não interrompe o pipeline — o job não é revertido.
- Respeita o modo
DRY_RUN: nenhuma notificação é enviada. - Desabilitada por padrão (
NTFY_ENABLED=false). - Suporte a token de autenticação (
Authorization: Bearer).
2. Requisitos Não Funcionais
RNF-001
Implementação em Go.
RNF-002
Distribuição via Docker.
RNF-003
Imagem baseada em Alpine Linux.
RNF-004
Baixo consumo de memória.
RNF-005
Utilizar SQLite embarcado como banco de dados — sem servidor externo, sem dependência de infraestrutura adicional. O arquivo do banco deve residir em volume Docker persistente.
RNF-006
Inicialização inferior a 5 segundos.
RNF-007
Suportar processamento contínuo durante longos períodos.