Introduction Dernière mise à jour 29/12/2021

XML TV Fr est un programme Open Source (licence Apache 2.0) crée par racacax en 2019. Il permet la récupération du guide des programmes de chaines francophones (principalement) au format XML TV à partir de multiples sources disponibles sur le net.

Exemple de fichier XML TV :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tv SYSTEM "xmltv.dtd">
<!-- Generated with XML TV Fr v2.0.0 -->
<tv source-info-url="https://github.com/racacax/XML-TV-Fr" source-info-name="XML TV Fr" generator-info-name="XML TV Fr" generator-info-url="https://github.com/racacax/XML-TV-Fr">
  <channel id="TF1.fr">
    <display-name>TF1</display-name>
    <icon src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS4u3EMdVyFA2uqIpbnwKBT1GRW9U-mA2jyCz28L2ieGx4vB9bKhpInhHCIqmk&amp;amp;s"/>
  </channel>
  <!-- Orange -->
  <programme start="20211227234500 +0100" stop="20211228004500 +0100" channel="TF1.fr">
    <title lang="fr">Joséphine, ange gardien</title>
    <sub-title lang="fr">Haute couture</sub-title>
    <desc lang="fr">Une créatrice de mode, passionnée par son métier, refuse de se faire soigner. Joséphine va tout mettre en oeuvre pour venir en aide à la jeune femme.</desc>
    <category lang="fr">Série</category>
    <category lang="fr">Série Passion</category>
    <icon src="https://proxymedia.woopic.com/340/p/169_EMI_23486537.jpg"/>
    <episode-num system="xmltv_ns">19.4.</episode-num>
    <rating system="CSA">
      <value>Tout public</value>
    </rating>
  </programme>
  <programme start="20211228004500 +0100" stop="20211228013000 +0100" channel="TF1.fr">
    <title lang="fr">New York Unité Spéciale</title>
    <sub-title lang="fr">Une mort prématurée</sub-title>
    <desc lang="fr">Deux kayakistes découvrent le corps sans vie d'un nourrisson dans un réfrigérateur : l'enquête s'oriente très rapidement vers deux adolescentes.</desc>
    <category lang="fr">Série</category>
    <category lang="fr">Série Suspense</category>
    <icon src="https://proxymedia.woopic.com/340/p/169_EMI_10397668.jpg"/>
    <episode-num system="xmltv_ns">3.13.</episode-num>
    <rating system="CSA">
      <value>-10</value>
      <icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Moins10.svg/200px-Moins10.svg.png"/>
    </rating>
  </programme>
</tv>

Services

Afin de récupérer le guide des programmes, XML TV Fr a plusieurs services d'intégrés. Chaque service est plus ou moins complet et comporte plus ou moins de chaines. La force de XML TV Fr contrairement est qu'en cas d'échec de récupération des programmes sur un service, le programme bascule automatiquement sur un autre service pour essayer de récupérer le guide.

Liste des services:
Nom Nombre de chaines Performance Description
6play 15 /
Amazonprime 11 /
Bouygues 390 Chaines présentes sur le site de Bouygues
Iciradiocanada 13 Chaines locales pour les différentes régions
Mycanal 726 Chaines présentes sur canalplus.com
Nouvelobs 99 /
Orange 264 Guide principal. Chaines présentes dans le bouquet Orange
Playtv 99 /
Plutotv 85 /
Proximus 426 Chaines de l'opérateur belge Proximus.
Sfr 379 Chaines présentes dans le bouquet SFR
Skweek 13 /
Tebeosud 2 Chaines locales du Finistère/Morbihan
Tele7jours 207 Chaines présentes sur le site de Télé 7 Jours
Teleboy 313 /
Telecablesat 268 Guide le plus complet fournissant le plus de détail. Chaines présentes sur le site Télécablesat. Récupération lente.
Teleloisirs 297 Guide avec autant de détails que Télécablesat. Chaines du site programme-tv.net.
Telerama 186 Guide le plus durable. Chaines présentes sur le site de Télérama
Tv5 7 Chaines TV du groupe TV5 Monde en Asie
Tv5global 8 /
Tvhebdo 330 Chaines canadiennes du site TV Hebdo. Récupération assez lente (nécessite proxy + une requête par programme et par chaine)
Vinipf 56 Guide TV pour la Polynésie française
Voo 188 Guide TV belge contenant une bonne partie de chaines françaises
  1. Récupération très rapide. Entre une et quelques requêtes par jour.
  2. Récupération rapide. Dépend en général du nombre de chaines.
  3. Récupération moyennement lente. Dépend en général du nombre de chaines et de programmes
  4. Récupération très lente. Dépend en général du nombre de chaines et de programmes.

