feat: implementa funcionalidade de exportação de faixas de áudio e legenda
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use crate::domain::entities::{Project, Track, TrackKind};
|
||||
use crate::domain::entities::{MediaTrackInfo, Project, Track, TrackKind};
|
||||
use crate::domain::value_objects::FilePath;
|
||||
|
||||
/// Constrói os argumentos do FFmpeg a partir de um Project.
|
||||
///
|
||||
@@ -126,14 +127,59 @@ impl FfmpegCommandBuilder {
|
||||
|
||||
args
|
||||
}
|
||||
|
||||
/// Constrói args para exportar uma faixa individual de um arquivo de mídia.
|
||||
///
|
||||
/// - Áudio: usa `-c:a copy` para preservar o stream sem reencoding (RNF-01 mantido).
|
||||
/// - Legenda: **omite** `-c copy` — o FFmpeg precisa converter o container de texto
|
||||
/// (ex: stream `subrip` dentro de MKV → arquivo `.srt`). Essa é a única
|
||||
/// exceção documentada ao invariante RNF-01, restrita a este método.
|
||||
/// - Vídeo/outros: usa `-c copy`.
|
||||
///
|
||||
/// O `-y` é incluído para evitar que o processo bloqueie ao sobrescrever um arquivo
|
||||
/// (a confirmação é responsabilidade do diálogo de salvamento da UI).
|
||||
pub fn build_export(
|
||||
source: &FilePath,
|
||||
track: &MediaTrackInfo,
|
||||
output: &FilePath,
|
||||
) -> Vec<String> {
|
||||
let mut args: Vec<String> = Vec::new();
|
||||
|
||||
args.push("-i".to_string());
|
||||
args.push(source.to_string_lossy().to_string());
|
||||
|
||||
args.push("-map".to_string());
|
||||
args.push(format!("0:{}", track.stream_index));
|
||||
|
||||
match &track.kind {
|
||||
TrackKind::Audio => {
|
||||
args.push("-c:a".to_string());
|
||||
args.push("copy".to_string());
|
||||
}
|
||||
TrackKind::Subtitle => {
|
||||
// Sem -c copy: o FFmpeg extrai a legenda convertendo o container de texto
|
||||
// automaticamente. Não há reencoding de mídia envolvido.
|
||||
}
|
||||
_ => {
|
||||
args.push("-c".to_string());
|
||||
args.push("copy".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
// Sobrescrever sem prompt interativo (o diálogo de salvamento já confirmou)
|
||||
args.push("-y".to_string());
|
||||
args.push(output.to_string_lossy().to_string());
|
||||
|
||||
args
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::application::use_cases::add_audio_track::AddAudioTrack;
|
||||
use crate::domain::entities::{MkvOutput, Project, VideoFile};
|
||||
use crate::domain::value_objects::{FilePath, SyncOffset, TrackLanguage};
|
||||
use crate::application::use_cases::add_audio_track::AddAudioTrack;
|
||||
|
||||
fn base_project() -> Project {
|
||||
Project::new(
|
||||
@@ -188,7 +234,11 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
let args = FfmpegCommandBuilder::build(&project);
|
||||
assert!(args.contains(&"1:a".to_string()), "faltou map 1:a — args: {:?}", args);
|
||||
assert!(
|
||||
args.contains(&"1:a".to_string()),
|
||||
"faltou map 1:a — args: {:?}",
|
||||
args
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user