neue Sortierung nach mp3-tags

This commit is contained in:
2026-09-29 12:17:10 +02:00
parent 21a5fe9937
commit 68019352e2
+61 -8
View File
@@ -2,6 +2,7 @@ import os
import signal
import subprocess
import threading
import json
import time
from datetime import datetime
from pathlib import Path
@@ -137,6 +138,51 @@ def format_duration(seconds):
return f"{minutes}:{seconds:02d}"
def read_metadata(path):
"""Read common ID3/FFmpeg metadata from an MP3."""
try:
result = subprocess.run(
["ffprobe", "-v", "error", "-show_entries",
"format_tags=date,artist,title,album", "-of", "json", str(path)],
capture_output=True, text=True, timeout=10,
)
if result.returncode != 0:
return {}
data = json.loads(result.stdout)
tags = data.get("format", {}).get("tags", {}) or {}
return {str(k).lower(): str(v) for k, v in tags.items() if v is not None}
except Exception:
return {}
def metadata_datetime(path):
tags = read_metadata(path)
value = tags.get("date", "")
if value:
try:
dt = datetime.fromisoformat(value.replace("Z", "+00:00"))
if dt.tzinfo is None:
dt = dt.replace(tzinfo=TIMEZONE)
return dt.astimezone(TIMEZONE).strftime("%d.%m.%Y %H:%M")
except ValueError:
pass
return format_datetime(path.stat().st_mtime)
def metadata_sort_key(path):
tags = read_metadata(path)
value = tags.get("date", "")
if value:
try:
dt = datetime.fromisoformat(value.replace("Z", "+00:00"))
if dt.tzinfo is None:
dt = dt.replace(tzinfo=TIMEZONE)
return dt.timestamp()
except ValueError:
pass
return path.stat().st_mtime
def get_duration(filename, directory=RECORDINGS_DIR):
path = directory / filename
@@ -741,9 +787,10 @@ a.button:hover {
<table>
<thead>
<tr>
<th>Start</th>
<th>Datei</th>
<th>Größe</th>
<th>Zeitpunkt</th>
<th>Redner</th>
<th>Beschreibung</th>
<th>Veranstaltung</th>
<th>Dauer</th>
<th>Wiedergabe</th>
<th></th>
@@ -757,9 +804,11 @@ a.button:hover {
<td>{{ item.datetime }}</td>
<td>{{ item.filename }}</td>
<td>{{ item.artist or "–" }}</td>
<td>{{ item.size }}</td>
<td>{{ item.title or "–" }}</td>
<td>{{ item.album or "–" }}</td>
<td>{{ item.duration }}</td>
@@ -855,17 +904,21 @@ def render_index():
for path in FINISHED_DIR.glob("*.mp3"):
try:
stat = path.stat()
tags = read_metadata(path)
files.append({
"filename": path.name,
"datetime": format_datetime(stat.st_mtime),
"datetime": metadata_datetime(path),
"artist": tags.get("artist", ""),
"title": tags.get("title", ""),
"album": tags.get("album", ""),
"size": format_size(stat.st_size),
"duration": format_duration(get_duration(path.name, FINISHED_DIR)),
"mtime": stat.st_mtime,
"sort_date": metadata_sort_key(path),
})
except FileNotFoundError:
continue
files.sort(key=lambda item: item["mtime"], reverse=True)
files.sort(key=lambda item: item["sort_date"], reverse=True)
with state_lock:
process = ffmpeg_process