Installation

L'installation se fait très simplement. Que ce soit sous Linux ou Windows, il suffit d'installer PHP (>=7.1.0) avec les extensions nécessaires.

Installation sous Linux

Lancez ces commandes :

sudo apt update
sudo apt install php7.4 php7.4-mbstring php7.4-curl php7.4-zip php7.4-xml

Ensuite, dans le dossier du projet XML TV Fr, lancez cette commande :

sudo apt install composer # pas besoin si composer déjà installé
composer install

Installation sous Windows

Téléchargez le ZIP de la version PHP de votre choix : https://windows.php.net/download#php-7.4 et activez les extensions mbstring, xml, curl et zip.

Téléchargez et installez ensuite Composer en reliant l'installation à la version de PHP téléchargée : https://getcomposer.org/download/

Ensuite, lancez cette commande dans le dossier du projet XML TV Fr :

composer install

Configuration

Le fichier de configuration est le fichier config.json (un fichier d'exemple config_example.json est fourni). Le fichier contenant les chaines est le fichier channels.json (par défaut).

Configuration globale (config.json)

Voici un exemple de fichier de configuration :

{
  "days" : 1,
  "cache_max_days": 8,
  "output_path": "./xmltv/",
  "time_limit": 0,
  "memory_limit": -1,
  "delete_raw_xml": false,
  "enable_gz": false,
  "enable_zip": true,
  "enable_xz": true,
  "enable_dummy" : false,
  "7zip_path": "C:\\Program Files\\7-Zip\\7z.exe",
  "custom_priority_orders" : {"Telerama": 0.2, "UltraNature": 0.5},
  "guides_to_generate" : [{"channels": "./channels.json", "filename": "xmltv.xml"}, {"channels": "./channels_tnt.json", "filename": "xmltv_tnt.xml"}]
}

days : Ce paramètre permet d'indiquer le nombre de jours de programmes que le script va essayer de récupérer.

cache_max_days : XML TV Fr garde en cache les données récupérées pour pouvoir les réutiliser lors d'un prochain lancement. Ce paramètre indique au bout de combien de jours une donnée est considérée comme obsolète.

output_path : Dans quel dossier le fichier XML TV sera exporté.

time_limit : Temps d'éxécution maximum du script en secondes (0 = infini).

memory_limit : Mémoire maximum du script (-1 = infini).

delete_raw_xml : Le XML TV brut est volumineux. Si vous souhaitez garder uniquement garder les versions compressées, mettez à true, sinon mettez false.

enable_gz : Active l'export en compression GZip (.gz) (true|false)

enable_zip : Active l'export en compression Zip (.gz) (true|false)

enable_xz : Active l'export en compression XZ (.xz) (true|false). Nécessite d'avoir rempli le paramètre 7zip_path.

enable_dummy : Afficher un faux guide des programmes pour les chaines HS (true|false)

7zip_path : Indique le chemin de l'executable de 7zip nécessaire à l'extraction au format XZ : https://www.7-zip.org/download.html

custom_priority_orders : Objet JSON indiquant des ordres de priorité personnalisés pour des services de façon global. Format clé/valeur avec comme clé le nom de la classe de service (exemple : TeleLoisirs) et comme valeur l'ordre de priorité donné (exemple : 0.89)

guides_to_generate : Tableau d'objets JSON indiquant les différents fichiers XML TV à générer. Chaque Object JSON contient la clé "channels" qui a comme valeur le chemin du fichier contenant les chaines et "filename" contenant le nom du fichier xml donné (pas le chemin).

Configuration des chaines (channels.json)

Voici un exemple de fichier de chaines (par défaut channels.json) :

{
	"France2.fr": {},
	"TF1.fr": {
		"priority": ["MyCanal", "Orange"]
	},
	"France3.fr": {
		"icon": "http://myicon",
		"name": "France 3",
		"alias": "France3Alias.fr"
	}

}

Ce fichier fonctionne avec le système clé/valeur avec comme clé l'ID de la chaine et comme valeur un objet JSON contenant des paramètres optionnels.

Le champ "priority" est un tableau de chaines de caractères indiquant un ordre de priorité personnalisé pour une chaine donnée.

Le champ "name" est une chaine de caractère indiquant le nom (pas l'ID) de la chaine. Il remplace les informations par défaut si indiqué.

Le champ "icon" est une chaine de caractère indiquant l'URL du logo de la chaine. Il remplace les informations par défaut si indiqué.

Le champ "alias" est une chaine de caractère indiquant l'ID de la chaine dans le fichier XMLTV. Il remplace les informations par défaut si indiqué.


Il est possible de générer le fichier channels.json à partir d'un outil dans le navigateur. Pour cela, placez-vous dans le dossier de travail de XML TV Fr et lancez cette commande :

php -S localhost:8080

L'outil sera disponible à l'adresse http://localhost:8080/tools/index.php. A noter que le port peut être modifié dans la commande et dans l'adresse.

Comme indiqué dans la section précédente, il est bien sûr possible d'avoir plusieurs fichiers de chaines pour générer plusieurs fichiers XML TV.

Utilisation

L'utilisation de XML TV Fr est plutôt simple et se fait très rapidement

Lancement

Pour lancer la récupération des programmes, placez-vous dans le dossier de travail de XML TV Fr, et lancez la commande :

php example/script_all.php

Logs

Les logs sont stockés dans le dossier logs au format JSON. Pour les consulter dans le navigateur, accédez à l'URL http://localhost:8080/tools/logs.php (voir section 3.2)

Ajouter des services

Il est possible d'améliorer XML TV Fr en apportant des contributions sur GitHub.

Service

Il est possible d'ajouter un service au sein de XML TV Fr afin d'enrichir le nombre de chaines ou tout simplement se donner une sécurité en cas d'échec d'autres sources.

Voici à quoi doit ressembler un fichier de service :

<?php
declare(strict_types=1);

namespace racacax\XmlTv\Component\Provider;


use racacax\XmlTv\Component\ProviderInterface;
use racacax\XmlTv\Component\ResourcePath;

class MyProvider extends AbstractProvider implements ProviderInterface
{

    public function __construct(?float $priority = null, array $extraParam = [])
    {
        parent::__construct(ResourcePath::getInstance()->getChannelPath('channels_myprovider.json'), $priority ?? 0.2);
    }

    public function constructEPG(string $channel, string $date)
    {
        parent::constructEPG($channel, $date);
        $error = false;
        foreach($results as $result) {
            $program = $this->channelObj->addProgram(strtotime($result['start']), strtotime($result['end']));
            $program->addTitle($result["title"], "en"); // argument langue optionnel, par defaut = "fr"
            $program->setIcon("myIconUrl");
            $program->addCategory(...)
            $program->addSubtitle(...)
            ...
        }
        if($error){
            return false;
        }
        return $this->channelObj;
    }
}

- Le constructeur doit avoir comme paramètres la priorité et un tableau de paramètres supplémentaires. Il appelle le constructeur parent qui lui possède deux autres paramètres : le chemin du fichiers de chaines du service (format JSON, structure totalement libre) et l'ordre de priorité.

- La méthode constructEPG à comme paramètre l'ID de la chaine et la date. Ce qui veut dire que cette méthode est appellée chaque jour pour chaque chaine. Elle doit forcément faire appel à la méthode de la classe parente et doit forcément terminer par un save() de l'objet channelObj (cette action sauvegardant les données sur le disque).

- L'object channelObj (du $this) est un object de type Channel représentant le guide des programmes pour une chaine pour un jour donné. Il contient des objets de type Program correspondant à un programme spécifique.

La classe Channel

Voici la signature de la classe Channel. Elle correspond à l'objet $this->channelObj de la méthode constructEPG() de chaque service

<?php
class Channel {
    public function __construct($id, $date, $provider);
   public function addProgram($start, $end);
   public function getPrograms();
   public function getId();
   public function toString();
   public function save($minimum=1);
   public function getFp();
   public function getProgramCount();
   public function popLastProgram();
}

addProgram : Création d'un program. $start : timestamp UNIX de début, $end : timestamp UNIX de fin.

popLastProgram : Suppression du dernier programme de la liste

save : Sauvegarde des programmes de la journée de la chaine sur le disque. $minimum : Entier indiquant le nombre de programmes minimums pour que la récupération soit indiquée comme OK (HS sinon).

La classe Program

Voici la signature de la classe Program :

<?php
class Program {
    /**
     * Program constructor.
     * @param $channel
     * @param $start
     * @param $end
     */
    public function __construct($channel, $start, $end);

    private function getPictoFromRatingSystem($rating, $system);

    /**
     * @return mixed
     */
    public function getTitles();
    /**
     * Ajout d'un titre
     * @param string $title
     * @param string $lang
     */
    public function addTitle($title, $lang="fr"): void;

    /**
     * @return mixed
     */
    public function getDescs();

    /**
     * Ajout d'un crédit (acteur, présentateur, ...)
     * @param $name
     * @param $type
     */
    public function addCredit($name, $type): void;

    /**
     * @return mixed
     */
    public function getCredits();

    /**
     * Ajout d'un synopsis
     * @param mixed $desc
     * @param string $lang
     */
    public function addDesc($desc, $lang="fr"): void;

    /**
     * @return mixed
     */
    public function getCategories();

    /**
     * @param mixed $category
     */
    public function addCategory($category, $lang="fr"): void;

    /**
     * @return mixed
     */
    public function getIcon();

    /**
     * Définition de l'icone du programme
     * @param mixed $icon
     */
    public function setIcon($icon): void;

    /**
     * @return mixed
     */
    public function getStart();

    /**
     * @return mixed
     */
    public function getEnd();


    /**
     * @return mixed
     */
    public function getEpisodeNum();

    /**
     * Définition de la saison et de l'épisode du programme
     * @param $season
     * @param $episode
     */
    public function setEpisodeNum($season, $episode);
    /**
     * @return mixed
     */
    public function getSubtitles();

    /**
     * Ajout d'un sous-titre au programme
     * @param mixed $subtitle
     * @param string $lang
     */
    public function addSubtitle($subtitle, $lang="fr");
    /**
     * @return mixed
     */
    public function getRating();

    /**
     * Définition du rating du programme (CSA -10 ans par exemple)
     * @param mixed $rating
     */
    public function setRating($rating, $system="CSA");

    public function toString();

    /**
     * Sauvegarde du programme
     */
    public function save();

    private function getFp();

    public static function listToMark($list, $tagName, $stringIfEmpty = null);

    /**
     * @return mixed
     */
    public function getYear();

    /**
     * Définition de l'année du programme
     * @param mixed $year
     */
    public function setYear($year);

}