import os import subprocess from datetime import datetime, timedelta # ========================================== # Einstellungen # ========================================== FFMPEG_EXE = r"C:\PortableApps\LIVE\ffmpeg.exe" TARGET_FOLDER = r"D:\Downloads_ZDF" # ========================================== # Senderliste # ========================================== CHANNELS = { "1": { "name": "DasErste", "url": "https://daserste-live.ard-mcdn.de/daserste/live/hls/de/master.m3u8" }, "2": { "name": "ZDF", "url": "http://zdf-hls-15.akamaized.net/hls/live/2016498/de/high/master.m3u8" }, "3": { "name": "ZDFneo", "url": "https://zdf-hls-16.akamaized.net/hls/live/2016499/de/high/master.m3u8" }, "4": { "name": "ZDFinfo", "url": "https://zdf-hls-17.akamaized.net/hls/live/2016500/de/high/master.m3u8" }, "5": { "name": "3sat", "url": "https://zdf-hls-18.akamaized.net/hls/live/2016501/dach/high/master.m3u8" }, "6": { "name": "ARTE", "url": "https://artesimulcast.akamaized.net/hls/live/2030993/artelive_de/master.m3u8" }, "7": { "name": "tagesschau24", "url": "https://tagesschau.akamaized.net/hls/live/2020117/tagesschau/tagesschau_3/master.m3u8" }, "8": { "name": "ONE", "url": "https://mcdn-one.ard.de/ardone/hls/master.m3u8" }, "9": { "name": "ARDalpha", "url": "https://mcdn.br.de/br/fs/ard_alpha/hls/de/master.m3u8" } } # ========================================== # Hilfsfunktion # ========================================== def parse_hhmm(text): try: hours, minutes = map(int, text.split(":")) return timedelta(hours=hours, minutes=minutes) except: return None # ========================================== # Zielordner anlegen # ========================================== os.makedirs(TARGET_FOLDER, exist_ok=True) # ========================================== # Sender auswählen # ========================================== print("\nVerfügbare Sender:") print("------------------") for key in sorted(CHANNELS): print(f"{key} = {CHANNELS[key]['name']}") choice = input("\nSender wählen: ") if choice not in CHANNELS: print("\nFehler: Ungültige Auswahl!") input("ENTER...") exit() sender_name = CHANNELS[choice]["name"] url = CHANNELS[choice]["url"] # ========================================== # Wie weit zurück? # ========================================== back_time_str = input("Wie weit zurück? (hh:mm): ") back_time = parse_hhmm(back_time_str) if back_time is None: print("\nFehler: Ungültiges Format!") print("Beispiel: 01:30 = 1 Stunde 30 Minuten") input("ENTER...") exit() # ========================================== # Aufnahmedauer # ========================================== duration_str = input("Aufnahmedauer? (hh:mm): ") duration = parse_hhmm(duration_str) if duration is None: print("\nFehler: Ungültiges Format!") print("Beispiel: 00:45 = 45 Minuten") input("ENTER...") exit() # ========================================== # Berechnungen # ========================================== back_seconds = int(back_time.total_seconds()) duration_seconds = int(duration.total_seconds()) if back_seconds > 10800: print("\nFehler: Maximal 3 Stunden Rücksprung möglich!") input("ENTER...") exit() segments_back = round(back_seconds / 2) # ========================================== # Dateiname erzeugen # ========================================== now = datetime.now() recording_start = now - back_time recording_end = recording_start + duration date_part = recording_start.strftime("%Y-%m-%d") start_part = recording_start.strftime("%H-%M-%S") end_part = recording_end.strftime("%H-%M-%S") filename = ( f"{sender_name}_{date_part}_{start_part}_-_{end_part}.mp4" ) output_file = os.path.join(TARGET_FOLDER, filename) # ========================================== # Informationen anzeigen # ========================================== print("\n=========================================") print("Download wird gestartet") print("=========================================") print(f"Sender : {sender_name}") print(f"Zurückspringen : {back_time_str}") print(f"Aufnahmedauer : {duration_str}") print(f"Segmente : {segments_back}") print(f"Ausgabedatei : {output_file}") print("=========================================\n") # ========================================== # FFmpeg starten # ========================================== subprocess.run([ FFMPEG_EXE, "-live_start_index", f"-{segments_back}", "-i", url, "-t", str(duration_seconds), "-c", "copy", output_file ]) # ========================================== # Ende # ========================================== print("\nDownload abgeschlossen.") input("ENTER...")