Tutoriel

Apple TV sans télécommande : la piloter depuis le Mac

Télécommande perdue, iPhone qui « cherche » à l’infini, télé qui ne répond pas. Bonjour, pyatv et 78 lignes de Python pour reprendre la main sur une Apple TV de 2012.

Plus de télécommande. L’iPhone affiche « Searching » sans fin. La télécommande de la télé n’y fait rien. Et pourtant, l’Apple TV est là, sur le réseau, qui accepte AirPlay sans broncher. Le problème n’était pas une panne. C’était une question de génération.

Le point de départ est banal. POP TV, l’offre télé de POST Luxembourg, refuse la recopie d’écran depuis le Mac : en AirPlay, on obtient le son et un écran noir. C’est la protection DRM/HDCP qui fait son travail, pas un réglage à décocher. En HDMI filaire, tout passe, parce que le câble négocie HDCP.

La parade propre : l’app POP TV Go sur l’iPhone, qui envoie le flux vidéo en AirPlay au lieu de recopier un écran. Ça fonctionne. Reste un détail : la télécommande de l’Apple TV a disparu depuis longtemps.

Le symptôme : « Searching » à l’infini

Le réflexe, c’est la télécommande intégrée au Centre de contrôle de l’iPhone. Menu « Choose a TV », puis « Searching ». Rien ne vient. Même Wi-Fi, pas de VPN, Apple TV redémarrée plusieurs fois : toujours rien.

Le détail qui intrigue : depuis ce même iPhone, AirPlay vers l’Apple TV marche parfaitement. L’appareil est donc visible. Alors pourquoi la télécommande ne le voit pas ?

Écouter le réseau avant de toucher à quoi que ce soit

Les appareils Apple s’annoncent sur le réseau local via Bonjour (mDNS). Chaque service a son nom : _airplay._tcp pour AirPlay, _companion-link._tcp pour la télécommande moderne. L’outil dns-sd, présent sur tous les Mac, permet de les écouter.

dns-sd -B _companion-link._tcp local.
# rien, a part le Mac lui-meme

dns-sd -L "Apple TV" _airplay._tcp local.
# Apple\032TV._airplay._tcp.local. can be reached at Apple-TV.local.:7000
#  model=AppleTV3,1 srcvers=220.68 osvers=8.4.4

Réponse : AppleTV3,1, système 8.4.4. Une Apple TV 3 de 2012, antérieure à tvOS. Elle n’annonce pas companion-link, le protocole qu’utilise la télécommande de l’iPhone. Elle ne l’annoncera jamais. Pas de mise à jour, pas de réglage, pas de jumelage possible. Et elle n’a pas non plus de HDMI-CEC, d’où l’indifférence totale à la télécommande de la télé.

Moyen de contrĂ´leProtocoleApple TV 3
Télécommande du Centre de contrôle (iPhone)companion-linkNon, réservé à tvOS
Télécommande de la téléHDMI-CECNon, absent du matériel
App POP TV Go (iPhone)AirPlayOui, mais vidéo seulement
Mac avec pyatvDMAP, port 3689Oui, navigation complète
Télécommande infrarougeIR, Learn RemoteOui, après apprentissage

pyatv : demander à l’Apple TV ce qu’elle accepte

pyatv est une bibliothèque Python open source qui parle tous les protocoles des Apple TV, anciens compris. Son utilitaire atvremote scanne un appareil et liste ce qu’il expose :

uvx --python 3.12 --from pyatv atvremote --scan-hosts <IP> scan

       Name: Apple TV
   Model/SW: Apple TV 3, ATV SW 8.4.4
Services:
 - Protocol: AirPlay, Port: 7000, Pairing: NotNeeded
 - Protocol: DMAP, Port: 3689, Credentials: <identifiant>, Pairing: Optional
 - Protocol: RAOP, Port: 7000, Pairing: NotNeeded

La ligne qui compte : DMAP, avec un identifiant déjà présent et un jumelage optionnel. DMAP est l’ancien protocole d’iTunes, celui qu’utilisait la défunte app « Remote ». L’identifiant vient visiblement du Partage à domicile activé sur l’Apple TV. Résultat : le Mac peut piloter l’Apple TV sans jumelage, donc sans avoir besoin d’une télécommande pour valider un code.

