refactor(main.py): simplify seek logic, update imports and print statements; update pyproject.toml to include ruff as a dependency
This commit is contained in:
@@ -4,7 +4,7 @@ import cv2
|
||||
import argparse
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
from typing import Optional, Tuple, List
|
||||
from typing import List
|
||||
import time
|
||||
import re
|
||||
import json
|
||||
@@ -402,7 +402,7 @@ class VideoEditor:
|
||||
self.cap.set(cv2.CAP_PROP_HW_ACCELERATION, cv2.VIDEO_ACCELERATION_ANY)
|
||||
break
|
||||
self.cap.release()
|
||||
except:
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if not self.cap or not self.cap.isOpened():
|
||||
@@ -427,11 +427,11 @@ class VideoEditor:
|
||||
|
||||
# Performance warning for known problematic cases
|
||||
if codec in ['H264', 'H.264', 'AVC1', 'avc1'] and self.total_frames > 10000:
|
||||
print(f" Warning: Large H.264 video detected - seeking may be slow")
|
||||
print(" Warning: Large H.264 video detected - seeking may be slow")
|
||||
if self.frame_width * self.frame_height > 1920 * 1080:
|
||||
print(f" Warning: High resolution video - decoding may be slow")
|
||||
print(" Warning: High resolution video - decoding may be slow")
|
||||
if self.fps > 60:
|
||||
print(f" Warning: High framerate video - may impact playback smoothness")
|
||||
print(" Warning: High framerate video - may impact playback smoothness")
|
||||
|
||||
# Reset playback state for new media
|
||||
self.current_frame = 0
|
||||
@@ -500,55 +500,6 @@ class VideoEditor:
|
||||
self.current_frame = target_frame
|
||||
self.load_current_frame()
|
||||
|
||||
def seek_video_smart(self, frames_delta: int):
|
||||
"""Seek using keyframe jumping for large jumps"""
|
||||
target_frame = max(
|
||||
0, min(self.current_frame + frames_delta, self.total_frames - 1)
|
||||
)
|
||||
|
||||
# For small jumps, use regular seeking
|
||||
if abs(frames_delta) <= 10:
|
||||
self.current_frame = target_frame
|
||||
self.load_current_frame()
|
||||
return
|
||||
|
||||
# For larger jumps, use keyframe seeking
|
||||
# Jump to nearest keyframe first, then seek forward
|
||||
keyframe_interval = self._detect_keyframe_interval()
|
||||
nearest_keyframe = (target_frame // keyframe_interval) * keyframe_interval
|
||||
|
||||
# Seek to keyframe first
|
||||
self.cap.set(cv2.CAP_PROP_POS_FRAMES, nearest_keyframe)
|
||||
self.current_frame = nearest_keyframe
|
||||
|
||||
# Then seek forward to target frame
|
||||
frames_to_seek = target_frame - nearest_keyframe
|
||||
for _ in range(frames_to_seek):
|
||||
ret, frame = self.cap.read()
|
||||
if not ret:
|
||||
break
|
||||
self.current_frame += 1
|
||||
|
||||
self.current_display_frame = frame if 'frame' in locals() else None
|
||||
|
||||
def _detect_keyframe_interval(self):
|
||||
"""Detect the keyframe interval for the current video"""
|
||||
# Try to get keyframe interval from video properties
|
||||
try:
|
||||
# Some backends support keyframe interval detection
|
||||
keyframe_interval = self.cap.get(cv2.CAP_PROP_FRAME_COUNT) / self.cap.get(cv2.CAP_PROP_FPS)
|
||||
if keyframe_interval > 0:
|
||||
return int(keyframe_interval)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Fallback: estimate based on video characteristics
|
||||
if self.fps >= 60:
|
||||
return 60 # High FPS videos often have keyframes every 60 frames
|
||||
elif self.fps >= 30:
|
||||
return 30 # Standard videos have keyframes every 30 frames
|
||||
else:
|
||||
return 15 # Lower FPS videos have keyframes every 15 frames
|
||||
|
||||
def seek_video_with_modifier(
|
||||
self, direction: int, shift_pressed: bool, ctrl_pressed: bool
|
||||
@@ -556,13 +507,12 @@ class VideoEditor:
|
||||
"""Seek video with different frame counts based on modifiers"""
|
||||
if ctrl_pressed:
|
||||
frames = direction * 60 # Ctrl: 60 frames
|
||||
self.seek_video_smart(frames)
|
||||
elif shift_pressed:
|
||||
frames = direction * 10 # Shift: 10 frames
|
||||
self.seek_video_smart(frames)
|
||||
else:
|
||||
frames = direction * 1 # Default: 1 frame
|
||||
self.seek_video(frames)
|
||||
|
||||
self.seek_video(frames)
|
||||
|
||||
def start_auto_repeat_seek(self, key: int, direction: int, shift_pressed: bool, ctrl_pressed: bool):
|
||||
"""Start auto-repeat seeking for a held key"""
|
||||
@@ -1296,7 +1246,6 @@ class VideoEditor:
|
||||
|
||||
# Handle crop selection (Shift + click and drag)
|
||||
if flags & cv2.EVENT_FLAG_SHIFTKEY:
|
||||
available_height = self.window_height - (0 if self.is_image_mode else self.TIMELINE_HEIGHT)
|
||||
|
||||
if event == cv2.EVENT_LBUTTONDOWN:
|
||||
self.crop_selecting = True
|
||||
@@ -1888,7 +1837,6 @@ class VideoEditor:
|
||||
|
||||
# Get modifier key states
|
||||
window_title = "Image Editor" if self.is_image_mode else "Video Editor"
|
||||
modifiers = cv2.getWindowProperty(window_title, cv2.WND_PROP_AUTOSIZE)
|
||||
# Note: OpenCV doesn't provide direct access to modifier keys in waitKey
|
||||
# We'll handle this through special key combinations
|
||||
|
||||
@@ -2008,7 +1956,7 @@ class VideoEditor:
|
||||
temp_fd, temp_path = tempfile.mkstemp(suffix=self.video_path.suffix, dir=temp_dir)
|
||||
os.close(temp_fd) # Close the file descriptor, we just need the path
|
||||
|
||||
print(f"Rendering to temporary file first...")
|
||||
print("Rendering to temporary file first...")
|
||||
success = self.render_video(temp_path)
|
||||
|
||||
if success:
|
||||
@@ -2092,9 +2040,9 @@ def main():
|
||||
|
||||
try:
|
||||
args = parser.parse_args()
|
||||
except SystemExit as e:
|
||||
except SystemExit:
|
||||
# If launched from context menu without arguments, this might fail
|
||||
input(f"Argument parsing failed. Press Enter to exit...")
|
||||
input("Argument parsing failed. Press Enter to exit...")
|
||||
return
|
||||
|
||||
if not os.path.exists(args.media):
|
||||
|
@@ -5,6 +5,7 @@ description = "Media Grader - Grade media files by moving them to numbered folde
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"opencv-python>=4.12.0.88",
|
||||
"ruff>=0.12.12",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
32
uv.lock
generated
32
uv.lock
generated
@@ -29,10 +29,14 @@ version = "0.1.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "opencv-python" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [{ name = "opencv-python", specifier = ">=4.12.0.88" }]
|
||||
requires-dist = [
|
||||
{ name = "opencv-python", specifier = ">=4.12.0.88" },
|
||||
{ name = "ruff", specifier = ">=0.12.12" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
@@ -78,3 +82,29 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/02/96/213fea371d3cb2f1d537612a105792aa0a6659fb2665b22cad709a75bd94/opencv_python-4.12.0.88-cp37-abi3-win32.whl", hash = "sha256:ff554d3f725b39878ac6a2e1fa232ec509c36130927afc18a1719ebf4fbf4357", size = 30284131, upload-time = "2025-07-07T09:14:08.819Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/80/eb88edc2e2b11cd2dd2e56f1c80b5784d11d6e6b7f04a1145df64df40065/opencv_python-4.12.0.88-cp37-abi3-win_amd64.whl", hash = "sha256:d98edb20aa932fd8ebd276a72627dad9dc097695b3d435a4257557bbb49a79d2", size = 39000307, upload-time = "2025-07-07T09:14:16.641Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.12.12"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/f0/e0965dd709b8cabe6356811c0ee8c096806bb57d20b5019eb4e48a117410/ruff-0.12.12.tar.gz", hash = "sha256:b86cd3415dbe31b3b46a71c598f4c4b2f550346d1ccf6326b347cc0c8fd063d6", size = 5359915, upload-time = "2025-09-04T16:50:18.273Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/09/79/8d3d687224d88367b51c7974cec1040c4b015772bfbeffac95face14c04a/ruff-0.12.12-py3-none-linux_armv6l.whl", hash = "sha256:de1c4b916d98ab289818e55ce481e2cacfaad7710b01d1f990c497edf217dafc", size = 12116602, upload-time = "2025-09-04T16:49:18.892Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/c3/6e599657fe192462f94861a09aae935b869aea8a1da07f47d6eae471397c/ruff-0.12.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7acd6045e87fac75a0b0cdedacf9ab3e1ad9d929d149785903cff9bb69ad9727", size = 12868393, upload-time = "2025-09-04T16:49:23.043Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/d2/9e3e40d399abc95336b1843f52fc0daaceb672d0e3c9290a28ff1a96f79d/ruff-0.12.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:abf4073688d7d6da16611f2f126be86523a8ec4343d15d276c614bda8ec44edb", size = 12036967, upload-time = "2025-09-04T16:49:26.04Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/03/6816b2ed08836be272e87107d905f0908be5b4a40c14bfc91043e76631b8/ruff-0.12.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:968e77094b1d7a576992ac078557d1439df678a34c6fe02fd979f973af167577", size = 12276038, upload-time = "2025-09-04T16:49:29.056Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/d5/707b92a61310edf358a389477eabd8af68f375c0ef858194be97ca5b6069/ruff-0.12.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42a67d16e5b1ffc6d21c5f67851e0e769517fb57a8ebad1d0781b30888aa704e", size = 11901110, upload-time = "2025-09-04T16:49:32.07Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/3d/f8b1038f4b9822e26ec3d5b49cf2bc313e3c1564cceb4c1a42820bf74853/ruff-0.12.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b216ec0a0674e4b1214dcc998a5088e54eaf39417327b19ffefba1c4a1e4971e", size = 13668352, upload-time = "2025-09-04T16:49:35.148Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/0e/91421368ae6c4f3765dd41a150f760c5f725516028a6be30e58255e3c668/ruff-0.12.12-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:59f909c0fdd8f1dcdbfed0b9569b8bf428cf144bec87d9de298dcd4723f5bee8", size = 14638365, upload-time = "2025-09-04T16:49:38.892Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/5d/88f3f06a142f58ecc8ecb0c2fe0b82343e2a2b04dcd098809f717cf74b6c/ruff-0.12.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ac93d87047e765336f0c18eacad51dad0c1c33c9df7484c40f98e1d773876f5", size = 14060812, upload-time = "2025-09-04T16:49:42.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/fc/8962e7ddd2e81863d5c92400820f650b86f97ff919c59836fbc4c1a6d84c/ruff-0.12.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01543c137fd3650d322922e8b14cc133b8ea734617c4891c5a9fccf4bfc9aa92", size = 13050208, upload-time = "2025-09-04T16:49:46.434Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/06/8deb52d48a9a624fd37390555d9589e719eac568c020b27e96eed671f25f/ruff-0.12.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afc2fa864197634e549d87fb1e7b6feb01df0a80fd510d6489e1ce8c0b1cc45", size = 13311444, upload-time = "2025-09-04T16:49:49.931Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/81/de5a29af7eb8f341f8140867ffb93f82e4fde7256dadee79016ac87c2716/ruff-0.12.12-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:0c0945246f5ad776cb8925e36af2438e66188d2b57d9cf2eed2c382c58b371e5", size = 13279474, upload-time = "2025-09-04T16:49:53.465Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/14/d9577fdeaf791737ada1b4f5c6b59c21c3326f3f683229096cccd7674e0c/ruff-0.12.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a0fbafe8c58e37aae28b84a80ba1817f2ea552e9450156018a478bf1fa80f4e4", size = 12070204, upload-time = "2025-09-04T16:49:56.882Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/04/a910078284b47fad54506dc0af13839c418ff704e341c176f64e1127e461/ruff-0.12.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b9c456fb2fc8e1282affa932c9e40f5ec31ec9cbb66751a316bd131273b57c23", size = 11880347, upload-time = "2025-09-04T16:49:59.729Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/58/30185fcb0e89f05e7ea82e5817b47798f7fa7179863f9d9ba6fd4fe1b098/ruff-0.12.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5f12856123b0ad0147d90b3961f5c90e7427f9acd4b40050705499c98983f489", size = 12891844, upload-time = "2025-09-04T16:50:02.591Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/9c/28a8dacce4855e6703dcb8cdf6c1705d0b23dd01d60150786cd55aa93b16/ruff-0.12.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:26a1b5a2bf7dd2c47e3b46d077cd9c0fc3b93e6c6cc9ed750bd312ae9dc302ee", size = 13360687, upload-time = "2025-09-04T16:50:05.8Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/fa/05b6428a008e60f79546c943e54068316f32ec8ab5c4f73e4563934fbdc7/ruff-0.12.12-py3-none-win32.whl", hash = "sha256:173be2bfc142af07a01e3a759aba6f7791aa47acf3604f610b1c36db888df7b1", size = 12052870, upload-time = "2025-09-04T16:50:09.121Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/60/d1e335417804df452589271818749d061b22772b87efda88354cf35cdb7a/ruff-0.12.12-py3-none-win_amd64.whl", hash = "sha256:e99620bf01884e5f38611934c09dd194eb665b0109104acae3ba6102b600fd0d", size = 13178016, upload-time = "2025-09-04T16:50:12.559Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/7e/61c42657f6e4614a4258f1c3b0c5b93adc4d1f8575f5229d1906b483099b/ruff-0.12.12-py3-none-win_arm64.whl", hash = "sha256:2a8199cab4ce4d72d158319b63370abf60991495fb733db96cd923a34c52d093", size = 12256762, upload-time = "2025-09-04T16:50:15.737Z" },
|
||||
]
|
||||
|
Reference in New Issue
Block a user