Regenerate M3U playlist after rename with correct order and durations
_update_m3u(): writes #EXTM3U + #EXTINF:seconds,Artist - Title + filename per track, in disc/track order (same order as the renamed files). Duration is read from mutagen; -1 if unavailable. execute_album(): after renaming, finds existing *.m3u / *.m3u8 in the album directory and overwrites it. Only triggered when files_renamed > 0 and a playlist file exists — never creates a new one from scratch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
40a2ef3fb6
commit
888464b4d0
1 changed files with 40 additions and 0 deletions
40
executor.py
40
executor.py
|
|
@ -206,6 +206,33 @@ def write_tags(path: Path, proposal: TrackProposal, album_proposal: AlbumProposa
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _update_m3u(m3u_path: Path, tracks: List[tuple]) -> bool:
|
||||||
|
"""
|
||||||
|
Schreibt M3U neu mit den umbenannten Dateien in Track-Reihenfolge.
|
||||||
|
tracks: [(TrackProposal, actual_path_after_rename), ...]
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
lines = ["#EXTM3U"]
|
||||||
|
for tp, track_path in tracks:
|
||||||
|
duration = -1
|
||||||
|
if HAS_MUTAGEN:
|
||||||
|
try:
|
||||||
|
audio = MutagenFile(str(track_path))
|
||||||
|
if audio and hasattr(audio, "info") and audio.info:
|
||||||
|
duration = int(audio.info.length)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
label = f"{tp.artist} - {tp.title}" if tp.artist else (tp.title or track_path.stem)
|
||||||
|
lines.append(f"#EXTINF:{duration},{label}")
|
||||||
|
lines.append(track_path.name)
|
||||||
|
m3u_path.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
||||||
|
print(f" 📋 Playlist aktualisiert: {m3u_path.name}")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ⚠️ M3U-Fehler {m3u_path.name}: {e}", file=sys.stderr)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def execute_album(
|
def execute_album(
|
||||||
proposal: AlbumProposal,
|
proposal: AlbumProposal,
|
||||||
backup_dir: Optional[Path],
|
backup_dir: Optional[Path],
|
||||||
|
|
@ -215,6 +242,7 @@ def execute_album(
|
||||||
report_data: List[Dict[str, Any]],
|
report_data: List[Dict[str, Any]],
|
||||||
) -> Dict[str, int]:
|
) -> Dict[str, int]:
|
||||||
stats = {"tags_written": 0, "covers_embedded": 0, "files_renamed": 0, "errors": 0}
|
stats = {"tags_written": 0, "covers_embedded": 0, "files_renamed": 0, "errors": 0}
|
||||||
|
final_tracks: List[tuple] = [] # (TrackProposal, final_path) für M3U
|
||||||
|
|
||||||
for tp in proposal.tracks:
|
for tp in proposal.tracks:
|
||||||
old_title = tp.path.stem
|
old_title = tp.path.stem
|
||||||
|
|
@ -263,6 +291,9 @@ def execute_album(
|
||||||
print(f" ⚠️ Umbenennungsfehler {tp.path.name}: {e}", file=sys.stderr)
|
print(f" ⚠️ Umbenennungsfehler {tp.path.name}: {e}", file=sys.stderr)
|
||||||
stats["errors"] += 1
|
stats["errors"] += 1
|
||||||
|
|
||||||
|
if not dry_run:
|
||||||
|
final_tracks.append((tp, new_path))
|
||||||
|
|
||||||
report_data.append({
|
report_data.append({
|
||||||
"status": "dry-run" if dry_run else "ok",
|
"status": "dry-run" if dry_run else "ok",
|
||||||
"album_dir": str(proposal.album_dir.name),
|
"album_dir": str(proposal.album_dir.name),
|
||||||
|
|
@ -284,6 +315,15 @@ def execute_album(
|
||||||
"sources": ", ".join(proposal.sources),
|
"sources": ", ".join(proposal.sources),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# M3U-Playlist aktualisieren wenn Dateien umbenannt wurden
|
||||||
|
if do_rename and not dry_run and stats["files_renamed"] > 0 and final_tracks:
|
||||||
|
m3u_files = (
|
||||||
|
list(proposal.album_dir.glob("*.m3u")) +
|
||||||
|
list(proposal.album_dir.glob("*.m3u8"))
|
||||||
|
)
|
||||||
|
if m3u_files:
|
||||||
|
_update_m3u(m3u_files[0], final_tracks)
|
||||||
|
|
||||||
# Nach allen Umbenennungen: Verzeichnis Linux-kompatibel bereinigen
|
# Nach allen Umbenennungen: Verzeichnis Linux-kompatibel bereinigen
|
||||||
if do_rename and not dry_run:
|
if do_rename and not dry_run:
|
||||||
sanitize_dir_names(proposal.album_dir)
|
sanitize_dir_names(proposal.album_dir)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue