feat(main.py): enhance video editor with rendering state checks and logging

This commit is contained in:
2025-09-08 00:00:26 +02:00
parent b7e4fac9e7
commit d29d45d4fd

View File

@@ -460,6 +460,12 @@ class VideoEditor:
# Try to load saved state for this media file # Try to load saved state for this media file
if self.load_state(): if self.load_state():
print("Loaded saved state for this media file") print("Loaded saved state for this media file")
if self.cut_start_frame is not None:
print(f" Cut start frame: {self.cut_start_frame}")
if self.cut_end_frame is not None:
print(f" Cut end frame: {self.cut_end_frame}")
else:
print("No saved state found for this media file")
def switch_to_video(self, index: int): def switch_to_video(self, index: int):
"""Switch to a specific video by index""" """Switch to a specific video by index"""
@@ -511,6 +517,11 @@ class VideoEditor:
self, direction: int, shift_pressed: bool, ctrl_pressed: bool self, direction: int, shift_pressed: bool, ctrl_pressed: bool
): ):
"""Seek video with different frame counts based on modifiers and seek multiplier""" """Seek video with different frame counts based on modifiers and seek multiplier"""
# Don't allow seeking while rendering to prevent crashes
if self.is_rendering():
print("Cannot seek while rendering is in progress")
return
if ctrl_pressed: if ctrl_pressed:
base_frames = 60 # Ctrl: 60 frames base_frames = 60 # Ctrl: 60 frames
elif shift_pressed: elif shift_pressed:
@@ -1500,7 +1511,7 @@ class VideoEditor:
"""Start video rendering in a separate thread""" """Start video rendering in a separate thread"""
# Check if already rendering # Check if already rendering
if self.render_thread and self.render_thread.is_alive(): if self.render_thread and self.render_thread.is_alive():
print("Render already in progress!") print("Render already in progress! Use 'X' to cancel first.")
return False return False
# Reset render state # Reset render state
@@ -1515,10 +1526,12 @@ class VideoEditor:
self.render_thread.start() self.render_thread.start()
print(f"Started rendering to {output_path} in background thread...") print(f"Started rendering to {output_path} in background thread...")
print("You can continue editing while rendering. Press 'X' to cancel.")
return True return True
def _render_video_worker(self, output_path: str): def _render_video_worker(self, output_path: str):
"""Worker method that runs in the render thread""" """Worker method that runs in the render thread"""
render_cap = None
try: try:
if not output_path.endswith(".mp4"): if not output_path.endswith(".mp4"):
output_path += ".mp4" output_path += ".mp4"
@@ -1528,6 +1541,12 @@ class VideoEditor:
# Send progress update to main thread # Send progress update to main thread
self.render_progress_queue.put(("init", "Initializing render...", 0.0, 0.0)) self.render_progress_queue.put(("init", "Initializing render...", 0.0, 0.0))
# Create a separate VideoCapture for the render thread to avoid thread safety issues
render_cap = cv2.VideoCapture(str(self.video_path))
if not render_cap.isOpened():
self.render_progress_queue.put(("error", "Could not open video for rendering!", 1.0, 0.0))
return False
# Determine frame range # Determine frame range
start_frame = self.cut_start_frame if self.cut_start_frame is not None else 0 start_frame = self.cut_start_frame if self.cut_start_frame is not None else 0
end_frame = ( end_frame = (
@@ -1583,9 +1602,9 @@ class VideoEditor:
self.render_progress_queue.put(("cancelled", "Render cancelled", 0.0, 0.0)) self.render_progress_queue.put(("cancelled", "Render cancelled", 0.0, 0.0))
return False return False
# Read frame # Read frame using the separate VideoCapture
self.cap.set(cv2.CAP_PROP_POS_FRAMES, frame_idx) render_cap.set(cv2.CAP_PROP_POS_FRAMES, frame_idx)
ret, frame = self.cap.read() ret, frame = render_cap.read()
if not ret: if not ret:
break break
@@ -1634,9 +1653,20 @@ class VideoEditor:
return True return True
except Exception as e: except Exception as e:
self.render_progress_queue.put(("error", f"Render error: {str(e)}", 1.0, 0.0)) error_msg = str(e)
print(f"Render error: {e}") # Handle specific FFmpeg threading errors
if "async_lock" in error_msg or "pthread_frame" in error_msg:
error_msg = "FFmpeg threading error - try restarting the application"
elif "Assertion" in error_msg:
error_msg = "Video codec error - the video file may be corrupted or incompatible"
self.render_progress_queue.put(("error", f"Render error: {error_msg}", 1.0, 0.0))
print(f"Render error: {error_msg}")
return False return False
finally:
# Always clean up the render VideoCapture
if render_cap:
render_cap.release()
def update_render_progress(self): def update_render_progress(self):
"""Process progress updates from the render thread""" """Process progress updates from the render thread"""