260916-IPTV-Publiques — la télévision publique européenne dans Jellyfin
1. Le besoin, et pourquoi pas les proxys ni un VPN
Regarder les télévisions publiques européennes (Rai en tête) depuis la maison. La page 322 raconte les deux impasses de la journée : les proxys seedbox.fr sont des IP de datacenter OVH que la Rai refuse, et un VPN grand public aurait coûté un abonnement pour un résultat incertain.
La troisième voie est la bonne : les diffuseurs publics publient eux-mêmes leurs flux HLS, et le projet communautaire iptv-org les recense par pays. Un flux HLS est une simple URL .m3u8. Il n'y a rien à contourner — seulement à trier ce qui répond réellement depuis le VPS, et à le servir proprement.
Décision de Julien : c'est Jellyfin qui joue la TV. Le VPS porte déjà Jellyfin ; une liste M3U branchée en tuner y ajoute une section « TV en direct » visible sur la télé, la tablette et les téléphones de toute la famille, avec logos, numéros de chaînes et groupes par pays.
2. Ce que fait generer_playlist.py
Toutes les 6 heures sur le VPS (cron 15 */6 * * *), stdlib seule :
- lit les listes iptv-org des pays concernés ;
- n'en garde que les chaînes de la liste blanche
config.json(regex sur le nom) ; ajoute les candidats supplémentaires connus hors liste (les flux CloudFront de Rai 1 et Rai 3, le flux officiel d'arte) ; écarte d'office les hôtes en adresse IP nue etstreamhostingcdn(rediffusions pirates) ; - teste chaque candidat : playlist HLS → variante la plus haute → téléchargement d'un vrai segment, avec mesure du débit. Un segment qui n'arrive pas, une playlist vide, un débit sous 3 Mbit/s = KO ;
- retient le candidat le plus rapide par chaîne, avec une préférence de stabilité pour celui de la fois précédente ;
- écrit
tv_publiques.m3u(tvg-id, logo,tvg-chno,group-title= pays) dans/home/debian/jellyfin/config/(=/config/dans le conteneur, lu par le tuner) et dans/home/debian/Documents/IPTV/(=D:\Syncthing\IPTV\, pour VLC depuis n'importe quelle machine) ; - si la liste a changé, demande à Jellyfin de relire son guide (
POST /ScheduledTasks/Running/{RefreshGuide}, clé API dédiéeiptv-publiquesdans/home/debian/.iptv_publiques.env, hors Syncthing) ; - termine par la ligne que lit le canari :
=== BILAN: 21/41 chaînes vivantes, 0 perdue — absentes : … ===.
« Perdue » ≠ « absente ». Une chaîne géobloquée depuis toujours est absente et ne fait pas parler le canari ; une chaîne vivante au passage précédent et morte maintenant est perdue, et là le canari chante (attendu: "BILAN: .*0 perdue", journal iptv_publiques.log, cadence 8 h). Hystérésis : au premier échec la chaîne est conservée dans la M3U avec son flux précédent (? au journal) ; elle n'est déclarée perdue qu'au second passage raté. Sans cela, les flux RTP « Not 24/7 » faisaient chanter le canari pour rien — constaté dès le second passage.
--simulation teste et affiche sans rien écrire, --verbeux détaille chaque candidat. explorer.py it de … liste et teste toutes les chaînes publiques d'un pays : c'est l'outil pour enrichir la liste blanche.
3. Relevé du 2026-09-16 depuis le VPS — 21 chaînes vivantes sur 41 demandées
| Pays | Vivantes | Absentes et pourquoi |
|---|---|---|
| Italie | Rai 1, Rai 2, Rai 3, Rai News 24, Rai Storia, Rai Scuola (CloudFront tiers, 80-95 Mbit/s), Rai Südtirol (flux officiel wzstreaming.rai.it) |
Rai 4, Gulp, Sport : flux officiels géobloqués |
| Espagne | TVE Internacional (le flux officiel RTVE pour l'Europe), Teledeporte, Clan | La 1, La 2, 24 Horas : HTTP 451 — RTVE bloque les IP d'hébergeur (mais répond depuis la maison) |
| Allemagne | Das Erste HD, Tagesschau 24, KiKA, hr-fernsehen, SR Fernsehen — tous flux officiels ARD, ouverts au monde | ZDF, 3sat : n'existent que via antik.sk, trop lent ; Phoenix, ZDFinfo/neo : géobloqués ; BR, NDR, WDR, ARD-alpha, MDR : géoblocage doux (voir §4) |
| Arte | arte (flux officiel Akamai, 140 Mbit/s) | — |
| Belgique | BX1 (Bruxelles) | La Une, Tipik : uniquement via des IP nues (écartées) ; VRT absente des listes |
| Portugal | RTP 1, RTP Notícias, RTP Açores (flux officiels) — intermittents, [Not 24/7] |
RTP 2 |
| Danemark | Folketinget (le parlement, Kaltura) | DR1, DR2 : géobloqués |
| Suisse | aucune | SRF/RTS/RSI : absentes des listes ou géobloquées |
| Autriche | aucune | ORF 1/2 : IP nues ; ORF III : géoblocage doux |
| Luxembourg | aucune | RTL Télé Lëtzebuerg : géoblocage doux |
| Pays-Bas | aucune | NPO : géobloqués |
Vérifié de bout en bout : tuner créé par l'API (POST /LiveTv/TunerHosts, type m3u, URL /config/tv_publiques.m3u, User-Agent navigateur), guide rafraîchi, 21 chaînes vues par Jellyfin, puis lecture de Rai 2 par le vrai enchaînement client (PlaybackInfo → LiveStreams/Open) : Jellyfin sonde le flux (hls, h264 1080p, aac) et répond SupportsDirectPlay: true — aucun transcodage, le VPS ne fait que relayer.
4. Pièges rencontrés
- Les listes iptv-org ne sont pas la Rai. Rai 1/2/3 y viennent de rediffuseurs tiers (un CloudFront anonyme, un opérateur slovaque). Ils peuvent disparaître : d'où le test à chaque passage et l'hystérésis, plutôt qu'une liste figée.
- Un flux « OK » n'est pas forcément jouable :
dash2/dash4.antik.skrépond 200 mais sert ses segments au rythme du direct (~1 Mbit/s), mesuré depuis le VPS et depuis la maison. En lecture ça coupe. D'où la mesure de débit et le seuildebit_min_mbit: 3. ZDF et 3sat n'ont pas d'autre source : absentes. - Géoblocage doux : ARD régionales, RTL.lu et ORF III resservent la playlist master à la place de la variante — HTTP 200, aucune erreur, et un lecteur naïf tourne en rond. Détecté par « la variante contient encore
#EXT-X-STREAM-INF». - Le dernier segment d'un direct n'est pas toujours servi (404 fugace sur Das Erste) : le test prend l'avant-avant-dernier et réessaie une fois.
- La géographie n'est pas la même depuis la maison et depuis le VPS : RTVE La 2 joue depuis la Livebox (IP Orange) et répond 451 depuis OVH. Jellyfin étant sur le VPS, c'est le VPS qui fait foi — la M3U de Syncthing est la même, VLC à la maison n'aura pas RTVE La 2 même si elle marcherait.
PlaybackInfoseul fait croire à un transcodage (ContainerNotSupported, VideoCodecNotSupported, ffmpeg à 170-290 % CPU) : Jellyfin ne sonde un tuner M3U qu'à l'ouverture (RequiresOpening: true→LiveStreams/Open). Après l'ouverture, direct play. Les ffmpeg de mes premiers essais ont tourné 2 min à 3 cœurs — tués à la main (pgrep -x ffmpeg).pkill -f 'motif'lancé parplink -m scripttue la session elle-même : le motif figure dans la ligne de commande du bash qui l'exécute. Passer parpgrep -xsur le nom du processus.streaming-live.rtp.ptrépond204 No Contenthors antenne ([Not 24/7]) : un204est traité comme vide, pas comme un succès.- arte : l'entrée « arte » de la liste France est une IP nue ; le flux officiel est
artesimulcast.akamaized.net/hls/live/2030993/artelive_de/index.m3u8(celui de la liste allemande, marqué à tort[Geo-blocked]— il répond depuis la France). Le cheminartelive_frn'existepas.pas sous cet identifiant : le flux français a le sien,2031003/artelive_fr(trouvé le lendemain dans la liste belge de Free-TV, voir §7).
5. Utilisation et entretien
- Regarder : Jellyfin → TV en direct (ou Live TV) → les chaînes par groupe de pays. Sur la télé, les numéros 1-7 sont l'Italie.
- VLC ailleurs : Média → Ouvrir un flux réseau →
D:\Syncthing\IPTV\tv_publiques.m3u(ou son équivalent sur chaque machine). - Ajouter une chaîne :
python3 explorer.py <pays>sur le VPS pour voir ce qui répond, puis une ligne danschainesdeconfig.json(nom, pays, motif, groupe, éventuelscandidats). Le passage suivant l'inclut si elle vit. - Voir l'état :
tail -3 /home/debian/logs/iptv_publiques.log, ou la page de veille du matin (« Tâches nocturnes »). - Retour arrière : supprimer le tuner dans Jellyfin (Tableau de bord → TV en direct), retirer la ligne de cron (sauvegarde
/home/debian/crontab.bak-260916), effacer les deuxtv_publiques.m3u.
Pas encore fait — le guide des programmes (EPG). Les tvg-id iptv-org (Rai1.it, DasErste.de…) sont ceux du projet iptv-org/epg, qui sait produire un XMLTV par chaîne ; Jellyfin l'accepte en fournisseur de guide XMLTV. Un grabber Node à faire tourner, à évaluer si le « qu'est-ce qui passe ? » manque à l'usage.
6. Fichiers
Jux-scripts/IPTV-Publiques/ : generer_playlist.py (production), config.json (liste blanche, sorties, seuils), explorer.py (exploration), README.md, doc_bookstack.md (cette page). Sur le VPS : journal /home/debian/logs/iptv_publiques.log, état /home/debian/logs/iptv_publiques.etat.json, clé API dans /home/debian/.iptv_publiques.env (chmod 600). Canari : entrée IPTV-Publiques dans Etat-Infra/config.json.
7. Le 2026-09-17 — seconde source (Free-TV) et guide des programmes
Julien a signalé la liste Free-TV/IPTV (via l'article de Korben sur les chaînes IPTV gratuites, qui ne cite que ces deux listes). Elle est complémentaire d'iptv-org : un seul fichier de 2 080 chaînes, le pays dans group-title, des flux officiels plus souvent, des marqueurs Ⓖ (géobloquée), Ⓢ (pas 24/7), Ⓨ (YouTube) accolés aux noms, et surtout un en-tête x-tvg-url qui désigne les guides XMLTV d'epgshare01 par pays.
Le script lit désormais les deux sources (sources dans config.json, mode pays pour iptv-org, mode groupe pour Free-TV), fusionne les candidats d'une même chaîne et garde le plus rapide. Résultat depuis le VPS : 55 chaînes vivantes sur 87 demandées (21 la veille). Ce que Free-TV a apporté :
| Pays | Nouvelles chaînes vivantes |
|---|---|
| Italie | Rai Italia Europa (le canal international de la Rai, fait pour l'étranger), Rai World Premium, La7 (flux officiel), Senato TV, Camera dei Deputati |
| Espagne | régionales officielles : Telemadrid, Canal Sur, Canal Extremadura, Televisión Canaria, ETB 1/2, TV3 Catalunya, 3/24, À Punt |
| Allemagne | NDR International, WDR Fernsehen |
| Arte | le flux français (artelive_fr, id Akamai 2031003 — celui de la liste belge) remplace le flux allemand |
| Portugal | RTP 2, RTP Mundo (international), RTP Madeira ; RTP 3/Notícias |
| Autriche | W24 (la chaîne de la ville de Vienne — ORF reste géobloqué) |
| Danemark | TV 2/Bornholm |
| Pays-Bas | 13 régionales publiques (NH Nieuws, RTV Rijnmond, Utrecht, Omroep Brabant, Gelderland, RTV Noord, Oost, Drenthe, Omrop Fryslân, Flevoland, West, Zeeland, L1) — NPO reste géobloqué |
Toujours rien pour la Suisse (SRF/RTS/RSI : IP nues ou géobloqués), le Luxembourg (RTL.lu en géoblocage doux) et les nationales RTVE, ZDF, ORF, DR, NPO, RTBF.
Guide des programmes — generer_guide.py (cron 5 3 * * *, 9 s) : lit en flux les guides epgshare01 des pays utiles (18 à 52 Mo de XML chacun, jusqu'à 751 chaînes), n'en garde que nos chaînes, réécrit leurs identifiants sur les nôtres et produit /config/guide.xml (5 Mo, ~7 500 programmes) pour le fournisseur XMLTV de Jellyfin (créé par POST /LiveTv/ListingProviders). 50 chaînes sur 55 ont un programme ; les 5 sans (Rai Italia, Rai World Premium, Rai Südtirol, Senato, Camera) n'existent dans aucun guide.
- Les identifiants ne concordent pas d'une liste à l'autre (
Rai1.it,Rai.1.HD..101.it,Das.Erste.devsDasErste.de,RTP.1.HD.ptvsRTP1.pt,HR.depour hr-fernsehen,SWR/SR.depour SR). D'où : la M3U porte désormais notre propretvg-idstable (rai1.tvpub), le guide est réécrit avec ces id, et l'appariement se fait sur les noms normalisés (sans ponctuation, sans « HD », sans suffixe pays) plus des aliasepgdansconfig.jsonpour les récalcitrants ("epg": ["SWR/SR"]). Le tvg-id d'origine reste danstvg-id-source - TVE Internacional n'est que dans le guide suisse (
TVE.Internacional.ch) :epg_pays: "ch"sur la chaîne, arte dans le guide français - Jellyfin affiche « en cours » et la grille sur la télé ; sa tâche Refresh Guide relit le fichier chaque nuit
Pièges du jour :
- L'outil Bash abîme
\bet\ndans un heredoc — un\bde regex est devenu un caractère backspace (0x08) dansexplorer.py: la regex^(Rai\b|…)ne trouvait plus une seule Rai, sans erreur. Éditer avec Edit/Write, jamais par heredoc (déjà noté en mémoire, re-mordu) - Free-TV marque le géoblocage d'un Ⓖ dans le nom : sans le retirer,
^Rai 1$ne matche pas « Rai 1 Ⓖ ». Et un flux marqué Ⓖ répond parfois depuis le VPS (arte, UniNettuno) : le marqueur trie les candidats, il ne les écarte pas - Segments RTP aux noms hors ASCII →
UnicodeEncodeError/InvalidURL: l'URL du segment est désormais encodée (urllib.parse.quote) antik.skrépond 200 mais sert au rythme du direct : ZDF et 3sat n'ont aucune autre source vivante, ils restent absents
8. État au 2026-09-17
55 chaînes dans Jellyfin, 50 avec guide, cron M3U toutes les 6 h et guide à 3h05 UTC, deux entrées canari (0 perdue, GUIDE: [1-9]). Ajouter une chaîne = python3 explorer.py <pays> puis une ligne dans chaines (motif sur le nom tel qu'il apparaît dans l'une des deux listes).