Mon setup gaming

  1. Introduction
  2. Gestion de l'alimentation
  3. Affichage
  4. Son
  5. Bonus
  6. Conclusion
    1. Avantages
    2. Inconvénients
    3. Pistes suivies

Introduction

Ma machine de jeu est un Ryzen 9 5900X avec une RTX3080 sous NixOS.

Je joue via la fonctionnalité "Remote Play" de Steam depuis mon Mac mini M1.

Jusqu'à présent, c'était assez inconfortable et trop rigide pour mes envies futures :

  • le PC est dans la même pièce que mon Mac mini M1 et il peut devenir bruyant pendant le jeu
  • le son ne fonctionnait pas en streaming, donc le PC était directement branché à mes enceintes
  • la vidéo ne fonctionnait à la bonne résolution que si mon PC était branché directement à mon écran

Je rajouterai que les solutions de type switch/KVM USB ne m'ont jamais satisfait parce qu'elles déconnent toujours, à un moment où à un autre, manifestement à cause d'un défaut électrique récurrent. À croire que ces ingénieurs ne savent pas relier des masses...

J'ai entrepris, et réussi, à résoudre tous mes problèmes pour obtenir une solution de streaming local pour Steam 100% headless qui soit pratique et confortable à l'usage.

Cela a nécessité pas mal de recherche, essais et échecs, alors j'ai pensé que vous faire part de mon setup serait intéressant.

On va partir du principe que votre PC de jeu est déjà fonctionnel (sur lequel vous pouvez déjà jouer dans des conditions normales).

Quelques précisions avant de commencer :

  • l'image n'est pas aussi nette en streaming qu'en jouant directement sur le PC de jeu - Steam compresse peut-être un peu trop agressivement mais au moins, ça fonctionne (vous verrez que jouer via VNC à l'air pas mal comme ça mais à l'usage, c'est moins agréable que le streaming via Steam)
  • il y a une très légère latence, mais si vous cherchez à faire du streaming, vous devez déjà être au courant (la latence via VNC est beaucoup plus problématique)
  • les boutons latéraux de la souris ne fonctionnent pas

Gestion de l'alimentation

Je commence par le plus simple : on va passer par du Wake on LAN assez classique pour le démarrage de la machine à la demande, et on laissera les options de mise en veille prolongée prendre le relais pour l'extinction de la machine.

Donc, sur le PC de jeu, on va dans le BIOS, et on active la fonctionnalité qui va bien. Malheureusement, vu la quantité de machines différentes, je n'ai pas vraiment le moyen d'être précis. Dans mon cas, c'est l'option Wake by PCI-E event, autrement dit, réveil par PCI-E, donc par le chipset réseau.

À noter : ça ne fonctionne que si la machine est câblée. Inutile d'essayer en Wifi...

Il faut aussi le client wol sur le Mac. J'ai appris que macOS intègre nativement Ruby, donc pas la peine de s'emmerder avec brew, il suffit de faire :

gem install wol

Testé sous macOS Ventura, mais si ça ne fonctionne pas pour vous, brew install wol fera l'affaire (à condition d'avoir installé homebrew, "évidemment").

Il faut noter l'adresse MAC du chipset réseau du PC de jeu. Suite à quoi, on pourra faire :

wol <adresse MAC>

depuis le mac pour réveiller le PC de jeu. Ça, c'est du classique, pas de quoi effrayer un sysadmin.

Affichage

Là on monte d'un cran : il faut qu'on puisse se passer d'un écran branché sur la machine. Quand on fait tout en console (par exemple, sur un serveur), c'est facile, mais là on a besoin d'un environnement de bureau.

Pour cette étape, on va avoir besoin de l'écran sur lequel on va vouloir jouer. Dans mon cas, c'est mon GT34, physiquement branché sur le Mac mini.

Il faut donc brancher temporairement l'écran sur le PC de jeu, puis démarrer la machine. Une fois sur le bureau, on lance le panneau de configuration NVidia, et on récupère l'EDID de l'écran :

Cliquez sur le bouton Acquire EDID

On l'enregistrera au format texte dans le dossier de son choix.

Sous NixOS, on va ensuite spécifier au serveur X qu'on veut utiliser ce fichier sur un écran "virtuel" (ou en tout cas déclaré comme présent et connecté) :

services.xserver.deviceSection = ''
  Option "ConnectedMonitor" "DFP-1"
  Option "CustomEDID" "DFP-1:/chemin/vers/edid.txt"
'';

N'oubliez pas de modifier la directive CustomEDID pour pointer vers le fichier enregistré à l'étape précédente.

Dans mon cas, j'avais l'écran branché sur un port DisplayPort, donc remplacez DFP-1 par votre sortie physique sur laquelle vous avez temporairement branché l'écran si elle diffère (par exemple HDMI-1). Je ne suis pas sûr que ce soit requis mais autant faire ça proprement.

Profitons de la modification de notre configuration de NixOS pour ajouter le paquet x11vnc, par exemple via :

{ pkgs, ... }:

{
  environment = {
    systemPackages = with pkgs; [
      # [...]
      x11vnc
    ];
  };
}

On peut ensuite appliquer les modifications et redémarrer la machine :

nixos-rebuild switch
reboot

À partir de là, on devrait pouvoir tout débrancher du PC de jeu (clavier, souris, écran, enceintes). On va donc se connecter en SSH au PC de jeu depuis le Mac pour le reste du processus. Sauf mention contraire, on exécutera les commandes suivantes en tant qu'utilisateur normal (celui qui peut jouer).

Une fois connecté en SSH, on lance le serveur VNC :

export DISPLAY=:0
x11vnc -usepw

