fix: Update conversion service and UI to support MP4 files in conversion process

This commit is contained in:
sHa
2026-01-04 13:41:35 +00:00
parent 13d610b1c3
commit e4314f1587
6 changed files with 16 additions and 13 deletions

BIN
dist/renamer-0.7.7-py3-none-any.whl vendored Normal file

Binary file not shown.

View File

@@ -1,6 +1,6 @@
[project] [project]
name = "renamer" name = "renamer"
version = "0.7.6" version = "0.7.7"
description = "Terminal-based media file renamer and metadata viewer" description = "Terminal-based media file renamer and metadata viewer"
readme = "README.md" readme = "README.md"
requires-python = ">=3.11" requires-python = ">=3.11"

View File

@@ -69,7 +69,7 @@ class AppCommandProvider(Provider):
("scan", "Scan Directory", "Scan current directory for media files (s)"), ("scan", "Scan Directory", "Scan current directory for media files (s)"),
("refresh", "Refresh File", "Refresh metadata for selected file (f)"), ("refresh", "Refresh File", "Refresh metadata for selected file (f)"),
("rename", "Rename File", "Rename the selected file (r)"), ("rename", "Rename File", "Rename the selected file (r)"),
("convert", "Convert to MKV", "Convert AVI/MPG/MPEG/WebM file to MKV container with metadata (c)"), ("convert", "Convert to MKV", "Convert AVI/MPG/MPEG/WebM/MP4 file to MKV container with metadata (c)"),
("delete", "Delete File", "Delete the selected file (d)"), ("delete", "Delete File", "Delete the selected file (d)"),
("toggle_mode", "Toggle Display Mode", "Switch between technical and catalog view (m)"), ("toggle_mode", "Toggle Display Mode", "Switch between technical and catalog view (m)"),
("expand", "Toggle Tree Expansion", "Expand or collapse all tree nodes (p)"), ("expand", "Toggle Tree Expansion", "Expand or collapse all tree nodes (p)"),
@@ -390,7 +390,7 @@ By Category:"""
self.notify("Proposed name is the same as current name; no rename needed.", severity="information", timeout=3) self.notify("Proposed name is the same as current name; no rename needed.", severity="information", timeout=3)
async def action_convert(self): async def action_convert(self):
"""Convert AVI/MPG/MPEG/WebM file to MKV with metadata preservation.""" """Convert AVI/MPG/MPEG/WebM/MP4 file to MKV with metadata preservation."""
tree = self.query_one("#file_tree", Tree) tree = self.query_one("#file_tree", Tree)
node = tree.cursor_node node = tree.cursor_node
@@ -403,7 +403,7 @@ By Category:"""
# Check if file can be converted # Check if file can be converted
if not conversion_service.can_convert(file_path): if not conversion_service.can_convert(file_path):
self.notify("Only AVI, MPG, MPEG, and WebM files can be converted to MKV", severity="error", timeout=3) self.notify("Only AVI, MPG, MPEG, WebM, and MP4 files can be converted to MKV", severity="error", timeout=3)
return return
# Create extractor for metadata # Create extractor for metadata

View File

@@ -505,10 +505,13 @@ class ConvertConfirmScreen(Screen):
def on_button_pressed(self, event): def on_button_pressed(self, event):
if event.button.id == "convert_copy": if event.button.id == "convert_copy":
self._do_conversion(encode_hevc=False) self._do_conversion(encode_hevc=False)
event.stop() # Prevent key event from also triggering
elif event.button.id == "convert_hevc": elif event.button.id == "convert_hevc":
self._do_conversion(encode_hevc=True) self._do_conversion(encode_hevc=True)
event.stop() # Prevent key event from also triggering
elif event.button.id == "cancel": elif event.button.id == "cancel":
self.app.pop_screen() # type: ignore self.app.pop_screen() # type: ignore
event.stop() # Prevent key event from also triggering
def _do_conversion(self, encode_hevc: bool): def _do_conversion(self, encode_hevc: bool):
"""Start conversion with the specified encoding mode.""" """Start conversion with the specified encoding mode."""

View File

