Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(export): prevent export progress from freezing at 102% #232

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions apps/desktop/src-tauri/src/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ pub async fn export_video(
.await
.unwrap();

// 30 FPS (calculated for output video)
let total_frames = (duration * 30.0).round() as u32;
// Calculate total frames with ceiling to ensure we don't exceed 100%
let total_frames = ((duration * 30.0).ceil() as u32).max(1);

let editor_instance = upsert_editor_instance(&app, video_id.clone()).await;

Expand All @@ -41,9 +41,11 @@ pub async fn export_video(
project,
output_path.clone(),
move |frame_index| {
// Ensure progress never exceeds total frames
let current_frame = (frame_index + 1).min(total_frames);
progress
.send(RenderProgress::FrameRendered {
current_frame: frame_index + 1,
current_frame,
})
.ok();
},
Expand Down
16 changes: 14 additions & 2 deletions apps/desktop/src/routes/editor/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -260,14 +260,26 @@ function ExportButton() {
const progress = new Channel<RenderProgress>();
progress.onmessage = (p) => {
if (p.type === "FrameRendered" && progressState.type === "saving") {
const percentComplete = Math.round(
(p.current_frame / (progressState.totalFrames || 1)) * 100
const percentComplete = Math.min(
Math.round(
(p.current_frame / (progressState.totalFrames || 1)) * 100
),
100

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we use 'Math.min' here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so it will not exceed 100%

);

setProgressState({
...progressState,
renderProgress: p.current_frame,
message: `Rendering video - ${percentComplete}%`,
});

// If rendering is complete, update the message
if (percentComplete === 100) {
setProgressState({
...progressState,
message: "Finalizing export...",
});
}
}
if (
p.type === "EstimatedTotalFrames" &&
Expand Down
16 changes: 14 additions & 2 deletions apps/desktop/src/routes/recordings-overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -375,14 +375,26 @@ export default function () {
undefined &&
progressState.totalFrames
) {
return `${Math.min(
const progress = Math.min(
Math.round(
(progressState.renderProgress /
progressState.totalFrames) *
100
),
100
)}%`;
);

// If we hit 100%, transition to the next stage
if (progress === 100 && progressState.type === "uploading") {
setProgressState({
...progressState,
stage: "uploading",
message: "Starting upload...",
uploadProgress: 0
});
}

return `${progress}%`;
}

return progressState.message;
Expand Down
Loading