From 5f3dd3ce20f2711b747f9c3acfd49ce389de028b Mon Sep 17 00:00:00 2001 From: SBCrumb Date: Thu, 25 Sep 2025 09:07:14 -0400 Subject: [PATCH] debug: Add comprehensive debugging for title extraction - Add detailed debug logging to _extract_title_from_filename() method - Log file search, regex pattern matching, and title cleanup process - Fix Tier 2 processing to call _get_episode_metadata() for title extraction - Add debug logging to _get_episode_metadata() to trace execution flow - Include both .mkv and .mp4 file checking with detailed logs This should help identify why title extraction isn't working for recreated NFO files and provide visibility into the extraction process. --- nfoguard.py | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/nfoguard.py b/nfoguard.py index 50d9ab4..6e81903 100644 --- a/nfoguard.py +++ b/nfoguard.py @@ -654,12 +654,14 @@ class TVProcessor: source = existing_episode["source"] aired = existing_episode.get("aired") - # Create NFO with existing data (no enhanced metadata needed) + # Create NFO with existing data, but try to add title from filename if missing if config.manage_nfo and dateadded: + # Try to extract title from filename as fallback for Tier 2 processing + enhanced_metadata = self._get_episode_metadata(None, season_num, episode_num, season_path) self.nfo_manager.create_episode_nfo( season_path, season_num, episode_num, aired, dateadded, source, config.lock_metadata, - None # No enhanced metadata for database-cached episodes + enhanced_metadata # Include filename-extracted title if available ) # Update file mtime if enabled @@ -777,10 +779,15 @@ class TVProcessor: # If no title from Sonarr, try to extract from filename if not metadata["title"] and season_dir: + _log("DEBUG", f"📁 No title from Sonarr for S{season_num:02d}E{episode_num:02d}, trying filename extraction") filename_title = self._extract_title_from_filename(season_dir, season_num, episode_num) if filename_title: metadata["title"] = filename_title - _log("INFO", f"Using filename-extracted title for S{season_num:02d}E{episode_num:02d}: '{filename_title}'") + _log("INFO", f"✅ Using filename-extracted title for S{season_num:02d}E{episode_num:02d}: '{filename_title}'") + else: + _log("DEBUG", f"⚠️ No filename title extracted for S{season_num:02d}E{episode_num:02d}") + elif metadata["title"]: + _log("DEBUG", f"✅ Using Sonarr title for S{season_num:02d}E{episode_num:02d}: '{metadata['title']}'") # Return metadata if we have at least some information if any(metadata.values()): @@ -794,36 +801,51 @@ class TVProcessor: import re # Look for video files matching this episode season_pattern = f"S{season_num:02d}E{episode_num:02d}" + _log("DEBUG", f"🔍 Searching for title in files for {season_pattern} in directory: {season_dir}") for video_file in season_dir.glob("*.mkv"): filename = video_file.name + _log("DEBUG", f"🔍 Checking file: {filename}") if season_pattern in filename: + _log("DEBUG", f"✅ Found matching file: {filename}") # Pattern: SeriesName-S01E01-Episode Title[WEBDL-1080p][AAC2.0][h264].mkv # Extract the part between season/episode and the first bracket - match = re.search(rf'{season_pattern}-(.*?)\[', filename) + pattern = rf'{season_pattern}-(.*?)\[' + _log("DEBUG", f"🔍 Using regex pattern: {pattern}") + match = re.search(pattern, filename) if match: title = match.group(1).strip() + _log("DEBUG", f"🔍 Raw extracted title: '{title}'") # Clean up common encoding artifacts and separators title = title.replace('-', ' ').strip() if title: - _log("DEBUG", f"Extracted title from filename: '{title}' for {season_pattern}") + _log("INFO", f"✅ Extracted title from filename: '{title}' for {season_pattern}") return title + else: + _log("DEBUG", f"⚠️ Title was empty after cleanup") + else: + _log("DEBUG", f"⚠️ Regex pattern didn't match filename") # Also check .mp4 files for video_file in season_dir.glob("*.mp4"): filename = video_file.name + _log("DEBUG", f"🔍 Checking .mp4 file: {filename}") if season_pattern in filename: - match = re.search(rf'{season_pattern}-(.*?)\[', filename) + _log("DEBUG", f"✅ Found matching .mp4 file: {filename}") + pattern = rf'{season_pattern}-(.*?)\[' + match = re.search(pattern, filename) if match: title = match.group(1).strip() + _log("DEBUG", f"🔍 Raw extracted title from .mp4: '{title}'") title = title.replace('-', ' ').strip() if title: - _log("DEBUG", f"Extracted title from filename: '{title}' for {season_pattern}") + _log("INFO", f"✅ Extracted title from .mp4 filename: '{title}' for {season_pattern}") return title except Exception as e: - _log("DEBUG", f"Error extracting title from filename for S{season_num:02d}E{episode_num:02d}: {e}") + _log("ERROR", f"Error extracting title from filename for S{season_num:02d}E{episode_num:02d}: {e}") + _log("DEBUG", f"⚠️ No title found in filenames for {season_pattern}") return None def _gather_season_episode_dates(self, series_path: Path, imdb_id: str, season_num: int, disk_episodes: Dict[Tuple[int, int], List[Path]], series_metadata: Optional[Dict[str, Any]] = None) -> Dict[Tuple[int, int], Tuple[Optional[str], Optional[str], str]]: