diff --git a/ToDo.md b/ToDo.md index 4efb45b..aff9a8a 100644 --- a/ToDo.md +++ b/ToDo.md @@ -23,7 +23,8 @@ TODO Steps: 20. ✅ Add loading indicators for metadata extraction 21. ✅ Add error handling for file operations and metadata extraction 22. 🔄 Implement blue highlighting for changed parts in proposed filename display (show differences between current and proposed names) -23. Implement metadata editing capabilities (future enhancement) -24. Add batch rename operations (future enhancement) -25. Add configuration file support (future enhancement) -26. Add plugin system for custom extractors/formatters (future enhancement) \ No newline at end of file +23. 🔄 Implement build script to exclude dev commands (bump-version, release) from distributed package +24. Implement metadata editing capabilities (future enhancement) +25. Add batch rename operations (future enhancement) +26. Add configuration file support (future enhancement) +27. Add plugin system for custom extractors/formatters (future enhancement) \ No newline at end of file diff --git a/dist/renamer-0.2.9-py3-none-any.whl b/dist/renamer-0.2.9-py3-none-any.whl new file mode 100644 index 0000000..6efd1e5 Binary files /dev/null and b/dist/renamer-0.2.9-py3-none-any.whl differ diff --git a/pyproject.toml b/pyproject.toml index ff1ee31..dfb95fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "renamer" -version = "0.2.8" +version = "0.2.9" description = "Terminal-based media file renamer and metadata viewer" readme = "README.md" requires-python = ">=3.11" diff --git a/renamer/constants.py b/renamer/constants.py index 5d39475..43db434 100644 --- a/renamer/constants.py +++ b/renamer/constants.py @@ -51,11 +51,21 @@ FRAME_CLASSES = { "typical_widths": [640, 704, 720], "description": "Standard Definition (SD) - DVD quality", }, + "480i": { + "nominal_height": 480, + "typical_widths": [640, 704, 720], + "description": "Standard Definition (SD) interlaced - NTSC quality", + }, "576p": { "nominal_height": 576, "typical_widths": [720, 768], "description": "PAL Standard Definition (SD) - European DVD quality", }, + "576i": { + "nominal_height": 576, + "typical_widths": [720, 768], + "description": "PAL Standard Definition (SD) interlaced - European quality", + }, "720p": { "nominal_height": 720, "typical_widths": [1280], @@ -66,6 +76,11 @@ FRAME_CLASSES = { "typical_widths": [1920], "description": "Full High Definition (FHD) - 1080p HD", }, + "1080i": { + "nominal_height": 1080, + "typical_widths": [1920], + "description": "Full High Definition (FHD) interlaced - 1080i HD", + }, "1440p": { "nominal_height": 1440, "typical_widths": [2560], diff --git a/renamer/extractors/filename_extractor.py b/renamer/extractors/filename_extractor.py index 69c0426..ffea6d4 100644 --- a/renamer/extractors/filename_extractor.py +++ b/renamer/extractors/filename_extractor.py @@ -11,7 +11,6 @@ class FilenameExtractor: def __init__(self, file_path: Path): self.file_path = file_path self.file_name = file_path.name - self.file_name = self._normalize_cyrillic(self.file_name) def _normalize_cyrillic(self, text: str) -> str: """Normalize Cyrillic characters to English equivalents for parsing""" @@ -157,10 +156,18 @@ class FilenameExtractor: def extract_frame_class(self) -> str | None: """Extract frame class from filename (480p, 720p, 1080p, 2160p, etc.)""" - # First check for specific numeric resolutions - match = re.search(r'(\d{3,4})[pi]', self.file_name, re.IGNORECASE) + # Normalize Cyrillic characters for resolution parsing + normalized_name = self._normalize_cyrillic(self.file_name) + + # First check for specific numeric resolutions with p/i + match = re.search(r'(\d{3,4})([pi])', normalized_name, re.IGNORECASE) if match: height = int(match.group(1)) + scan_type = match.group(2).lower() + frame_class = f"{height}{scan_type}" + if frame_class in FRAME_CLASSES: + return frame_class + # Fallback to height-based if not in constants return self._get_frame_class_from_height(height) # If no specific resolution found, check for quality indicators diff --git a/renamer/extractors/mediainfo_extractor.py b/renamer/extractors/mediainfo_extractor.py index 77c5819..4b2177d 100644 --- a/renamer/extractors/mediainfo_extractor.py +++ b/renamer/extractors/mediainfo_extractor.py @@ -59,7 +59,27 @@ class MediaInfoExtractor: return None height = getattr(self.video_tracks[0], 'height', None) if height: - return self._get_frame_class_from_height(height) + # Check if interlaced + interlaced = getattr(self.video_tracks[0], 'interlaced', None) + scan_type = 'i' if interlaced == 'Yes' else 'p' + + # First try exact match + frame_class = f"{height}{scan_type}" + if frame_class in FRAME_CLASSES: + return frame_class + + # Find closest height with same scan type + closest_height = None + min_diff = float('inf') + for fc, info in FRAME_CLASSES.items(): + if fc.endswith(scan_type): + diff = abs(height - info['nominal_height']) + if diff < min_diff: + min_diff = diff + closest_height = info['nominal_height'] + + if closest_height and min_diff <= 50: + return f"{closest_height}{scan_type}" return None def extract_resolution(self) -> tuple[int, int] | None: diff --git a/renamer/test/filenames/[02] Balto Wolf Quest (2002) [1080i,ukr,eng].mkv b/renamer/test/filenames/[02] Balto Wolf Quest (2002) [1080i,ukr,eng].mkv new file mode 100644 index 0000000..e69de29 diff --git a/uv.lock b/uv.lock index b79f558..c52c436 100644 --- a/uv.lock +++ b/uv.lock @@ -164,7 +164,7 @@ wheels = [ [[package]] name = "renamer" -version = "0.2.8" +version = "0.2.9" source = { editable = "." } dependencies = [ { name = "langcodes" },