Au premier démarrage, le serveur va vous demander de créer un fichier de mot de passe. Au cours des démarrages suivants (en utilisant le même paramètre -usepw), ce fichier sera lu et x11vnc ne vous demandera plus rien.

On peut alors lancer un client VNC depuis le Mac (j'ai choisi TigerVNC), ce qui nous permettra de vérifier que la résolution est la bonne. Si la résolution n'est pas bonne, il va falloir investiguer...

Son

Maintenant qu'on accède au bureau via VNC, on va pouvoir configurer le son.

Au cours de mes premiers essais, je n'avais aucun son sur le Mac via le streaming de Steam. Je sortai le son directement sur les enceintes depuis le PC de jeu. Ça fonctionne, mais ce que je veux, c'est pouvoir m'abstenir de brancher quoique ce soit au PC (à part le câble réseau sinon pas de WoL) : à terme, je veux que celui-ci soit placé dans mon placard informatique et que je l'oublie.

Tout en gardant le client VNC ouvert, on lance Steam sur la machine cliente (donc, dans mon cas, le Mac mini), et on lance une session de jeu en streaming, peu importe le jeu.

Quand le jeu est lancé, on retourne dans le client VNC, et on affiche les paramètres de son. L'astuce pour avoir le son en streaming est simple mais le comportement par défaut de pulseaudio est de couper le son du périphérique d'enregistrement de Steam qui permet le streaming. Il suffit de l'activer, encore fallait-il le savoir !

Périphérique de capture utilisé par le streaming depuis Steam

Il faut donc aller dans l'onglet "Enregistrement", il faut activer l'option "Tous les flux" du menu déroulant "Afficher" en bas de la fenêtre, s'assurer que le "Monitor of..." corresponde bien à une sortie son qui est valable (sur laquelle on aurait du son si on branchait des enceintes dessus) et il faut s'assurer que le bouton 🔇 ne soit pas actif... sachant que tout cela n'est disponible QUE lorsqu'un jeu est en cours de streaming.

Quand ça c'est fait, on est bons ! Tous ces réglages survivront - heureusement - à l'arrêt du streaming et au reboot de la machine.

Bonus

En bonus, j'ai pu découvrir quelques fonctionnalités bien sympathiques de macOS, et en particulier, l'application Automator. Celle-ci permet notamment d'ajouter des "Actions rapides" aux applications.

Ici, on va créer une action rapide pour Steam, qui va permettre de démarrer le PC de jeu via WoL en un clic de souris.

Après avoir lancé Automator, on créé un nouveau document, puis une nouvelle action rapide.

Configuration de notre action rapide

On enregistre ensuite le document, qu'on intitulera par exemple "WoL PC de jeu".

Comme par magie, dans le menu principal de Steam on obtient le résultat suivant (sans même redémarrer Steam...) :

Tadam !

Conclusion

J'ai été très surpris de la difficulté de trouver les informations relatives à l'affichage et au son. J'ignore si c'est parce que la majorité des joueurs est toujours sous Windows et que Windows est plus permissif que pulseaudio en ce qui concerne le streaming audio, ou à cause de la diversité des environnements sous GNU-Linux, ou encore parce que je veux faire un truc que personne n'a fait.

Ma solution n'est pas encore parfaite, mais elle correspond à mes envies du moment. Je me doute que mon cas d'usage est très spécifique, néanmoins il me plait de croire que vous aurez trouvé cet article intéressant !

Avantages

  • Tout fonctionne
  • En vérité, ce n'est pas si compliqué que ça, une fois qu'on a trouvé quoi faire...

Inconvénients

  • La spécification d'un EDID dans la configuration de xserver impose des caractéristiques particulières : pour le moment, je ne peux pas jouer sur un écran 4K (sur ma TV par exemple) dans des conditions optimales, parce que l'EDID de mon écran est celui d'un écran 3K
  • Il faut allumer le PC de jeu via une action spécifique : une amélioration possible serait que Steam procède directement à l'allumage de la machine quand on veut démarrer une session de jeu, mais il faut reconnaître que Steam affiche la liste des jeux disponibles en streaming : il faut donc que la machine distante soit déjà allumée et Steam lancé

Pistes suivies

J'avais trouvé une solution qui fonctionne bien si on veut un environnement dockerisé : https://github.com/Steam-Headless/docker-steam-headless

La solution proposée est bien foutue, pratiquement clés en main, avec le client noVNC bien pratique à lancer dans un navigateur. Par contre, la mise en veille du PC physique nécessite des ajustements.

En ce qui concerne la question de la résolution de l'écran virtuel, avant d'exploiter la technique de l'EDID, j'ai testé l'usage de la commande suivante, conjointement à Xvfb :

export DISPLAY=:0
xrandr --fb 3440x1440

Cette solution me semblait parfaite parce que très légère et très simple. Ça fonctionne parfaitement bien dans presque tous les cas de figure (même le contrôle via VNC fonctionne), sauf certains jeux. En l'occurrence, Dwarf Fortress crash au démarrage. En écrivant cet article, je me rends compte que c'est probablement parce que je lançais uniquement Steam via xvfb-run, et que le problème ne se poserait pas si je lançais carrément une session XFCE4. Je testerai à l'occasion.

Enfin, j'aurai pu suivre une autre piste en ce qui concerne l'écran virtuel, c'est le dongle HDMI. Celui-ci simule un écran en envoyant au PC un EDID dont le serveur X déduit les caractéristiques. Sauf que ce n'est pas assez flexible pour moi. Un dongle "4K" sera incapable de m'envoyer du 3440x1440, et surtout, ces dongles sont limités aux 60Hz quand moi je veux du 120Hz au minimum. Et puis, pourquoi acheter si je peux solutionner le problème avec une ligne de configuration...