feat: atualiza versão do projeto para 1.3 e revisa o plano de desenvolvimento e PRD com novas funcionalidades e requisitos

This commit is contained in:
2026-02-28 18:19:03 -03:00
parent 16dcb0b9d4
commit 18739c3ce7
3 changed files with 266 additions and 136 deletions
+58 -47
View File
@@ -1,9 +1,9 @@
# PRD — Simple Multimedia Track Audio Editor
**Versão:** 1.1
**Versão:** 1.2
**Data:** 28/02/2026
**Status:** Em desenvolvimento
**Revisão:** Incorporados feedbacks de arquitetura — modelo de sessão, ffprobe, tipos fortes e regra de no-reencode
**Revisão:** v1.2 — Adicionado RF-09 (Modo Lote); batch promovido de backlog para requisito planejado
---
@@ -105,6 +105,17 @@ As ferramentas existentes são complexas (ex: interface direta do FFmpeg via CLI
- A faixa original é remapeada com o novo timestamp via `ffmpeg -itsoffset` combinado com `-map`
- Útil para corrigir atrasos em faixas de dublagem ou legenda já incorporadas ao arquivo
### RF-09 — Processamento em lote
- A interface oferece duas abas: **Projeto Único** (fluxo atual) e **Lote**
- A aba Lote funciona como um **carrinho**: o usuário adiciona, revisa e remove itens livremente antes de processar
- Cada item é um projeto completo e independente (vídeo, faixas e saída próprios), configurado via **formulário inline** na própria aba Lote — sem navegação para outra tela
- A seleção de arquivos usa **diálogos nativos** (igual ao modo Projeto Único) — nenhum path é digitado manualmente
- O processamento é **sequencial** — um projeto por vez, sem paralelismo, para evitar sobrecarga de I/O
- Durante o processamento, o carrinho é bloqueado: não é possível adicionar nem remover itens
- Cada item exibe seu estado individual: `Aguardando | Processando | Concluído | Erro`
- É possível cancelar o item em execução; os demais permanecem no carrinho com estado `Aguardando`
---
## 7. Requisitos Não Funcionais
@@ -158,15 +169,15 @@ Arquivo de saída (.mkv)
### Stack
| Camada | Tecnologia | Motivo |
|--------------|-------------------------------|---------------------------------------------|
| Interface | `egui` / `eframe` | Nativo, simples, multiplataforma |
| Backend | Rust (`std::process::Command`)| Estável, sem dependências externas |
| Erros | `anyhow` | Propagação de erros simplificada |
| Configuração | `serde` | Serialização de perfis e histórico |
| Async | `tokio` (opcional) | Execução não bloqueante da interface |
| Mídia | FFmpeg (externo) | Maduro, estável, amplamente testado |
| Container | MKV | Melhor suporte a múltiplas faixas |
| Camada | Tecnologia | Motivo |
| ------------ | ------------------------------ | ------------------------------------ |
| Interface | `egui` / `eframe` | Nativo, simples, multiplataforma |
| Backend | Rust (`std::process::Command`) | Estável, sem dependências externas |
| Erros | `anyhow` | Propagação de erros simplificada |
| Configuração | `serde` | Serialização de perfis e histórico |
| Async | `tokio` (opcional) | Execução não bloqueante da interface |
| Mídia | FFmpeg (externo) | Maduro, estável, amplamente testado |
| Container | MKV | Melhor suporte a múltiplas faixas |
### Dependências Cargo
@@ -208,10 +219,10 @@ As dependências sempre apontam de fora para dentro. Camadas internas não conhe
Contém as entidades e objetos de valor do negócio. Não depende de nada externo.
| Tipo | Exemplos |
|----------------|-----------------------------------------------------------------------------------|
| Entities | `Project`, `VideoFile`, `AudioTrack`, `SubtitleTrack`, `MkvOutput`, `MediaTrackInfo` |
| Value Objects | `TrackId`, `SyncOffset`, `TrackLanguage`, `FilePath` |
| Tipo | Exemplos |
| ------------- | ------------------------------------------------------------------------------------ |
| Entities | `Project`, `VideoFile`, `AudioTrack`, `SubtitleTrack`, `MkvOutput`, `MediaTrackInfo` |
| Value Objects | `TrackId`, `SyncOffset`, `TrackLanguage`, `FilePath` |
> **`Project`** é a entidade central do domínio. Representa a sessão de edição completa do usuário e deve ser a única fonte de verdade do estado em memória.
>
@@ -232,10 +243,10 @@ Contém as entidades e objetos de valor do negócio. Não depende de nada extern
Contém as regras de negócio da aplicação. Orquestra as entidades do domínio.
Define traits (ports) que as camadas externas devem implementar.
| Tipo | Exemplos |
|------------|-------------------------------------------------------------------------------------------------------------------|
| Use Cases | `LoadMediaInfo`, `AddAudioTrack`, `AddSubtitle`, `AdjustSync`, `EditExistingTrackSync`, `SetTrackLanguage`, `GenerateOutput` |
| Ports | `MediaProcessorPort`, `MediaInfoPort`, `FileSystemPort` |
| Tipo | Exemplos |
| --------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Use Cases | `LoadMediaInfo`, `AddAudioTrack`, `AddSubtitle`, `AdjustSync`, `EditExistingTrackSync`, `SetTrackLanguage`, `GenerateOutput` |
| Ports | `MediaProcessorPort`, `MediaInfoPort`, `FileSystemPort` |
> **`MediaInfoPort`** é o port responsável por inspecionar arquivos de mídia existentes. Deve ser definido na camada Application e implementado na camada Adapters via `FfprobeGateway`.
>
@@ -253,11 +264,11 @@ Define traits (ports) que as camadas externas devem implementar.
Implementam os ports definidos na camada de Application. Traduzem dados entre o domínio e o mundo externo.
| Tipo | Exemplos |
|--------------------|---------------------------------------------------------------------------|
| Gateway | `FfmpegCommandBuilder`, `FfmpegGateway`, `FfprobeGateway` |
| Presenter | `ErrorPresenter` (formata stderr do FFmpeg) |
| File Adapter | `FilePickerAdapter` |
| Tipo | Exemplos |
| ------------ | --------------------------------------------------------- |
| Gateway | `FfmpegCommandBuilder`, `FfmpegGateway`, `FfprobeGateway` |
| Presenter | `ErrorPresenter` (formata stderr do FFmpeg) |
| File Adapter | `FilePickerAdapter` |
> **`FfprobeGateway`** implementa `MediaInfoPort`. Executa `ffprobe -v quiet -print_format json -show_streams` e mapeia a saída para `Vec<MediaTrackInfo>`. Não conhece o domínio além das structs que está populando.
>
@@ -267,11 +278,11 @@ Implementam os ports definidos na camada de Application. Traduzem dados entre o
Camada mais externa. Contém o framework de UI e a execução real de processos.
| Tipo | Exemplos |
|--------------|-------------------------------------------------------|
| UI | `App` (eframe), componentes egui |
| Process | Execução de `std::process::Command` / `tokio::process`|
| Filesystem | Leitura e escrita de arquivos |
| Tipo | Exemplos |
| ---------- | ------------------------------------------------------ |
| UI | `App` (eframe), componentes egui |
| Process | Execução de `std::process::Command` / `tokio::process` |
| Filesystem | Leitura e escrita de arquivos |
---
@@ -300,14 +311,14 @@ src/
## 10. Débitos Técnicos
| ID | Descrição | Impacto | Mitigação |
|-----|--------------------------------------|------------------|--------------------------------------|
| DT-01 | FFmpeg não embutido | Usuário precisa instalar | Distribuir junto com a aplicação |
| DT-02 | Dependência de processo externo | Menor controle interno | Encapsular via módulo de serviço |
| DT-03 | Parsing de erros do FFmpeg (stderr) | Necessário tratamento manual | Parsear saída e exibir mensagem amigável |
| DT-04 | Compatibilidade de codecs | Alguns codecs podem não ser aceitos | Usar MKV como container padrão |
| DT-05 | Performance de processo externo | Pequeno overhead | Aceitável — mux é rápido |
| DT-06 | ffprobe como dependência adicional | Parsing de JSON da saída do ffprobe | Validar presença de ffprobe na inicialização; exibir mensagem clara se ausente |
| ID | Descrição | Impacto | Mitigação |
| ----- | ----------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------ |
| DT-01 | FFmpeg não embutido | Usuário precisa instalar | Distribuir junto com a aplicação |
| DT-02 | Dependência de processo externo | Menor controle interno | Encapsular via módulo de serviço |
| DT-03 | Parsing de erros do FFmpeg (stderr) | Necessário tratamento manual | Parsear saída e exibir mensagem amigável |
| DT-04 | Compatibilidade de codecs | Alguns codecs podem não ser aceitos | Usar MKV como container padrão |
| DT-05 | Performance de processo externo | Pequeno overhead | Aceitável — mux é rápido |
| DT-06 | ffprobe como dependência adicional | Parsing de JSON da saída do ffprobe | Validar presença de ffprobe na inicialização; exibir mensagem clara se ausente |
---
@@ -318,7 +329,6 @@ src/
- Seleção de faixa padrão no container MKV
- Remoção de faixas existentes do arquivo original
- Suporte a perfis de configuração salvos
- Modo de processamento em lote (batch)
---
@@ -345,18 +355,18 @@ src/
O FFmpeg é uma ferramenta de poder absurdo — e opacidade equivalente. O usuário não entende `track index`, `stream mapping` ou `itsoffset`. O usuário entende:
- *"Áudio em português está 1.2 segundos atrasado"*
- *"Quero adicionar a legenda em inglês"*
- *"Gerar o arquivo final"*
- _"Áudio em português está 1.2 segundos atrasado"_
- _"Quero adicionar a legenda em inglês"_
- _"Gerar o arquivo final"_
Toda decisão de UX deve partir dessa perspectiva. Termos técnicos do FFmpeg nunca devem aparecer na interface.
| FFmpeg (interno) | Interface (usuário) |
|-----------------------|--------------------------------------|
| `-itsoffset -1200ms` | "Adiantar 1.2s" |
| `stream 0:a:1` | "Faixa de áudio 2 — Português" |
| `-c copy` | *(invisível — nunca exposto)* |
| `ffprobe output` | Lista de faixas detectadas |
| FFmpeg (interno) | Interface (usuário) |
| -------------------- | ------------------------------ |
| `-itsoffset -1200ms` | "Adiantar 1.2s" |
| `stream 0:a:1` | "Faixa de áudio 2 — Português" |
| `-c copy` | _(invisível — nunca exposto)_ |
| `ffprobe output` | Lista de faixas detectadas |
---
@@ -373,6 +383,7 @@ O MKV (Matroska) é estruturalmente um banco de dados multimídia. Suas operaç
O arquivo de saída não é uma criação nova — é uma nova **visão** do container original com faixas adicionadas e metadados ajustados, sem tocar nos bytes de mídia.
Esse modelo mental simplifica a implementação:
- Sem buffers de vídeo
- Sem pipelines de transcoding
- Apenas mapeamento de streams e metadados