webrtc-tauri
WebRTC dans Tauri — LGB-037
Nature de ce document
Ce billet est explicitement un rapport d’investigation, pas une suite
U/M/I/C/E complète (voir docs/projet/03-BACKLOG-LEGBA.md, section
LGB-037). Ce fichier distingue, pour chaque plateforme, trois états
possibles — jamais mélangés implicitement :
- testé-fonctionne : exécuté réellement depuis cette session, avec la sortie de commande à l’appui.
- testé-échoue (avec cause) : exécuté réellement, la cause technique exacte est identifiée et citée.
- non testé : pas d’environnement disponible pour le vérifier depuis cette session ; jamais présenté comme un succès ou un échec supposé.
Le scaffold vérifié est examples/tauri-shell
— exemple isolé, non publié (voir son README.md pour l’architecture et
les commandes).
Résumé par plateforme
| Plateforme | Build | Lancement | Connexion signalisation LiveKit | Caméra/micro réels |
|---|---|---|---|---|
| macOS (local, cette session) | testé-fonctionne | testé-fonctionne (processus stable, sans crash) | non testé visuellement (voir ci-dessous) | non testé |
Linux (conteneur ubuntu:24.04, cette session — mêmes étapes que le job CI) | testé-fonctionne (après correction d’un conflit de paquets apt, cause exacte ci-dessous) | testé-fonctionne (processus stable sous Xvfb, rendu logiciel faute de GPU) | non testé dans cette vérification locale ; le job CI réel (tauri-shell-linux) le tentera, pas encore exécuté sur GitHub Actions | non testé |
| Windows | non testé — aucune machine Windows disponible dans cet environnement | — | — | — |
macOS — testé localement, dans cette session
Environnement réel de cette session
Contrairement à l’hypothèse de départ du billet (environnement sandboxé
sans affichage), l’exécution a eu lieu sur la machine macOS réelle de
l’utilisateur (Wislys-MacBook-Pro, Apple M5, macOS 26.2, écran interne
réel). Mais cette session est un job d’arrière-plan non interactif :
pas de session graphique pilotable, pas d’accès caméra/micro accordé. Les
outils shell (cargo, pnpm, tauri) fonctionnent normalement ; piloter
une fenêtre réelle (capturer un écran, accorder une permission caméra) est
délibérément resté hors de portée de cette vérification — voir
« Ce qui n’a pas été tenté, et pourquoi » plus bas.
Build — testé-fonctionne
pnpm exec tauri build --no-bundle
A compilé les 415 crates Rust de la chaîne Tauri v2 (tauri 2.11.5,
wry 0.55.1, WKWebView natif macOS) et produit un binaire réel :
Built application at: examples/tauri-shell/src-tauri/target/release/tauri-shell
file confirme : Mach-O 64-bit executable arm64, 9,2 Mo.
Un premier essai a échoué avec un message d’erreur exact (scénario 12) :
error: proc macro panicked
--> src/main.rs:6:14
= help: message: failed to open icon .../icons/icon.png: No such file or directory (os error 2)
tauri::generate_context!() exige une icône même avec bundle.active: false (pas de paquet .app produit, mais l’icône de fenêtre reste
requise). Corrigé en ajoutant trois PNG minimaux (couleur unie, générés
par script, pas de dépendance de design) dans
examples/tauri-shell/src-tauri/icons/. Après correction, le build a
réussi sans autre erreur.
--no-bundle a été choisi délibérément : produire un .app/.dmg
distribuable est hors du périmètre de ce billet (qui vérifie la connexion
WebRTC, pas la distribution) et aurait ajouté des exigences de
signature/notarisation macOS non pertinentes ici. Documenté aussi dans
examples/tauri-shell/README.md.
Lancement — testé-fonctionne (au sens : le processus démarre et reste stable)
Le binaire a été lancé directement (./src-tauri/target/release/tauri-shell)
en arrière-plan shell, à deux reprises :
- Sans stack LiveKit démarrée : processus toujours actif après 3 s,
aucune sortie stderr, arrêt propre au
kill. - Stack LiveKit démarrée (voir plus bas), jeton fraîchement signé : même résultat — processus stable 6 s, aucune erreur, arrêt propre.
Aucun crash, aucune exception Rust, aucun message d’erreur dans les deux cas. C’est une preuve réelle que le binaire s’exécute sur macOS, pas une supposition.
Ce qui n’a pas été tenté, et pourquoi — non testé
- Confirmation visuelle que la fenêtre s’affiche et que la page HTML
s’y charge. Tauri sur macOS ne redirige pas la console WKWebView vers
stdout du processus par défaut (contrairement à Chrome/Playwright utilisé
par les tests E2E existants) : il n’y a pas de journal exploitable depuis
le shell. La vérification visuelle nécessiterait de piloter l’écran réel
de la machine de l’utilisateur (capture d’écran, clics) depuis une tâche
d’arrière-plan non surveillée — délibérément évité ici : le binaire n’est
pas un
.appenregistré (build--no-bundle), donc les outils d’automatisation d’applications macOS ne le reconnaissent même pas comme cible pilotable (list_appsavec le nom du binaire renvoie une liste vide) — confirmé en essayant. - Connexion réelle au serveur de signalisation LiveKit observée avec
succès. Un serveur LiveKit de développement était réellement joignable
pendant l’essai n°2 (
curl http://localhost:7880→OK, provenant du stack docker-compose d’un autre chantier en parallèle sur la même machine — mêmedocker-compose.yml, mêmes clésdevkey/secret, jamais dupliquées ni modifiées). Le jeton a été signé avec succès (signature JWT locale, aucun appel réseau nécessaire — voirscripts/mint-dev-token.mjs). Mais faute de journal WKWebView ou de capture d’écran, l’issue réelle deroom.connect()(succès, échec, timeout) n’a pas été observée. Absence de crash n’est pas la preuve d’une connexion réussie — ce rapport ne prétend pas ce qu’il n’a pas vu. - Capture caméra/micro réelle. Nécessite une permission macOS accordée interactivement (boîte de dialogue système) : accorder cette permission au nom de l’utilisateur, sans lui, depuis une tâche d’arrière-plan non surveillée, active la caméra/le micro réels de sa machine — jugé inapproprié à faire seul. Documenté comme non testé, pas comme un échec.
Pourquoi ce n’est pas maquillé en succès : le scénario 13 du billet exige de ne jamais glisser implicitement d’un état à l’autre. « Le processus ne crashe pas » et « la salle a été rejointe avec succès » sont deux affirmations différentes ; seule la première est prouvée ici.
Linux (CI, ubuntu-latest) — job isolé + vérification locale par conteneur
Le job CI
.github/workflows/ci.yml gagne un nouveau job, tauri-shell-linux,
volontairement isolé :
- Aucun
needs:— ne dépend d’aucun autre job, et aucun autre job ne dépend de lui. continue-on-error: trueau niveau du job entier : un échec ici ne fait jamais échouer le workflow global, donc ne bloque jamais la fusion des autres billets (scénario 14). Une régression y reste visible (une annotation::warning::est émise si le lancement échoue autrement que par timeout), sans jamais devenir bloquante.- N’installe/ne construit que
examples/tauri-shell— aucune des huit portes de qualité existantes n’est modifiée.
Ce job n’a pas encore tourné sur GitHub Actions au moment de la
rédaction (il tourne à la prochaine ouverture de PR). Pour ne pas se
contenter d’un fichier YAML non vérifié, les mêmes étapes ont été
reproduites dans un vrai conteneur ubuntu:24.04 (image de base de
ubuntu-latest au moment de ce billet) depuis cette session — résultats
ci-dessous, avec la sortie de commande réelle à l’appui.
Vérification par conteneur — résultats réels
Exécuté depuis cette session : docker run --rm -v <dépôt>:/src:ro ubuntu:24.04 bash … — le dépôt est copié dans le conteneur avant pnpm install (jamais écrit dans le node_modules macOS monté). Mêmes versions
que le job CI : Node 22 (nodesource, v22.23.2 installé), pnpm@12.4.2
(corepack), Rust stable (rustc 1.98.1, cargo 1.98.1, via rustup).
Dépendances système — testé-échoue puis corrigé (cause exacte).
Premier essai avec libappindicator3-dev et
libayatana-appindicator3-dev dans la même commande apt-get install :
The following packages have unmet dependencies:
libappindicator3-dev : Depends: libappindicator3-1 (= 12.10.1+20.10.20200706.1-0ubuntu5)
libayatana-appindicator3-dev : Conflicts: libappindicator3-dev
E: Unable to correct problems, you have held broken packages.
Les deux paquets sont mutuellement exclusifs sur Ubuntu 24.04 (noble) —
libappindicator3-dev vient d’une doc Tauri plus ancienne. Corrigé en ne
gardant que libayatana-appindicator3-dev (le job CI et
examples/tauri-shell n’installent plus que celui-ci). Après correction,
apt-get install réussit sans erreur.
Build — testé-fonctionne. pnpm exec tauri build --no-bundle a
compilé les mêmes ~415 crates que sur macOS, cette fois avec le backend
WebKitGTK (webkit2gtk, gdk, soup3, cairo-rs, tao…) au lieu de
WKWebView :
Finished `release` profile [optimized] target(s) in 1m 26s
Built application at: /work/examples/tauri-shell/src-tauri/target/release/tauri-shell
Aucune erreur de compilation Rust, aucun contournement.
Lancement — testé-fonctionne (processus stable), avec une limite
matérielle réelle documentée. Lancé sous xvfb-run --auto-servernum -- timeout 8 ./tauri-shell (même motif Xvfb que la Porte 7 E2E) :
libEGL warning: DRI3 error: Could not get DRI3 device
libEGL warning: Ensure your X server supports DRI3 to get accelerated rendering
launch exit code (124 = timeout, i.e. it was still running): 124
Code de sortie 124 = timeout a dû tuer le processus après 8 s parce
qu’il tournait encore — même signal de stabilité que sur macOS, pas un
crash. L’avertissement DRI3/EGL est réel et attendu : Xvfb ne fournit
aucun GPU, WebKitGTK bascule sur un rendu logiciel. Non bloquant ici
(le processus continue de tourner), mais documenté comme limite connue
pour un futur test visuel (un rendu logiciel peut suffire pour une
capture d’écran automatisée, mais serait plus lent qu’un rendu accéléré).
Ce que cette vérification locale ne couvre pas, par rapport au job CI
réel. Ce conteneur local n’a pas démarré le stack docker-compose.yml
(Docker-dans-Docker non configuré pour cette vérification rapide) : la
tentative de connexion réelle au serveur de signalisation LiveKit n’a
donc pas été exercée ici, contrairement au job tauri-shell-linux
dans .github/workflows/ci.yml, qui lance docker compose up -d avant
de construire et lancer le scaffold. Le job CI lui-même n’a pas encore
tourné sur GitHub Actions au moment de la rédaction — il tournera à la
prochaine exécution du workflow sur cette PR.
Capture caméra/micro — non testé. Même limite que macOS : aucune
tentative de getUserMedia/getDisplayMedia observée. De plus, le motif
Chrome existant (--use-fake-device-for-media-stream,
--use-fake-ui-for-media-permissions) est spécifique à Chromium — il ne
s’applique pas à WebKitGTK, le moteur utilisé par la WebView Tauri sur
Linux. WebKitGTK a son propre mécanisme de périphérique factice (GStreamer
videotestsrc/audiotestsrc), non mis en place ni testé ici — documenté
comme un écart réel entre l’infrastructure E2E existante (Chromium) et ce
scaffold (WebKitGTK), pas une simple hypothèse.
Matrice de compatibilité Linux — causes exactes
| Aspect | État | Cause exacte |
|---|---|---|
| Dépendances système (apt) | testé-échoue → corrigé | libappindicator3-dev et libayatana-appindicator3-dev sont en conflit direct sur Ubuntu 24.04 (noble) ; seul libayatana-appindicator3-dev s’installe |
Compilation Rust (cargo/tauri build --no-bundle) | testé-fonctionne | Aucune, compile proprement avec WebKitGTK |
| Lancement du binaire sous Xvfb | testé-fonctionne (stable) | — |
| Rendu accéléré (GPU) | testé-échoue (non bloquant) | Xvfb n’expose aucun périphérique DRI3 ; WebKitGTK bascule sur un rendu logiciel |
| Connexion réelle au serveur de signalisation LiveKit | non testé (vérification locale) / prévu en CI | Non exercé dans cette vérification locale (pas de Docker-dans-Docker) ; le job CI réel démarre docker-compose.yml avant de lancer le scaffold, mais n’a pas encore tourné sur GitHub Actions |
| Capture caméra/micro factice | non testé | Le motif Chrome --use-fake-device-for-media-stream ne s’applique pas à WebKitGTK ; équivalent GStreamer non mis en place |
Windows — non testé
Aucune machine Windows n’est disponible dans cet environnement d’exécution. Ni build, ni lancement, ni aucune autre vérification n’ont été tentés. Documenté explicitement comme non testé — ni comme un succès supposé, ni comme un échec (scénario 5).
Ce qui a été délibérément laissé de côté
- Empaquetage distribuable (
.app/.dmgsur macOS,.deb/.AppImage/.rpmsur Linux) : hors périmètre — ce billet vérifie la connexion WebRTC dans une WebView Tauri, pas un pipeline de distribution.bundle.active: falsepartout. - Commandes IPC Tauri : aucune définie. La WebView parle directement à
LiveKit en WebSocket/WebRTC ;
src-taurin’ouvre qu’une fenêtre. - Intégration aux portes de qualité existantes :
examples/tauri-shellne définit aucun scriptbuild/lint/typecheck/test—turbol’ignore silencieusement dans tous les jobs existants. Seul le nouveau job isolé le touche.