Files
serman-rss-wrapper-mixcloud/fix_covers.py

110 lines
4.0 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Cover-Optimierungs-Tool
Repariert alle Cover-Bilder im _audio-Verzeichnis für Apple Podcasts Kompatibilität.
"""
from pathlib import Path
import urllib.parse
def fix_all_covers(audio_dir="../httpdocs/_audio"):
"""Optimiert alle Cover-Dateien im Audio-Verzeichnis."""
try:
from PIL import Image
except ImportError:
print("❌ PIL/Pillow nicht installiert!")
print("💡 Installiere mit: uv add pillow")
return False
audio_path = Path(audio_dir)
if not audio_path.exists():
print(f"❌ Audio-Verzeichnis '{audio_dir}' existiert nicht!")
return False
# Finde alle Cover-Dateien
cover_files = list(audio_path.glob("cover_*.jpg"))
print(f"🖼️ {len(cover_files)} Cover-Dateien gefunden")
if not cover_files:
print(" Keine Cover-Dateien zum Optimieren gefunden")
return True
fixed_count = 0
for cover_file in cover_files:
try:
print(f"\n📋 Prüfe: {cover_file.name}")
# Lade das Bild
image = Image.open(cover_file)
original_width, original_height = image.size
print(f" 📐 Aktuelle Größe: {original_width}x{original_height}px")
# Prüfe ob Optimierung nötig ist
needs_fix = False
if original_width < 1400 or original_height < 1400:
print(f" ⚠️ Zu klein (< 1400px)")
needs_fix = True
elif original_width > 3000 or original_height > 3000:
print(f" ⚠️ Zu groß (> 3000px)")
needs_fix = True
elif original_width != original_height:
print(f" ⚠️ Nicht quadratisch")
needs_fix = True
if not needs_fix:
print(f" ✅ Cover ist bereits optimal")
continue
# Bestimme Zielgröße
if original_width < 1400 or original_height < 1400:
target_size = 1400
elif original_width > 3000 or original_height > 3000:
target_size = 3000
else:
target_size = min(original_width, original_height)
if target_size < 1400:
target_size = 1400
elif target_size > 3000:
target_size = 3000
print(f" 🎯 Zielgröße: {target_size}x{target_size}px")
# Mache quadratisch falls nötig
if original_width != original_height:
size = min(original_width, original_height)
left = (original_width - size) // 2
top = (original_height - size) // 2
right = left + size
bottom = top + size
image = image.crop((left, top, right, bottom))
print(f" ✂️ Zugeschnitten auf quadratisch")
# Skaliere auf Zielgröße
image = image.resize((target_size, target_size), Image.Resampling.LANCZOS)
# Konvertiere zu RGB falls nötig
if image.mode in ('RGBA', 'LA', 'P'):
background = Image.new('RGB', image.size, (255, 255, 255))
if image.mode == 'P':
image = image.convert('RGBA')
background.paste(image, mask=image.split()[-1] if image.mode == 'RGBA' else None)
image = background
# Speichere optimiertes Cover
image.save(cover_file, 'JPEG', quality=95, optimize=True)
final_width, final_height = image.size
print(f" ✅ Optimiert: {final_width}x{final_height}px")
fixed_count += 1
except Exception as e:
print(f" ❌ Fehler bei {cover_file.name}: {e}")
print(f"\n🎉 {fixed_count} von {len(cover_files)} Cover-Dateien optimiert!")
return True
if __name__ == "__main__":
fix_all_covers()