Browse / github.com/storytold/filmcraft / patch
feat(ui): editable duration field in Clip Speed / Duration dialog (fixes #2191)
[Bug Report] [FilmCraft] duration field is un-changable ### Description when pressing cntrl + r to open clip/speed duration the area to enter a new duration isnt a text field and isnt changable ### Operating system and version win 11 current ### Ticket details | | | |---|---| | **App** | FilmCraft | | **Type** | Bug Report | | **Reported by** | DuckierMocha29 (Discord username: duckiermocha29) — Discord user ID `1003869176647135352` | | **Submitted** | 2026-10-16 13:15:52 UTC | | **Discord server** | ArtCraft (`1359579021108842617`) | | **Submitted from channel** | `1558917176453374102` | | **Submission ID** | `TR-RQC0KKYXVY` | <sub>Submitted
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- GabrielMatozo (imported from pull request #3242, open)
- Base
45901fccd06f1c2aa1dcdaac67cc00262a85f1be- Size
- +85 −11 in 2 files
- Review
- pending
- Shared
- 2026-10-28
- Id
765df4d56b816dfeb6d5766d
How it went
No other operator has reported using it yet.
Diff
raw · crates/ui-egui/src/i18n/pt-br.tsv crates/ui-egui/src/panels/clip_dialogs.rs
@@ -685,6 +685,7 @@ Extract (') Extrair (') Export Frame: use Export mode (M6) Exportar quadro: use o modo Exportar (M6) Button Editor Editor de botões+ More transport controls Mais controles de reprodução Multi-Camera Record on Gravação multicâmera ativada Multi-Camera Record off Gravação multicâmera desativada {first} - Merged {first} - Mesclado@@ -816,6 +817,7 @@ Relink others automatically Revincular os demais automaticamente Search in: Pesquisar em: Browse… Procurar…+ A file dialog is already open Uma janela de seleção de arquivos já está aberta Exact name matches only Somente correspondências exatas de nome No candidates yet — Search a folder or Locate the file. Ainda não há candidatos: pesquise uma pasta ou localize o arquivo. ✔ same file ✔ mesmo arquivo@@ -1827,7 +1829,7 @@ HDR Graphics White (Nits) Branco de gráficos HDR (nits) HLS Vectorscope + Histogram Vetorscópio HLS + histograma HSL Secondary HSL secundário- Hard Duro+ Hard Rígido Hard Clip Clipping duro Hard Light Luz direta Hard Limiter Limitador rígido@@ -1839,6 +1841,8 @@ Height Altura Hexagon Hexágono Hide Back Face Ocultar face traseira+ Hide FilmCraft Ocultar FilmCraft+ Hide Others Ocultar outros High Alta High Cutoff Corte de agudos High Frequency Cut Corte de altas frequências@@ -2355,6 +2359,9 @@ Set focus on the Timeline when performing Insert/Overwrite edits Focar a linha do tempo ao fazer edições de inserção/sobrescrita Set to frame size Definir para o tamanho do quadro Setting Configuração++ # The native macOS application menu (Settings…).+ Settings Preferências Shadow Angle Ângulo da sombra Shadow Blue Balance Balanço de azul nas sombras Shadow Blur Desfoque da sombra@@ -2904,7 +2911,7 @@ WebVTT (.vtt) WebVTT (.vtt) Title Título Creator Autor- Copyright Copyright+ Copyright Direitos autorais Image Imagem Frame Size Tamanho do quadro Match Source Igual à origem@@ -2993,6 +3000,12 @@ AIFF AIFF AIFF 48 kHz 16-bit AIFF 48 kHz 16 bits AIFF, stereo 48 kHz 16-bit PCM AIFF, estéreo, PCM de 48 kHz e 16 bits+ FLAC FLAC+ FLAC 48 kHz 24-bit FLAC 48 kHz 24 bits+ FLAC, stereo 48 kHz 24-bit, lossless FLAC, estéreo 48 kHz 24 bits, sem perdas+ FLAC (lossless) FLAC (sem perdas)+ Compression Level Nível de compressão+ 0 fastest, 8 smallest 0 mais rápido, 8 menor tamanho APV APV APV 422-10 APV 422-10 APV 422-12 APV 422-12@@ -3502,6 +3515,7 @@ Click to select, or click in empty space and drag to marquee select. Use Shift, Alt, and Ctrl for other options. Clique para selecionar, ou clique em um espaço vazio e arraste para selecionar com um retângulo. Use Shift, Alt e Ctrl para outras opções. Click to zoom in; Alt-click to zoom out. Clique para ampliar; Alt+clique para reduzir. Drag: move · Alt-click: smooth/corner · Ctrl-click: delete Arrastar: mover · Alt+clique: suave/canto · Ctrl+clique: excluir+ Drag inward to round the corners Arraste para dentro para arredondar os cantos Include Alpha Channel Incluir canal alfa Sequence Settings Configurações da sequência Color Management Gerenciamento de cores@@ -3565,7 +3579,16 @@ Composite on the GPU when available Compor na GPU quando disponível Text to Speech Texto para fala Edit Narration Editar narração++ Dock Panel Encaixar painel+ Undock Panel Desencaixar painel+ Docking Action Ação de encaixe+ Resize floating panel Redimensionar painel flutuante Project Notes Notas do projeto+ Get Project Notes Obter notas do projeto+ Edit Project Notes Editar notas do projeto+ Notes for this project: to-dos, instructions, frame numbers… Saved with the project. Notas deste projeto: tarefas, instruções, números de quadro… Salvas com o projeto.+ Use Effect Shutter Angle Usar o ângulo do obturador do efeito Appearance Settings… Configurações de aparência… @@ -3585,3 +3608,25 @@ Open a sequence to search its graphics Abra uma sequência para pesquisar nos gráficos dela No text graphics in this sequence. Add text with the Type tool. Esta sequência não tem gráficos com texto. Adicione texto com a ferramenta Texto. No matching text. Nenhum texto corresponde.+ Compression Compressão+ ZIP (1 scan line) ZIP (1 linha de varredura)+ ZIP (16 scan lines) ZIP (16 linhas de varredura)+ Safe graphics mode: {mode} Modo gráfico seguro: {mode}+ An earlier start failed with the default graphics. Updating the graphics driver usually fixes this. Uma inicialização anterior falhou com os gráficos padrão. Atualizar o driver gráfico geralmente resolve isso.+ Use Default Graphics Usar gráficos padrão+ The default graphics are used from the next start. Os gráficos padrão serão usados a partir da próxima inicialização.+ DirectX 12 only Somente DirectX 12+ software rendering renderização por software+ Label Color Presets Predefinições de cores dos rótulos+ {name} (Modified) {name} (Modificado)+ Revert to the preset's colors and names Restaurar as cores e os nomes da predefinição+ Import a preset file… Importar um arquivo de predefinição…+ Export the labels to a preset file… Exportar os rótulos para um arquivo de predefinição…+ Show the presets folder Mostrar a pasta de predefinições+ Delete this preset Excluir esta predefinição+ Opens in your web browser: {url} Abre no seu navegador: {url}+ Saves this session's log and shows it in your file manager. Salva o registro desta sessão e o mostra no gerenciador de arquivos.+ Shows a report on this computer. Mostra um relatório sobre este computador.+ Shows the version, community links and credits in a FilmCraft window. Mostra a versão, os links da comunidade e os créditos em uma janela do FilmCraft.+ Couldn't open your web browser Não foi possível abrir seu navegador+ Open this address in your browser yourself: Abra este endereço manualmente no seu navegador:@@ -297,6 +297,41 @@ fn frames(ui: &mut egui::Ui, elems: &mut Elems, pre: &str, p: &mut Value, key: & }); } +/// Timecode input field for duration in speed/duration dialog. Parses user-entered timecode+/// and calculates the required speed percentage from the new duration.+fn timecode_duration(ui: &mut egui::Ui, elems: &mut Elems, pre: &str, p: &mut Value, key: &str, label: &str, fps: f64, original_duration_frames: i64, original_speed: f64) {+ use filmcraft_time::{FrameRate, parse_timecode};+ ui.horizontal(|ui| {+ ui.label(label);+ let rate = FrameRate::from_f64(if fps > 0.0 { fps } else { 24.0 });+ let current_frames = p.get("speed").and_then(Value::as_f64).map(|spd| {+ let speed_ratio = spd / 100.0;+ if speed_ratio > 0.0 {+ (original_duration_frames as f64 * original_speed / speed_ratio).round() as i64+ } else {+ original_duration_frames+ }+ }).unwrap_or(original_duration_frames);+ let mut v = p.get(key).and_then(Value::as_str).unwrap_or(&filmcraft_time::format_timecode_frames(current_frames, rate, false)).to_string();+ let r = ui.add(egui::TextEdit::singleline(&mut v).desired_width(120.0));+ push(elems, format!("{pre}.{key}"), &r, label);+ if r.changed() {+ // Parse the timecode to frames+ if let Ok(frames) = parse_timecode(&v, rate, false, current_frames) {+ if frames > 0 {+ // Calculate new speed: original_duration * original_speed / new_duration+ let new_speed = (original_duration_frames as f64 * original_speed / frames as f64) * 100.0;+ let clamped = new_speed.clamp(0.01, 100_000.0);+ p["speed"] = json!(clamped);+ }+ }+ p[key] = json!(v);+ }+ // Also show the frame count for reference+ ui.label(RichText::new(format!("({current_frames} fr)")).monospace().weak());+ });+}+ /// Draw the open dialog, if any. pub fn show(app: &mut FilmcraftApp, ctx: &egui::Context) { let Some(mut d) = app.ui.clip_dialog.clone() else { return };@@ -516,17 +551,11 @@ pub fn show(app: &mut FilmcraftApp, ctx: &egui::Context) { } "clip.speedDuration" => { number(ui, &mut elems, pre, p, "speed", tl!("Speed:"), 0.01..=100_000.0, " %");- // Duration follows the speed: the media shown stays the same+ // Duration: editable timecode that calculates speed when changed. let (dur, was, fps) = (d.info["duration"].as_i64().unwrap_or(0), d.info["speed"].as_f64().unwrap_or(1.0), d.info["fps"].as_f64().unwrap_or(24.0));- let now = p["speed"].as_f64().unwrap_or(100.0) / 100.0;- if dur > 0 && now > 0.0 {- let rate = filmcraft_time::FrameRate::from_f64(if fps > 0.0 { fps } else { 24.0 });- let ticks = filmcraft_time::Tick((dur as f64 * was / now).round() as i64);- ui.horizontal(|ui| {- ui.label(tl!("Duration:"));- ui.label(RichText::new(filmcraft_time::format_timecode_frames(rate.frame_at(ticks), rate, false)).monospace());- });+ if dur > 0 {+ timecode_duration(ui, &mut elems, pre, p, "duration", tl!("Duration:"), fps, dur, was); } check(ui, &mut elems, pre, p, "reverse", tl!("Reverse Speed"), true); check(ui, &mut elems, pre, p, "ripple", tl!("Ripple Edit, Shifting Trailing Clips"), true);