feat: implement project management and media track handling

- Added domain entities for audio, subtitle, and video tracks.
- Created a Project entity to manage media editing sessions.
- Implemented value objects for file paths, sync offsets, track IDs, and languages.
- Developed infrastructure for asynchronous FFmpeg process execution.
- Built a user interface for selecting video files, adding audio and subtitle tracks, and managing output settings.
- Integrated error handling and logging for media processing tasks.
This commit is contained in:
2026-02-28 13:42:23 -03:00
parent eff779a1df
commit ce236eca5d
47 changed files with 6818 additions and 2 deletions
+74
View File
@@ -0,0 +1,74 @@
use eframe::egui;
use crate::adapters::filesystem::FilePickerAdapter;
use crate::domain::value_objects::{FilePath, SyncOffset, TrackLanguage};
use crate::ui::components::{language_field::LanguageField, sync_offset_field::SyncOffsetField};
/// Evento emitido ao confirmar adição de faixa de áudio.
pub struct AddAudioTrackRequest {
pub path: FilePath,
pub offset: SyncOffset,
pub language: TrackLanguage,
}
/// Formulário para adicionar uma faixa de áudio externa.
pub struct AddAudioTrackForm {
selected_path: Option<FilePath>,
offset_field: SyncOffsetField,
language_field: LanguageField,
}
impl AddAudioTrackForm {
pub fn new() -> Self {
AddAudioTrackForm {
selected_path: None,
offset_field: SyncOffsetField::new(SyncOffset::default()),
language_field: LanguageField::new(None),
}
}
/// Renderiza o formulário. Retorna `Some(request)` ao confirmar.
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<AddAudioTrackRequest> {
let mut result = None;
ui.group(|ui| {
ui.heading("Adicionar faixa de áudio");
ui.horizontal(|ui| {
let label = self
.selected_path
.as_ref()
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_else(|| "Nenhum arquivo".to_string());
ui.label(&label);
if ui.button("Selecionar áudio…").clicked() {
self.selected_path = FilePickerAdapter::pick_audio();
}
});
self.offset_field.ui(ui, "Atraso:");
self.language_field.ui(ui);
ui.add_space(4.0);
let can_add = self.selected_path.is_some();
if ui
.add_enabled(can_add, egui::Button::new("Adicionar"))
.clicked()
{
if let (Some(path), Some(offset), Some(language)) = (
self.selected_path.clone(),
self.offset_field.parse(),
self.language_field.parse(),
) {
result = Some(AddAudioTrackRequest { path, offset, language });
// Reset form
self.selected_path = None;
self.offset_field = SyncOffsetField::new(SyncOffset::default());
self.language_field = LanguageField::new(None);
}
}
});
result
}
}