Enhance project structure and add new files for enrichment and analysis

- Updated AGENTS.md to reflect changes in CLI commands and module organization, including the addition of an enrichment step and new functional modules.
- Introduced analysis.json, identities.json, inventory.csv, and plan.json to support enriched metadata and execution planning.
- Added CODE_IMPROVEMENTS.md to document identified code issues and proposed solutions for future enhancements.
- Updated README.md to include new enrichment features and configuration options.
- Removed unused dependency on ffmpeg-python from pyproject.toml.

These changes improve the overall functionality and maintainability of the Video Library Manager project.
This commit is contained in:
windyboy
2026-02-10 16:56:17 +08:00
parent f0c951ad7f
commit dcd87754cf
39 changed files with 145509 additions and 642 deletions
+87
View File
@@ -5,6 +5,7 @@ import pytest
from vlm.config import Config
from vlm.enrichment import _build_display_title, _build_providers, enrich_identities_data
from vlm.providers.base import ProviderResult
from vlm.providers.tmdb import TMDBAuthError
class DummyProvider:
@@ -12,9 +13,11 @@ class DummyProvider:
def __init__(self):
self.calls = 0
self.last_request_count = 0
def enrich(self, *, title: str, media_type: str, year=None):
self.calls += 1
self.last_request_count = 1
return ProviderResult(
provider="dummy",
canonical_id=f"dummy:{title}",
@@ -83,6 +86,7 @@ def test_enrich_flags_low_reputation_for_review(tmp_path, monkeypatch):
class LowScoreProvider(DummyProvider):
def enrich(self, *, title: str, media_type: str, year=None):
self.calls += 1
self.last_request_count = 1
return ProviderResult(
provider="dummy",
canonical_id=f"dummy:{title}",
@@ -192,9 +196,11 @@ def test_refresh_all_clears_stale_enrichment_fields(tmp_path, monkeypatch):
def __init__(self):
self.calls = 0
self.last_request_count = 0
def enrich(self, *, title: str, media_type: str, year=None):
self.calls += 1
self.last_request_count = 1
if self.calls == 1:
return ProviderResult(
provider="dummy",
@@ -264,3 +270,84 @@ def test_build_display_title_deduplicates_fallback_title(tmp_path):
payload = {"title_zh": None, "title_en": None}
assert _build_display_title(record, payload, config) == "Interstellar"
def test_enrich_without_provider_keys_does_not_count_api_calls(tmp_path):
"""Missing provider keys should not inflate API call metrics."""
config = Config(
library_root=tmp_path,
enrichment_cache_db=tmp_path / "cache.db",
enrichment_providers=["tmdb"],
translation_fallback_machine=True,
tmdb_api_key=None,
openai_api_key=None,
)
identities = {
"metadata": {},
"movies": [
{
"path": "/library/movie/Test.2020.mkv",
"filename": "Test.2020.mkv",
"category": "movie",
"title": "Test",
"year": 2020,
"confidence": 0.9,
"needs_review": False,
}
],
"series": [],
"anime": [],
"other": [],
}
_, stats = enrich_identities_data(identities, config, refresh_mode="refresh_all")
assert stats["api_calls"] == 0
assert stats["enriched"] == 0
assert stats["skip_reasons"] == {"no_key": 1}
def test_enrich_auth_failure_stops_immediately(tmp_path, monkeypatch):
"""Provider authentication errors should stop the run immediately."""
class AuthFailProvider:
name = "tmdb"
last_request_count = 1
def enrich(self, *, title: str, media_type: str, year=None):
raise TMDBAuthError("TMDB authentication failed (401/403)")
config = Config(
library_root=tmp_path,
enrichment_cache_db=tmp_path / "cache.db",
enrichment_providers=["tmdb"],
tmdb_api_key="fake-key",
translation_fallback_machine=False,
)
monkeypatch.setattr(
"vlm.enrichment._build_providers",
lambda _config, request_timeout, retries: [AuthFailProvider()],
)
identities = {
"metadata": {},
"movies": [
{
"path": "/library/movie/Test.2020.mkv",
"filename": "Test.2020.mkv",
"category": "movie",
"title": "Test",
"year": 2020,
"confidence": 0.9,
"needs_review": False,
}
],
"series": [],
"anime": [],
"other": [],
}
with pytest.raises(RuntimeError, match="authentication failed"):
enrich_identities_data(identities, config, refresh_mode="refresh_all")