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
+53 -26
View File
@@ -37,6 +37,10 @@ class Config:
translation_mode: str = "bidirectional"
translation_fallback_machine: bool = True
tmdb_api_key: Optional[str] = None
tmdb_bearer_token: Optional[str] = None
tmdb_language: str = "zh-CN"
tmdb_region: Optional[str] = None
tmdb_include_adult: bool = False
openai_api_key: Optional[str] = None
reputation_min_votes: int = 50
reputation_low_score_threshold: float = 6.0
@@ -82,11 +86,14 @@ def load_config(path: Path) -> Config:
"anime": ["anime"]
})
enrichment = data.get("enrichment", {})
enrichment = data.get("enrichment")
if enrichment is None:
enrichment = data.get("enrich", {})
translation = enrichment.get("translation", {})
api_keys = enrichment.get("api_keys", {})
reputation = enrichment.get("reputation", {})
naming = enrichment.get("naming", {})
tmdb = enrichment.get("tmdb", {})
return Config(
library_root=library_root,
@@ -110,6 +117,10 @@ def load_config(path: Path) -> Config:
translation_mode=translation.get("mode", "bidirectional"),
translation_fallback_machine=translation.get("fallback_machine", True),
tmdb_api_key=api_keys.get("tmdb"),
tmdb_bearer_token=api_keys.get("tmdb_bearer"),
tmdb_language=tmdb.get("language", "zh-CN"),
tmdb_region=tmdb.get("region"),
tmdb_include_adult=tmdb.get("include_adult", False),
openai_api_key=api_keys.get("openai"),
reputation_min_votes=reputation.get("min_votes", 50),
reputation_low_score_threshold=reputation.get("low_score_threshold", 6.0),
@@ -125,6 +136,38 @@ def create_default_config(path: Path) -> Config:
video_extensions=[".mp4", ".mkv", ".avi", ".mov", ".wmv", ".flv", ".webm", ".m4v"],
)
enrichment_content = {
"enabled": default_config.enrichment_enabled,
"incremental": default_config.enrichment_incremental,
"refresh_mode": default_config.enrichment_refresh_mode,
"providers": default_config.enrichment_providers,
"cache_db": str(default_config.enrichment_cache_db),
"max_concurrency": default_config.enrichment_max_concurrency,
"min_match_score": default_config.enrichment_min_match_score,
"translation": {
"mode": default_config.translation_mode,
"fallback_machine": default_config.translation_fallback_machine,
},
"api_keys": {
"tmdb": default_config.tmdb_api_key,
"tmdb_bearer": default_config.tmdb_bearer_token,
"openai": default_config.openai_api_key,
},
"tmdb": {
"language": default_config.tmdb_language,
"region": default_config.tmdb_region,
"include_adult": default_config.tmdb_include_adult,
},
"reputation": {
"min_votes": default_config.reputation_min_votes,
"low_score_threshold": default_config.reputation_low_score_threshold,
"policy": default_config.reputation_policy,
},
"naming": {
"title_format": default_config.naming_title_format,
},
}
yaml_content = {
"library_root": str(default_config.library_root),
"video_extensions": default_config.video_extensions,
@@ -137,31 +180,9 @@ def create_default_config(path: Path) -> Config:
"quarantine_dir": default_config.quarantine_dir,
"log_level": default_config.log_level,
"categories": default_config.categories,
"enrichment": {
"enabled": default_config.enrichment_enabled,
"incremental": default_config.enrichment_incremental,
"refresh_mode": default_config.enrichment_refresh_mode,
"providers": default_config.enrichment_providers,
"cache_db": str(default_config.enrichment_cache_db),
"max_concurrency": default_config.enrichment_max_concurrency,
"min_match_score": default_config.enrichment_min_match_score,
"translation": {
"mode": default_config.translation_mode,
"fallback_machine": default_config.translation_fallback_machine,
},
"api_keys": {
"tmdb": default_config.tmdb_api_key,
"openai": default_config.openai_api_key,
},
"reputation": {
"min_votes": default_config.reputation_min_votes,
"low_score_threshold": default_config.reputation_low_score_threshold,
"policy": default_config.reputation_policy,
},
"naming": {
"title_format": default_config.naming_title_format,
},
},
"enrichment": enrichment_content,
# Backward-compatible alias for users who prefer `enrich`.
"enrich": enrichment_content,
}
path.parent.mkdir(parents=True, exist_ok=True)
@@ -287,5 +308,11 @@ def validate_config(config: Config) -> list[str]:
errors.append("reputation_min_votes must be >= 0")
if not (0.0 <= config.reputation_low_score_threshold <= 10.0):
errors.append("reputation_low_score_threshold must be between 0.0 and 10.0")
if not isinstance(config.tmdb_language, str) or not config.tmdb_language.strip():
errors.append("tmdb_language must be a non-empty string")
if config.tmdb_region is not None and not isinstance(config.tmdb_region, str):
errors.append("tmdb_region must be a string when set")
if not isinstance(config.tmdb_include_adult, bool):
errors.append("tmdb_include_adult must be a boolean")
return errors