Premier piège en route : avec Python 3.14, atvremote plante sur RuntimeError: There is no current event loop. L’outil appelle asyncio.get_event_loop() hors d’une boucle, ce que Python 3.14 refuse désormais. uvx --python 3.12 règle la question sans rien installer globalement.

Une télécommande clavier en un fichier

Taper une commande par appui de touche, ce n’est pas une télécommande. J’ai donc fait écrire à Claude Code un petit script, atv.py, 78 lignes. Les dépendances sont déclarées dans l’en-tête du fichier (PEP 723), et uv run atv.py s’occupe de tout : bonne version de Python, pyatv, environnement isolé.

# /// script
# requires-python = ">=3.12,<3.13"
# dependencies = ["pyatv"]
# ///

Le principe : le terminal passe en mode « cbreak » pour lire chaque touche sans attendre Entrée, chaque touche est traduite en commande pyatv, la connexion DMAP reste ouverte. Flèches pour naviguer, Entrée pour valider, Échap pour Menu, h pour l’accueil.

KEYS = {
    "\x1b[A": ("up", "haut"),
    "\x1b[B": ("down", "bas"),
    "\r": ("select", "OK"),
    "\n": ("select", "OK"),  # le terminal convertit Entree en \n
    "\x1b": ("menu", "Menu"),
    "h": ("top_menu", "Accueil"),
}

conf.set_credentials(Protocol.DMAP, DMAP_CREDENTIALS)
atv = await pyatv.connect(conf, loop)
await atv.remote_control.select()

Le piège de la touche Entrée

Premier test : les flèches marchent, Entrée ne fait rien. Le script attendait \r, le code envoyé par la touche. Mais le mode cbreak ne coupe pas tout : l’option ICRNL du terminal reste active et convertit \r en \n avant que le programme ne le lise.

Correctif : accepter les deux. Une ligne. Le genre de bug qu’on ne trouve pas en relisant le code, seulement en appuyant sur la touche.

Learn Remote : se passer du Mac

Le Mac dépanne, mais personne ne veut ouvrir un terminal pour regarder la télé. L’Apple TV 3 a un menu oublié : Settings > General > Remotes > Learn Remote. Il apprend n’importe quelle télécommande infrarouge. Celle de la télé, par exemple.

  1. Naviguer jusqu’au menu Learn Remote avec atv.py.
  2. Pointer la télécommande de la télé vers l’Apple TV.
  3. Appuyer sur la touche choisie pour chaque fonction demandée : haut, bas, gauche, droite, OK, Menu.
  4. Nommer la télécommande et valider.

Une fois l’apprentissage terminé, la télécommande de la télé pilote aussi l’Apple TV. Le Mac retourne à ses occupations, le script reste en secours.

Identifier le modèle avant de chercher la panne. Trois redémarrages et une vérification Wi-Fi n’auraient jamais réglé un problème de génération. Une seule commande dns-sd l’a révélé en quelques secondes.

Ce que j’en retiens

  • « Ça marche en AirPlay » ne prouve rien. Chaque fonction Apple a son propre protocole, et un appareil peut en accepter un et ignorer l’autre.
  • Le rĂ©seau dit la vĂ©ritĂ©. Les annonces Bonjour donnent le modèle exact et le système, sans toucher Ă  l’appareil.
  • Le vieux matĂ©riel a de vieux protocoles, pas zĂ©ro protocole. DMAP est obsolète pour Apple, pas pour pyatv.
  • Le correctif final n’est pas le script. C’est un menu de 2012 qui rend la tĂ©lĂ©commande de la tĂ©lĂ© utile. Le code a servi de pont, pas de solution dĂ©finitive.

Essayer pyatv

Bibliothèque Python open source, compatible des Apple TV 2 et 3 jusqu’aux modèles tvOS récents. L’utilitaire atvremote suffit pour un premier scan.

pyatv sur GitHub