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
if self.load_state():
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):
"""Switch to a specific video by index"""
@@ -511,6 +517,11 @@ class VideoEditor:
self, direction: int, shift_pressed: bool, ctrl_pressed: bool
):
"""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:
base_frames = 60 # Ctrl: 60 frames
elif shift_pressed:
@@ -1500,7 +1511,7 @@ class VideoEditor:
"""Start video rendering in a separate thread"""
# Check if already rendering
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
# Reset render state
@@ -1515,10 +1526,12 @@ class VideoEditor:
self.render_thread.start()
print(f"Started rendering to {output_path} in background thread...")
print("You can continue editing while rendering. Press 'X' to cancel.")
return True
def _render_video_worker(self, output_path: str):
"""Worker method that runs in the render thread"""
render_cap = None
try:
if not output_path.endswith(".mp4"):
output_path += ".mp4"
@@ -1528,6 +1541,12 @@ class VideoEditor:
# Send progress update to main thread
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
start_frame = self.cut_start_frame if self.cut_start_frame is not None else 0
end_frame = (
@@ -1583,9 +1602,9 @@ class VideoEditor:
self.render_progress_queue.put(("cancelled", "Render cancelled", 0.0, 0.0))
return False
# Read frame
self.cap.set(cv2.CAP_PROP_POS_FRAMES, frame_idx)
ret, frame = self.cap.read()
# Read frame using the separate VideoCapture
render_cap.set(cv2.CAP_PROP_POS_FRAMES, frame_idx)
ret, frame = render_cap.read()
if not ret:
break
@@ -1634,9 +1653,20 @@ class VideoEditor:
return True
except Exception as e:
self.render_progress_queue.put(("error", f"Render error: {str(e)}", 1.0, 0.0))
print(f"Render error: {e}")
error_msg = str(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
finally:
# Always clean up the render VideoCapture
if render_cap:
render_cap.release()
def update_render_progress(self):
"""Process progress updates from the render thread"""