From 8f779601832b95725960471637ccadb933bee216 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Mon, 8 Sep 2025 20:39:26 +0200 Subject: [PATCH] Fix rendering again........ --- croppa/main.py | 113 ++++++++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 52 deletions(-) diff --git a/croppa/main.py b/croppa/main.py index c5aada2..4fd2693 100644 --- a/croppa/main.py +++ b/croppa/main.py @@ -1872,16 +1872,28 @@ class VideoEditor: output_path ] - # Start FFmpeg process with Windows-optimized configuration + # Use a more robust approach: write to a temporary file in chunks + import tempfile + import os + + # Create a temporary file for the raw video data + temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.raw') + temp_file.close() + + print(f"Using temporary file approach: {temp_file.name}") + + # Modify FFmpeg command to read from file + ffmpeg_cmd[ffmpeg_cmd.index('-i') + 1] = temp_file.name + + # Start FFmpeg process self.ffmpeg_process = subprocess.Popen( ffmpeg_cmd, - stdin=subprocess.PIPE, stderr=subprocess.PIPE, - stdout=subprocess.DEVNULL, # Discard stdout to prevent hanging - bufsize=65536, # 64KB buffer to prevent Windows pipe overflow - universal_newlines=False, # Binary mode for Windows + stdout=subprocess.DEVNULL, creationflags=subprocess.CREATE_NO_WINDOW if hasattr(subprocess, 'CREATE_NO_WINDOW') else 0 ) + + self.temp_file_name = temp_file.name # OpenCV for frame reading and transformations render_cap = cv2.VideoCapture(str(self.video_path)) @@ -1894,60 +1906,57 @@ class VideoEditor: self.render_progress_queue.put(("progress", f"Processing {total_frames} frames...", 0.1, 0.0)) - for i in range(total_frames): - if self.render_cancelled: - self.ffmpeg_process.stdin.close() - self.ffmpeg_process.terminate() - self.ffmpeg_process.wait() - render_cap.release() - self.ffmpeg_process = None - self.render_progress_queue.put(("cancelled", "Render cancelled", 0.0, 0.0)) - return False + # Write all frames to temporary file first + with open(self.temp_file_name, 'wb') as temp_file: + for i in range(total_frames): + if self.render_cancelled: + render_cap.release() + self.render_progress_queue.put(("cancelled", "Render cancelled", 0.0, 0.0)) + return False - ret, frame = render_cap.read() - if not ret: - break - - # Apply transformations with OpenCV - processed_frame = self._process_frame_for_render(frame, output_width, output_height) - if processed_frame is not None: - # Debug frame dimensions - if i == 0: # Only print for first frame - print(f"Processed frame dimensions: {processed_frame.shape[1]}x{processed_frame.shape[0]}") - print(f"Expected dimensions: {output_width}x{output_height}") - - # Write frame to FFmpeg via pipe - try: - self.ffmpeg_process.stdin.write(processed_frame.tobytes()) - frames_written += 1 - - # Small delay every 10 frames to prevent Windows pipe overflow - if frames_written % 10 == 0: - time.sleep(0.001) # 1ms delay - - except BrokenPipeError: - # FFmpeg process died - print("FFmpeg process died - BrokenPipeError") + ret, frame = render_cap.read() + if not ret: break - # Update progress with FPS calculation - current_time = time.time() - progress = 0.1 + (0.8 * (i + 1) / total_frames) - - # Calculate FPS and update progress (throttled) - if current_time - last_progress_update > 0.5: - elapsed = current_time - start_time - fps_rate = frames_written / elapsed if elapsed > 0 else 0 - self.render_progress_queue.put(("progress", f"Processed {i+1}/{total_frames} frames", progress, fps_rate)) - last_progress_update = current_time + # Apply transformations with OpenCV + processed_frame = self._process_frame_for_render(frame, output_width, output_height) + if processed_frame is not None: + # Debug frame dimensions + if i == 0: # Only print for first frame + print(f"Processed frame dimensions: {processed_frame.shape[1]}x{processed_frame.shape[0]}") + print(f"Expected dimensions: {output_width}x{output_height}") + + # Write frame to temporary file + temp_file.write(processed_frame.tobytes()) + frames_written += 1 - # Close FFmpeg input and wait for completion - self.ffmpeg_process.stdin.close() + # Update progress with FPS calculation + current_time = time.time() + progress = 0.1 + (0.8 * (i + 1) / total_frames) + + # Calculate FPS and update progress (throttled) + if current_time - last_progress_update > 0.5: + elapsed = current_time - start_time + fps_rate = frames_written / elapsed if elapsed > 0 else 0 + self.render_progress_queue.put(("progress", f"Processed {i+1}/{total_frames} frames", progress, fps_rate)) + last_progress_update = current_time + + render_cap.release() + + # Now wait for FFmpeg to finish encoding + self.render_progress_queue.put(("progress", "Encoding with FFmpeg...", 0.9, 0.0)) + + # Wait for FFmpeg to finish encoding stderr = self.ffmpeg_process.communicate()[1] return_code = self.ffmpeg_process.returncode self.ffmpeg_process = None - - render_cap.release() + + # Clean up temporary file + if hasattr(self, 'temp_file_name') and os.path.exists(self.temp_file_name): + try: + os.unlink(self.temp_file_name) + except OSError: + pass if return_code == 0: total_time = time.time() - start_time