13.1.2026, 13:21
@dariely: Nic takového, jako aliasy v obecném slova smyslu u epg neexistuje. Je to tedy vždy o tom, buď na jedné straně (ve zdroji epg, tedy např. souboru mltv) upravit ta data a vytvořit v nich duplicitní záznamy s jinými channel id, nebo na straně druhé upravit ty identifikace v kódu klienta, nebo v datech, které generují nebo používají (playlisty). Úprava v klientech je samozřejmě náročná a není to ani úplně ta správná cesta, tedy modifikovat kód nějakého doplňku jiného autora. Ta úprava v datech, je už přijatelnější. Ale i tady to chce samozřejmě počítat s tím, že je potřeba tu funkci vytvořit v rámci nějakého kódu, doplňku/scriptu.
Já přijímám TV přes Tvheadend a mám značné množství kanálů z různých zdrojů, takže epg získávám několika různými způsoby. Primární je Webgrab++, ale mám i několik xmltv zdrojů, které stahuji a vybírám si z nich epg těch kanálů, které mě zajímají. A tady se hodí mít možnost filtrovat xmltv podle channel id. Nechtěl jsem se s tím vymýšlet a tak jsem si tuhle část kódu nechal napsat AI. A když jsem formuloval zadání, tak jsem tam rovnou nechal i přidat funkci přejmenování channel id. Ono to sice pro Tvheadend není potřeba, protože se to přemapování dá udělat v něm, ale protože tam mám i jiné funkce, hodilo se mi to tam mít. Tak tu definici té procedury, jako užitečného nástroje, uvádím. Je dostatečně okomentovaná, takže její použití je celkem zřejmé.
Já přijímám TV přes Tvheadend a mám značné množství kanálů z různých zdrojů, takže epg získávám několika různými způsoby. Primární je Webgrab++, ale mám i několik xmltv zdrojů, které stahuji a vybírám si z nich epg těch kanálů, které mě zajímají. A tady se hodí mít možnost filtrovat xmltv podle channel id. Nechtěl jsem se s tím vymýšlet a tak jsem si tuhle část kódu nechal napsat AI. A když jsem formuloval zadání, tak jsem tam rovnou nechal i přidat funkci přejmenování channel id. Ono to sice pro Tvheadend není potřeba, protože se to přemapování dá udělat v něm, ale protože tam mám i jiné funkce, hodilo se mi to tam mít. Tak tu definici té procedury, jako užitečného nástroje, uvádím. Je dostatečně okomentovaná, takže její použití je celkem zřejmé.
Kód:
from lxml import etree
def filter_xmltv(input_path, output_path, channel_ids, mode="include", replace_dict=None):
"""
Filtruje XMLTV soubor podle seznamu ID kanálů a volitelně nahrazuje ID.
:param input_path: cesta ke vstupnímu XMLTV souboru
:param output_path: cesta pro výstupní XMLTV soubor
:param channel_ids: seznam ID kanálů
:param mode: "include" nebo "exclude"
:param replace_dict: slovník pro nahrazení ID {původní_id: nové_id}, default None
"""
assert mode in ("include", "exclude"), "mode musí být 'include' nebo 'exclude'"
parser = etree.XMLParser(remove_blank_text=False)
tree = etree.parse(input_path, parser)
root = tree.getroot()
# Funkce rozhodující, zda kanál/progam zůstanou
def keep_channel(cid):
if mode == "include":
return cid in channel_ids
else: # exclude
return cid not in channel_ids
# Filtruj <channel> a nahraď ID, pokud je ve slovníku
kept_channels = set() # uložení zachovaných ID po nahrazení
for ch in root.findall("channel"):
original_id = ch.get("id")
if not keep_channel(original_id):
root.remove(ch)
continue
new_id = replace_dict.get(original_id, original_id) if replace_dict else original_id
ch.set("id", new_id)
kept_channels.add(new_id)
# Filtruj <programme> a nahraď channel ID podle slovníku
for prog in root.findall("programme"):
original_id = prog.get("channel")
if not keep_channel(original_id):
root.remove(prog)
continue
new_id = replace_dict.get(original_id, original_id) if replace_dict else original_id
# pouze pokud nový ID stále patří mezi zachované kanály
if new_id in kept_channels:
prog.set("channel", new_id)
else:
root.remove(prog)
# Ulož XMLTV se zachováním formátování
tree.write(
output_path,
encoding="utf-8",
xml_declaration=True,
pretty_print=True
)
