Aller au contenu
D
Journal
Flutter · 18 juin 2026 · 9 min de lecture

Flutter et WebRTC : atteindre une latence mobile inférieure à 300 ms

Ce qu'il a fallu vérifier — au-delà de la config WebRTC — pour obtenir une diffusion vidéo pair-à-pair fluide sur téléphone.

WebRTC n’est pas « juste » un flux vidéo. C’est un enchaînement de couches où chacune peut coûter cent millisecondes si on ne fait pas attention. Sur VisiOne, l’objectif était de rester sous 300 ms de bout en bout dans les conditions de test documentées. Voici ce qui a compté, dans l’ordre.

Le signaling ne doit pas être un blocage

Notre signaling utilisait MQTT plutôt qu’un serveur WebSocket dédié. Bon choix — la caméra parlait déjà MQTT. Mauvais réflexe initial : envoyer les SDP en base64 dans le payload MQTT. Le broker s’en foutait, mais le round-trip d’aller-retour avec confirmation coûtait 40 à 60 ms. On a passé le SDP en payload binaire QoS 1 sans confirmation applicative — et gagné 30 ms mesurables.

STUN plutôt que TURN quand possible

TURN garantit la connectivité, mais impose un relais. Sur les réseaux du client, le NAT était traversable dans 80 % des cas. On a mis un serveur STUN en premier, TURN en fallback. Sur les 80 % de cas STUN, la latence bout-à-bout tombait de ~80 ms.

Codec : H.264 hardware ou rien

Sur Android, flutter_webrtc peut utiliser VP8 par défaut. Sur les téléphones milieu de gamme du marché camerounais, décoder VP8 en soft consomme 20 % de CPU en plus et ajoute 40-60 ms de latence perceptible. On a forcé H.264 avec fallback VP8 uniquement si le décodeur hardware refusait — vérifié via RTCRtpSender.getCapabilities.

Le rendu Flutter n’est pas gratuit

RTCVideoRenderer fait un pont natif → Flutter texture. Sur mobile, ce pont coûte 1 frame de latence si on n’active pas le rendu SurfaceView natif. On l’a activé partout où c’était possible, en acceptant la contrainte : la texture ne peut plus être composée avec d’autres widgets Flutter au pixel près. En pratique, on affichait le flux en plein écran ou dans un container fixe — c’était acceptable.

Ce qui n’a pas marché

  • essayer de baisser la résolution en dessous de 480p : la charge CPU montait paradoxalement à cause de l’upscaling écran ;
  • désactiver l’écho cancellation « pour gagner du temps » : sans effet mesurable ;
  • utiliser un simulateur Chrome pour tester la latence bout-à-bout — les chiffres du simulateur étaient systématiquement 60 ms trop optimistes.

La méthode qui a marché

Instrumentation dès le premier prototype. On envoyait un timestamp dans chaque frame vidéo (via metadata SEI) et on le lisait à l’affichage. Une timeline avec 6 checkpoints : capture, encode, signaling out, réception, decode, render. Chaque optimisation était mesurée. Sans cette timeline, on aurait « senti » que c’était plus fluide sans savoir pourquoi.

Le chiffre final — < 300 ms — n’est pas une performance de démo. C’est le résultat d’un budget bien tenu à chaque étage.

DT

Delano Toungsi

Développeur mobile senior Flutter · Yaoundé, Cameroun

Me proposer un entretien →

Un besoin mobile qui vous ressemble ?