@@ -1,6 +1,6 @@
"""Conversion service for video to MKV remux with metadata preservation. """Conversion service for video to MKV remux with metadata preservation.
This service manages the process of converting AVI/MPG/MPEG/WebM files to MKV container: This service manages the process of converting AVI/MPG/MPEG/WebM/MP4 files to MKV container:
- Fast stream copy (no re-encoding) - Fast stream copy (no re-encoding)
- Audio language detection and mapping from filename - Audio language detection and mapping from filename
- Subtitle file detection and inclusion - Subtitle file detection and inclusion
@@ -24,7 +24,7 @@ class ConversionService:
"""Service for converting video files to MKV with metadata preservation. """Service for converting video files to MKV with metadata preservation.
This service handles: This service handles:
- Validating video files for conversion (AVI, MPG, MPEG, WebM) - Validating video files for conversion (AVI, MPG, MPEG, WebM, MP4)
- Detecting nearby subtitle files - Detecting nearby subtitle files
- Mapping audio languages from filename to tracks - Mapping audio languages from filename to tracks
- Building ffmpeg command for fast remux or HEVC encoding - Building ffmpeg command for fast remux or HEVC encoding
@@ -168,18 +168,18 @@ class ConversionService:
return ':'.join(base_params + cpu_params) return ':'.join(base_params + cpu_params)
def can_convert(self, file_path: Path) -> bool: def can_convert(self, file_path: Path) -> bool:
"""Check if a file can be converted (is AVI, MPG, MPEG, or WebM). """Check if a file can be converted (is AVI, MPG, MPEG, WebM, or MP4).
Args: Args:
file_path: Path to the file to check file_path: Path to the file to check
Returns: Returns:
True if file is AVI, MPG, MPEG, or WebM and can be converted True if file is AVI, MPG, MPEG, WebM, or MP4 and can be converted
""" """
if not file_path.exists() or not file_path.is_file(): if not file_path.exists() or not file_path.is_file():
return False return False
return file_path.suffix.lower() in {'.avi', '.mpg', '.mpeg', '.webm'} return file_path.suffix.lower() in {'.avi', '.mpg', '.mpeg', '.webm', '.mp4', '.m4v'}
def find_subtitle_files(self, video_path: Path) -> List[Path]: def find_subtitle_files(self, video_path: Path) -> List[Path]:
"""Find subtitle files near the video file. """Find subtitle files near the video file.
@@ -280,7 +280,7 @@ class ConversionService:
- Sets MKV title from filename - Sets MKV title from filename
Args: Args:
source_path: Source video file (AVI, MPG, MPEG, or WebM) source_path: Source video file (AVI, MPG, MPEG, WebM, or MP4)
mkv_path: Destination MKV file mkv_path: Destination MKV file
audio_languages: Language codes for each audio track audio_languages: Language codes for each audio track
subtitle_files: List of subtitle files to include subtitle_files: List of subtitle files to include
@@ -361,7 +361,7 @@ class ConversionService:
"""Convert video file to MKV with metadata preservation. """Convert video file to MKV with metadata preservation.
Args: Args:
avi_path: Source video file path (AVI, MPG, MPEG, or WebM) avi_path: Source video file path (AVI, MPG, MPEG, WebM, or MP4)
extractor: Optional MediaExtractor (creates new if None) extractor: Optional MediaExtractor (creates new if None)
output_path: Optional output path (defaults to same name with .mkv) output_path: Optional output path (defaults to same name with .mkv)
dry_run: If True, build command but don't execute dry_run: If True, build command but don't execute
@@ -382,7 +382,7 @@ class ConversionService:
""" """
# Validate input # Validate input
if not self.can_convert(avi_path): if not self.can_convert(avi_path):
error_msg = f"File is not a supported format (AVI/MPG/MPEG/WebM) or doesn't exist: {avi_path}" error_msg = f"File is not a supported format (AVI/MPG/MPEG/WebM/MP4) or doesn't exist: {avi_path}"
logger.error(error_msg) logger.error(error_msg)
return False, error_msg return False, error_msg

2
uv.lock generated
View File

@@ -462,7 +462,7 @@ wheels = [
[[package]] [[package]]
name = "renamer" name = "renamer"
version = "0.7.6" version = "0.7.7"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "langcodes" }, { name = "langcodes" },