2026-10-25 14:02:03 +00:00
|
|
|
|
# Appels audio-vidéo PostIt — architecture cible
|
|
|
|
|
|
|
|
|
|
|
|
## Statut et périmètre
|
|
|
|
|
|
|
2026-10-26 03:05:23 +00:00
|
|
|
|
Ce document décrit l'architecture cible et l'implémentation commencée.
|
|
|
|
|
|
La préférence de confidentialité est persistée et éditable dans le profil.
|
|
|
|
|
|
La signalisation est intégrée au chat, désactivée par défaut. Un premier
|
2026-11-02 15:33:03 +00:00
|
|
|
|
transport natif **Android et Desktop Linux en IPv4/IPv6 directe (LAN/VPN ou IP publique)** est raccordé :
|
2026-10-26 04:15:19 +00:00
|
|
|
|
captures Podcast existantes et SRTP direct, sans libwebrtc ni nouvelle
|
|
|
|
|
|
couche JNI WebRTC. Il ne réalise pas encore la cible Internet, TURN ou groupe.
|
2026-10-25 16:49:51 +00:00
|
|
|
|
Il complète la [topologie de PostIt](postit.md) et les
|
2026-10-25 14:02:03 +00:00
|
|
|
|
[mécanismes de notification existants](notifications.md).
|
|
|
|
|
|
La cible couvre :
|
|
|
|
|
|
|
|
|
|
|
|
- les appels audio-vidéo bidirectionnels entre deux utilisateurs ;
|
|
|
|
|
|
- un réglage utilisateur booléen persistant permettant de masquer son adresse
|
|
|
|
|
|
IP aux autres participants en imposant TURN ;
|
|
|
|
|
|
- les appels de groupe ;
|
|
|
|
|
|
- les clients Browser, Android et Desktop.
|
|
|
|
|
|
|
2026-11-02 15:33:03 +00:00
|
|
|
|
## Première implémentation Android et Desktop Linux : SRTP direct IPv4/IPv6
|
2026-11-02 15:25:54 +00:00
|
|
|
|
|
|
|
|
|
|
Les adresses IPv4 publiques directement assignees a une interface locale active
|
|
|
|
|
|
sont egalement disponibles, avec la meme validation unicast cote client,
|
2026-11-02 15:33:03 +00:00
|
|
|
|
media et signalisation serveur. Les IPv6 globales (2000::/3), privees ULA
|
|
|
|
|
|
(fc00::/7) et de boucle locale (::1) sont aussi acceptees. Les sockets UDP
|
|
|
|
|
|
utilisent la famille de l'adresse locale et les URL de reception encadrent
|
|
|
|
|
|
les IPv6 de crochets. Les adresses non specifiees, link-local, multicast,
|
|
|
|
|
|
reservees IPv4 (240/4), IPv4-mapped IPv6 et les formes non canoniques ou
|
|
|
|
|
|
avec identifiant de zone sont refusees. Une zone link-local du premier
|
|
|
|
|
|
pair n'est pas reutilisable telle quelle par le second.
|
2026-11-02 15:25:54 +00:00
|
|
|
|
Il faut autoriser en entree les deux ports UDP consecutifs choisis et assurer
|
|
|
|
|
|
la joignabilite entre les pairs. Ce support n'ajoute ni ICE/TURN ni traversee
|
|
|
|
|
|
NAT automatique : l'adresse publique d'un routeur ne remplace pas une adresse
|
|
|
|
|
|
assignee a la machine. Le consentement explicite au partage d'IP et le refus
|
|
|
|
|
|
du mode direct pour les comptes masquant leur IP restent inchanges.
|
2026-11-02 15:33:03 +00:00
|
|
|
|
Les pairs doivent disposer de routes vers leurs adresses respectives ;
|
|
|
|
|
|
aucune traduction automatique IPv4/IPv6 n'est fournie. Les tests natifs
|
|
|
|
|
|
Linux verifient sur ::1 la reception audio/video bidirectionnelle chiffree,
|
|
|
|
|
|
le rejet d'une mauvaise cle et le cycle de vie des ports RTP/RTCP.
|
|
|
|
|
|
Un appel IPv6 entre deux machines et le transport IPv6 Android restent
|
|
|
|
|
|
a valider en conditions reelles.
|
2026-10-26 03:05:23 +00:00
|
|
|
|
|
|
|
|
|
|
Cette tranche réutilise la capture caméra/microphone et les encodeurs des
|
|
|
|
|
|
Podcasts, mais **pas leur segmentation HLS ni leurs envois de fichiers** :
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
2026-10-26 04:15:19 +00:00
|
|
|
|
PostIt A ----------- ChatHub authentifié / HTTPS ----------- PostIt B
|
2026-10-26 03:05:23 +00:00
|
|
|
|
invitation, consentement,
|
|
|
|
|
|
adresses et clés, fin
|
|
|
|
|
|
|
2026-10-26 04:15:19 +00:00
|
|
|
|
PostIt A ========== H.264/AAC, MPEG-TS sur SRTP/UDP ========== PostIt B
|
2026-10-26 03:05:23 +00:00
|
|
|
|
dans les deux sens
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
L'implémentation est dans
|
2026-10-26 04:15:19 +00:00
|
|
|
|
[LibVlcLanCallMedia](../../src/PostIt/PostIt/Services/LibVlcLanCallMedia.cs),
|
2026-10-26 03:05:23 +00:00
|
|
|
|
[LinuxLanCallVideo](../../src/PostIt/PostIt/Services/LinuxLanCallVideo.cs) et
|
|
|
|
|
|
[LanCallViewModel](../../src/PostIt/PostIt/ViewModels/Chat/LanCallViewModel.cs).
|
2026-10-26 04:15:19 +00:00
|
|
|
|
Android utilise
|
|
|
|
|
|
[AndroidLanCallMedia](../../src/PostIt/PostIt.Android/Services/AndroidLanCallMedia.cs)
|
|
|
|
|
|
avec les mêmes contrats et clés SRTP.
|
2026-10-26 03:05:23 +00:00
|
|
|
|
Les contrôles et les deux surfaces vidéo sont intégrés à la page du chat.
|
|
|
|
|
|
Il n'y a pas de service de salles supplémentaire, d'enregistrement,
|
|
|
|
|
|
de fichier média temporaire ou de moteur WebRTC Android ajouté.
|
|
|
|
|
|
|
|
|
|
|
|
### Activer et essayer
|
|
|
|
|
|
|
|
|
|
|
|
1. Sur le serveur, activer explicitement les deux options :
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"AudioVideoCalls": {
|
|
|
|
|
|
"Enabled": true,
|
|
|
|
|
|
"EnableLanCalls": true
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Les deux valeurs sont `false` par défaut. Les paramètres TURN ne sont
|
|
|
|
|
|
pas nécessaires pour ce mode. Utiliser le ChatHub en **HTTPS** ;
|
|
|
|
|
|
invitation, acceptation et échange de clés LAN sont refusés en HTTP.
|
|
|
|
|
|
Derrière un proxy TLS, configurer correctement le schéma HTTPS transmis
|
|
|
|
|
|
à ASP.NET Core, uniquement depuis les proxys de confiance.
|
2026-10-26 04:15:19 +00:00
|
|
|
|
2. Utiliser deux clients Android 8+ ou Desktop Linux. Linux nécessite LibVLC
|
|
|
|
|
|
avec V4L2, PulseAudio, x264, AAC et RTP/SRTP installés. Android réutilise
|
|
|
|
|
|
la bibliothèque VLC embarquée pour les Podcasts et MediaRecorder pour
|
|
|
|
|
|
H.264/AAC. La version Debian 13 a été utilisée pour les essais Linux.
|
|
|
|
|
|
Les deux comptes doivent être présents dans
|
2026-10-26 03:05:23 +00:00
|
|
|
|
la même salle existante et ne pas se bloquer mutuellement.
|
2026-11-02 15:33:03 +00:00
|
|
|
|
3. Dans « Appel direct IPv4/IPv6 (LAN/VPN ou IP publique) », actualiser les périphériques,
|
2026-10-26 03:05:23 +00:00
|
|
|
|
sélectionner la caméra, le microphone et une IPv4 privée locale
|
|
|
|
|
|
accessible depuis le pair. Les adresses RFC1918 et de bouclage sont
|
|
|
|
|
|
acceptées ; pas de DNS, IPv6 ou adresse publique. Le bouclage sert aux
|
|
|
|
|
|
essais sur un même hôte, pas à joindre un second poste.
|
|
|
|
|
|
4. Choisir un port UDP **pair entre 1024 et 65534**, par défaut 5004.
|
2026-10-26 04:15:19 +00:00
|
|
|
|
Autoriser l'entrée UDP sur ce port **et le suivant** depuis le pair dans
|
|
|
|
|
|
le pare-feu : RTP sur le port pair, RTCP sur le port impair suivant.
|
|
|
|
|
|
Les deux ports doivent être disponibles. Deux clients sur la même
|
|
|
|
|
|
adresse doivent utiliser des paires distinctes.
|
|
|
|
|
|
Aucun pare-feu n'est modifié automatiquement.
|
2026-10-26 03:05:23 +00:00
|
|
|
|
5. Saisir le pseudo exact du destinataire, confirmer la divulgation de
|
2026-11-02 15:33:03 +00:00
|
|
|
|
l'adresse IP locale (LAN/VPN ou publique), puis appeler. Le destinataire choisit ses propres
|
2026-10-26 03:05:23 +00:00
|
|
|
|
périphériques et son adresse, confirme et accepte explicitement.
|
|
|
|
|
|
Aucun accès à la caméra/microphone ne commence avant l'acceptation ;
|
|
|
|
|
|
l'émission attend également la destination validée du pair.
|
|
|
|
|
|
6. Utiliser un **casque** : il n'y a pas d'annulation d'écho acoustique.
|
|
|
|
|
|
« Refuser / Raccrocher », la sortie de page et la perte de SignalR
|
|
|
|
|
|
arrêtent et libèrent les médias. Il n'y a pas de reprise automatique
|
|
|
|
|
|
de capture après reconnexion.
|
|
|
|
|
|
|
2026-10-26 04:15:19 +00:00
|
|
|
|
### Capture et cycle de vie Android
|
|
|
|
|
|
|
|
|
|
|
|
- La caméra avant est sélectionnée en priorité dans la liste ; une autre
|
|
|
|
|
|
caméra reste sélectionnable explicitement. Le microphone est obligatoire.
|
|
|
|
|
|
- Les permissions caméra, microphone et notifications sont demandées
|
|
|
|
|
|
après acceptation et réception de l'endpoint distant, avant la capture.
|
|
|
|
|
|
Un refus termine explicitement l'appel, sans tentative de capture de repli.
|
|
|
|
|
|
- Camera2, MediaRecorder et la rotation EGL sont ceux des Podcasts.
|
|
|
|
|
|
Le descripteur du pipe MPEG-TS est lu directement par LibVLC (`fd://`)
|
|
|
|
|
|
puis remultiplexé vers SRTP, **sans réencodage**, HLS ou fichier média.
|
|
|
|
|
|
Le pipe système assure une mémoire bornée ; il n'y a pas de file de
|
|
|
|
|
|
segments ni de lecture de capture par callbacks managés.
|
|
|
|
|
|
- La prévisualisation réutilise la surface EGL existante. Le retour
|
|
|
|
|
|
distant utilise la surface Android LibVLC déjà employée pour les Podcasts.
|
2026-11-05 10:44:19 +00:00
|
|
|
|
La rotation capteur/écran tient compte de celle déjà portée par la matrice
|
|
|
|
|
|
`SurfaceTexture` (miroir de la caméra avant compris) et suit les changements
|
|
|
|
|
|
portrait/paysage. Les dimensions
|
|
|
|
|
|
encodées restent fixes pendant l'appel, avec bandes noires si nécessaire.
|
2026-10-26 04:15:19 +00:00
|
|
|
|
- Le service de capture partagé affiche une notification d'appel avec
|
|
|
|
|
|
l'action « Raccrocher » ; cette action ne publie aucun Podcast.
|
|
|
|
|
|
Un Podcast et un appel ne peuvent pas posséder la capture simultanément.
|
|
|
|
|
|
- Le passage de PostIt en arrière-plan termine cet appel vidéo ; revenir
|
|
|
|
|
|
dans l'application ne le redémarre pas. La sortie de page et la perte
|
|
|
|
|
|
SignalR conservent la même règle d'arrêt.
|
|
|
|
|
|
- À l'arrêt, le lecteur natif libère d'abord son entrée. Le pipe restant
|
|
|
|
|
|
est drainé pendant la finalisation de MediaRecorder, pour ne pas bloquer
|
|
|
|
|
|
son écrivain, puis caméra, microphone, lecteurs et service sont libérés.
|
|
|
|
|
|
|
|
|
|
|
|
#### Particularité VLC Android : RTCP séparé
|
|
|
|
|
|
|
|
|
|
|
|
L'essai matériel initial a identifié un SIGSEGV dans `libc.__vfprintf`,
|
|
|
|
|
|
appelé par `vlc_memstream_vprintf` puis `sdp_AddAttribute` pendant la
|
|
|
|
|
|
création de la sortie RTP. Le code VLC 3 génère l'attribut sans valeur
|
|
|
|
|
|
`rtcp-mux` avec un format nul ; cette combinaison échoue avec le binaire
|
|
|
|
|
|
Android embarqué. Ce crash est distinct du précédent essai libwebrtc/JNI.
|
|
|
|
|
|
|
|
|
|
|
|
Les appels utilisent donc une paire RTP/RTCP standard, sans `rtcp-mux`,
|
|
|
|
|
|
sur Android **et** Linux. Les médias conservent les mêmes codecs, clés et
|
|
|
|
|
|
port RTP : c'est un changement de configuration du transport, pas
|
|
|
|
|
|
l'ajout d'un moteur WebRTC ou d'une cryptographie propre au projet.
|
|
|
|
|
|
|
2026-10-26 03:05:23 +00:00
|
|
|
|
### Confidentialité et limites
|
|
|
|
|
|
|
|
|
|
|
|
- Une clé SRTP aléatoire de 128 bits et un sel de 112 bits sont générés
|
|
|
|
|
|
par appel et par direction avec le générateur cryptographique système.
|
|
|
|
|
|
Seuls les deux appareils ayant accepté échangent un endpoint chacun
|
|
|
|
|
|
via SignalR authentifié. Les représentations diagnostiques masquent
|
|
|
|
|
|
adresse, clé et sel.
|
|
|
|
|
|
- Le chiffrement SRTP est fourni par LibVLC ; les clés passent par
|
|
|
|
|
|
le serveur de signalisation, qui **peut donc les connaître**. Ce n'est
|
|
|
|
|
|
pas un chiffrement de bout en bout à l'insu du serveur.
|
|
|
|
|
|
- Si l'un des comptes impose `HideIpAddressInCalls`, le mode LAN est
|
|
|
|
|
|
**refusé**, y compris si la préférence change avant l'acceptation.
|
|
|
|
|
|
Il n'y a aucun repli direct contournant cette préférence.
|
|
|
|
|
|
- Pas d'ICE, de STUN, de TURN, de traversée NAT automatique, de groupe,
|
2026-10-26 04:15:19 +00:00
|
|
|
|
d'interopérabilité Browser, de négociation de codecs ni
|
2026-11-02 15:33:03 +00:00
|
|
|
|
d'adaptation de débit. Ce mode exige une connectivite IP directe entre les pairs
|
2026-11-02 15:25:54 +00:00
|
|
|
|
(LAN/VPN ou adresse publique assignee), avec les ports UDP ouverts.
|
2026-10-26 03:05:23 +00:00
|
|
|
|
- H.264 à 30 images/s, cible 1 200 kbit/s ; AAC mono 48 kHz, 96 kbit/s.
|
|
|
|
|
|
Ces réglages ne constituent pas une garantie de latence ni de débit.
|
|
|
|
|
|
Le retour local n'émet pas le son du microphone.
|
|
|
|
|
|
- L'absence de première réception audio **et** vidéo provoque l'arrêt
|
|
|
|
|
|
après 30 secondes ; les erreurs natives sont affichées et terminent
|
|
|
|
|
|
l'appel. Après réception initiale, les compteurs LibVLC ne permettent
|
|
|
|
|
|
pas ici de diagnostiquer précisément une panne média silencieuse :
|
|
|
|
|
|
l'utilisateur peut raccrocher, et la perte de SignalR arrête toujours
|
|
|
|
|
|
la capture. Pas encore de mesure de qualité ou de latence affichée.
|
|
|
|
|
|
|
|
|
|
|
|
### Validation effectuée et restante
|
|
|
|
|
|
|
|
|
|
|
|
Les tests natifs utilisent deux moteurs LibVLC réels, un fichier audio-vidéo
|
|
|
|
|
|
synthétique fourni explicitement et de vrais sockets UDP de bouclage :
|
|
|
|
|
|
|
|
|
|
|
|
- décodage bidirectionnel de trames vidéo et d'échantillons audio PCM ;
|
|
|
|
|
|
- refus de décodage avec une mauvaise clé, sans casser l'autre direction ;
|
|
|
|
|
|
- même échange avec la branche de prévisualisation locale activée
|
|
|
|
|
|
(sortie factice dans ce test sans fenêtre).
|
2026-10-26 04:15:19 +00:00
|
|
|
|
- entrée MPEG-TS déjà encodée à travers un pipe, sans transcodage.
|
2026-10-26 03:05:23 +00:00
|
|
|
|
|
|
|
|
|
|
Les tests de signalisation couvrent consentement, sélection d'un seul
|
|
|
|
|
|
appareil, confidentialité, HTTPS, validation des endpoints et arrêt.
|
|
|
|
|
|
Les tests Avalonia sans fenêtre couvrent l'ordre invitation/acceptation/
|
|
|
|
|
|
capture, le refus, les événements tardifs, l'interruption, les erreurs média
|
2026-10-26 04:15:19 +00:00
|
|
|
|
et l'annulation d'un démarrage natif en attente. Ils vérifient aussi les
|
|
|
|
|
|
hooks Android, le choix initial de caméra avant, la configuration lors
|
|
|
|
|
|
d'une invitation entrante et l'arrêt lors du passage en arrière-plan.
|
2026-10-26 03:05:23 +00:00
|
|
|
|
|
|
|
|
|
|
Pour exécuter les tests média, définir `POSTIT_TEST_MEDIA` avec le chemin
|
|
|
|
|
|
d'un MP4 H.264/AAC de test (640 × 480), puis :
|
|
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
|
dotnet test --project src/PostIt/PostIt.Tests/PostIt.Tests.csproj \
|
|
|
|
|
|
--filter-class '*LinuxLanCallMediaTests'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Sans cette entrée explicite, ces tests sont ignorés, pas remplacés par un
|
|
|
|
|
|
succès fictif. Les tests de contrôle s'exécutent sans caméra.
|
2026-10-26 04:15:19 +00:00
|
|
|
|
Le test de pipe utilise `POSTIT_TEST_TS`, un MPEG-TS H.264/AAC explicite.
|
|
|
|
|
|
|
|
|
|
|
|
Une activité **Debug uniquement**,
|
|
|
|
|
|
[AndroidLanCallTestActivity](../../src/PostIt/PostIt.Tests/AndroidLanCallTestActivity.cs),
|
|
|
|
|
|
teste l'adaptateur réel sur téléphone : caméra avant/microphone, surfaces
|
|
|
|
|
|
de retour et prévisualisation attachées, deux moteurs SRTP en UDP de
|
|
|
|
|
|
bouclage, retour synthétique et rejet d'une mauvaise clé. Elle n'utilise
|
|
|
|
|
|
ni compte ni API ; elle ne valide donc pas à elle seule un appel SignalR
|
|
|
|
|
|
entre deux comptes. L'activité n'est pas compilée dans l'APK Release.
|
|
|
|
|
|
|
|
|
|
|
|
Pour la lancer sur un appareil de développement dont les permissions
|
|
|
|
|
|
ont été accordées, installer l'APK Debug et ses assemblies via
|
|
|
|
|
|
`dotnet build -t:Install`, puis copier un MPEG-TS synthétique de 40 secondes,
|
|
|
|
|
|
640 × 480 avec audio AAC, sous `files/lan-call-fixture.ts` dans les données
|
|
|
|
|
|
privées de l'application. Exécuter :
|
|
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
|
adb shell am start -S -n fr.pschneider.postit/fr.pschneider.postit.LanCallTestActivity
|
|
|
|
|
|
adb shell run-as fr.pschneider.postit cat files/lan-call-test-result.txt
|
|
|
|
|
|
# Variante : ajouter --es wrongKey true à la commande am start.
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Le résultat ne devient `PASS` qu'après vérification des médias et nettoyage
|
|
|
|
|
|
complet. Le test ne produit aucun enregistrement de caméra.
|
|
|
|
|
|
Sur le téléphone Android 15 arm64 connecté, l'essai positif a décodé
|
|
|
|
|
|
158 trames caméra et 399 360 échantillons audio en environ dix secondes,
|
|
|
|
|
|
avec un retour audio/vidéo décodé simultanément. L'essai avec mauvaise clé
|
|
|
|
|
|
a produit zéro trame et zéro échantillon dans la direction concernée,
|
|
|
|
|
|
tout en conservant le retour. Les deux essais ont terminé leur nettoyage,
|
|
|
|
|
|
sans service de capture restant. La capture Podcast antérieure a également
|
|
|
|
|
|
été retestée sur caméra avant : quatre segments, environ 11,8 secondes,
|
|
|
|
|
|
audio AAC présent, capture en arrière-plan puis arrêt par notification.
|
|
|
|
|
|
|
2026-10-26 03:05:23 +00:00
|
|
|
|
**La caméra physique, le rendu natif visible dans deux applications, le
|
2026-10-26 04:15:19 +00:00
|
|
|
|
son audible et un appel entre deux machines restent à valider côté Linux** :
|
|
|
|
|
|
aucune caméra n'était disponible sur cet hôte. La capture matérielle Android
|
|
|
|
|
|
est testée, mais un appel Android ↔ Linux ou entre deux téléphones distincts
|
|
|
|
|
|
sur LAN/VPN et la qualité acoustique restent à valider. Les essais de
|
|
|
|
|
|
bouclage ne prouvent pas une latence conversationnelle.
|
2026-10-26 03:05:23 +00:00
|
|
|
|
|
2026-10-25 14:02:03 +00:00
|
|
|
|
## Choix des protocoles
|
|
|
|
|
|
|
2026-10-26 03:05:23 +00:00
|
|
|
|
La table suivante demeure la **cible multi-plateforme initiale**, distincte
|
|
|
|
|
|
du premier transport Linux LAN/VPN décrit ci-dessus.
|
|
|
|
|
|
|
2026-10-25 14:02:03 +00:00
|
|
|
|
| Besoin | Choix | Rôle |
|
|
|
|
|
|
|---|---|---|
|
|
|
|
|
|
| Médias temps réel | WebRTC | Audio-vidéo bidirectionnel à faible latence, adaptation au réseau |
|
|
|
|
|
|
| Chiffrement du transport média | DTLS-SRTP | Établissement des clés et protection des médias |
|
|
|
|
|
|
| Signalisation | SignalR sur HTTPS | Invitation, acceptation/refus, négociation SDP, candidats ICE, fin d'appel |
|
|
|
|
|
|
| Connectivité | ICE, STUN et TURN | Sélection du chemin réseau, découverte d'adresse et relais |
|
|
|
|
|
|
| Audio | Opus | Codec privilégié pour la voix |
|
|
|
|
|
|
| Vidéo | VP8 ou H.264 | Codec négocié selon les capacités réelles des clients |
|
|
|
|
|
|
| Appels de groupe | SFU compatible WebRTC | Réception et redistribution sélective des flux |
|
|
|
|
|
|
|
|
|
|
|
|
SignalR transporte les messages de contrôle, **jamais les flux audio-vidéo**.
|
2026-10-26 01:00:19 +00:00
|
|
|
|
La signalisation doit réutiliser le [ChatHub existant](../../src/Yavsc.Server/Hubs/ChatHub.cs),
|
|
|
|
|
|
déjà exposé par [Yavsc.Api](../../src/Yavsc.Api/Program.cs), et ses salles de
|
|
|
|
|
|
discussion. Il n'est pas nécessaire de créer un second service de salles.
|
|
|
|
|
|
Les contrats d'appel et leurs autorisations restent à définir explicitement :
|
|
|
|
|
|
l'appartenance à une salle ne vaut pas acceptation d'un appel.
|
2026-10-25 14:02:03 +00:00
|
|
|
|
Le choix des bibliothèques natives, du SFU et des codecs effectivement
|
|
|
|
|
|
disponibles reste à valider par un prototype multi-plateforme.
|
|
|
|
|
|
|
|
|
|
|
|
## Topologies média
|
|
|
|
|
|
|
|
|
|
|
|
### Appels à deux
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
PostIt A ---- SignalR / HTTPS ---- Serveur ---- SignalR / HTTPS ---- PostIt B
|
|
|
|
|
|
Invitation, acceptation, SDP, candidats ICE, fin
|
|
|
|
|
|
|
|
|
|
|
|
PostIt A ================= WebRTC direct ========================= PostIt B
|
|
|
|
|
|
ou
|
|
|
|
|
|
PostIt A ================= relais TURN =========================== PostIt B
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Privilégier un chemin direct lorsque les préférences de confidentialité le
|
|
|
|
|
|
permettent. Prévoir TURN dès la première version : STUN seul ne suffit pas sur
|
|
|
|
|
|
certains réseaux mobiles, NAT ou réseaux d'entreprise.
|
|
|
|
|
|
|
|
|
|
|
|
Déployer par exemple coturn, avec des transports UDP et des solutions de
|
|
|
|
|
|
repli TCP/TLS, dont TURN/TLS sur le port 443. Ce dernier améliore la
|
|
|
|
|
|
connectivité sans garantir la traversée de tous les pare-feu et proxys.
|
|
|
|
|
|
|
|
|
|
|
|
### Appels de groupe
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
PostIt A ---- WebRTC, éventuellement via TURN ----+
|
|
|
|
|
|
PostIt B ---- WebRTC, éventuellement via TURN ----+---- SFU
|
|
|
|
|
|
PostIt C ---- WebRTC, éventuellement via TURN ----+
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Utiliser un **SFU**, plutôt qu'un maillage de connexions entre participants :
|
|
|
|
|
|
chaque client envoie ses pistes au serveur, qui redistribue les flux utiles.
|
|
|
|
|
|
Cela évite de multiplier les envois montants avec le nombre de participants.
|
|
|
|
|
|
Prévoir la sélection des pistes reçues et, selon les capacités des clients,
|
|
|
|
|
|
le simulcast ou le codage vidéo scalable pour adapter débit et résolution.
|
|
|
|
|
|
|
|
|
|
|
|
Le SFU ne remplace pas TURN : un client peut avoir besoin d'un relais pour
|
|
|
|
|
|
atteindre le SFU, ou l'imposer par sa préférence de confidentialité.
|
|
|
|
|
|
|
|
|
|
|
|
Les contrats de signalisation doivent représenter dès le départ un appel et
|
|
|
|
|
|
ses participants, sans être limités à un couple appelant/appelé. Pour ajouter
|
|
|
|
|
|
un troisième participant à un appel direct, établir les connexions au SFU,
|
|
|
|
|
|
puis fermer les connexions directes après confirmation du nouveau transport.
|
|
|
|
|
|
En cas d'échec, conserver l'appel à deux et signaler l'échec de l'ajout.
|
|
|
|
|
|
Une topologie SFU pour tous les appels reste une alternative à évaluer si la
|
|
|
|
|
|
simplicité d'exploitation prime sur le coût serveur.
|
|
|
|
|
|
|
|
|
|
|
|
## Préférence persistante de masquage d'adresse IP
|
|
|
|
|
|
|
|
|
|
|
|
### Contrat fonctionnel
|
|
|
|
|
|
|
2026-10-25 16:49:51 +00:00
|
|
|
|
Le booléen de compte `HideIpAddressInCalls` est persisté côté serveur et
|
|
|
|
|
|
accessible en lecture/écriture uniquement par
|
|
|
|
|
|
l'utilisateur concerné via `GET /api/v1/account/me` et
|
|
|
|
|
|
`PUT /api/v1/account/me`, ainsi que dans « Mon profil » de PostIt.
|
|
|
|
|
|
Le réglage est partagé entre ses appareils ; une préférence locale seule
|
|
|
|
|
|
ne suffit pas.
|
|
|
|
|
|
|
|
|
|
|
|
Valeur initiale : `false`, pour les nouveaux comptes et les comptes existants
|
|
|
|
|
|
après migration. Le champ de mise à jour est nullable : son absence ou `null`
|
|
|
|
|
|
conserve la valeur existante, notamment pour les anciens clients ; `false`
|
|
|
|
|
|
explicite désactive la préférence.
|
2026-10-25 14:02:03 +00:00
|
|
|
|
`false` autorise le chemin direct mais n'interdit pas TURN lorsqu'il est
|
|
|
|
|
|
nécessaire à la connectivité. `true` impose un transport relayé.
|
|
|
|
|
|
|
|
|
|
|
|
Présenter le réglage comme « Masquer mon adresse IP aux autres participants »,
|
|
|
|
|
|
en précisant le surcoût potentiel en latence et en bande passante serveur.
|
|
|
|
|
|
Il ne procure pas l'anonymat : les services contactés, notamment l'API, le
|
|
|
|
|
|
serveur de signalisation et TURN, peuvent toujours connaître l'adresse IP.
|
|
|
|
|
|
|
2026-10-25 16:49:51 +00:00
|
|
|
|
La migration EF Core `HideIpAddressInCalls`, dans le projet Yavsc.Org, ajoute
|
|
|
|
|
|
la colonne booléenne non nullable à `AspNetUsers`. Elle doit être déployée
|
|
|
|
|
|
avant de servir les nouvelles lectures et écritures de profil. Cette étape
|
|
|
|
|
|
n'installe ni TURN ni SFU et n'implémente pas encore les règles de négociation
|
|
|
|
|
|
décrites ci-dessous.
|
|
|
|
|
|
|
2026-10-25 14:02:03 +00:00
|
|
|
|
### Application à la négociation
|
|
|
|
|
|
|
|
|
|
|
|
- Charger la préférence avant de créer le transport média. Si sa lecture
|
|
|
|
|
|
échoue, signaler l'erreur et bloquer l'établissement plutôt que supposer
|
|
|
|
|
|
que le masquage est désactivé.
|
|
|
|
|
|
- Lorsque le réglage est activé, configurer une politique ICE **relay-only**
|
|
|
|
|
|
(`iceTransportPolicy: "relay"` dans le navigateur, équivalent natif ailleurs)
|
|
|
|
|
|
avant la collecte des candidats.
|
|
|
|
|
|
- Ne publier aucun candidat local `host` ou `srflx`, ni aucune adresse locale
|
|
|
|
|
|
dans les descriptions SDP ou messages de signalisation. Utiliser les API du
|
|
|
|
|
|
moteur WebRTC et vérifier les descriptions produites, plutôt qu'une
|
|
|
|
|
|
réécriture ad hoc du SDP.
|
|
|
|
|
|
- Appliquer cette contrainte aux offres, réponses, renégociations,
|
|
|
|
|
|
redémarrages ICE et transitions vers le SFU.
|
|
|
|
|
|
- Le masquage d'un participant impose le relais de **son propre transport**,
|
|
|
|
|
|
même si les autres participants n'ont pas activé cette préférence.
|
|
|
|
|
|
- Si TURN est indisponible ou qu'aucune paire de candidats relayée n'aboutit,
|
|
|
|
|
|
afficher une erreur explicite ; **aucun repli direct automatique**.
|
|
|
|
|
|
|
|
|
|
|
|
Le serveur détermine la politique attendue depuis la préférence persistée,
|
|
|
|
|
|
contrôle les messages de signalisation et distribue les paramètres autorisés.
|
|
|
|
|
|
Le client applique la politique ICE ; les tests doivent vérifier le chemin
|
|
|
|
|
|
réellement sélectionné, pas seulement la configuration demandée.
|
|
|
|
|
|
|
|
|
|
|
|
Une modification pendant un appel doit être prise en charge explicitement :
|
|
|
|
|
|
l'activation suspend l'émission et remplace le transport avant de reprendre
|
|
|
|
|
|
les médias en mode relayé. L'interface ne doit pas annoncer le masquage tant
|
|
|
|
|
|
que ce remplacement n'est pas confirmé. Elle précise qu'une adresse déjà
|
|
|
|
|
|
divulguée auparavant ne peut pas être retirée aux participants.
|
|
|
|
|
|
La désactivation peut attendre l'appel suivant, sans abandonner le relais
|
|
|
|
|
|
en cours.
|
|
|
|
|
|
|
|
|
|
|
|
## Intégration dans PostIt
|
|
|
|
|
|
|
|
|
|
|
|
Séparer le cycle de vie partagé de l'appel du moteur média :
|
|
|
|
|
|
|
|
|
|
|
|
- code partagé : invitation, sonnerie, acceptation/refus, participants,
|
|
|
|
|
|
préférences, état de connexion, coupure micro/caméra et raccrochage ;
|
|
|
|
|
|
- Browser : API WebRTC du navigateur via interop JavaScript ;
|
|
|
|
|
|
- Android et Desktop : moteur WebRTC natif et intégration de la capture,
|
|
|
|
|
|
des périphériques et du rendu dans Avalonia.
|
|
|
|
|
|
|
|
|
|
|
|
Le prototype doit vérifier les bindings maintenus, leurs licences, les
|
|
|
|
|
|
architectures processeur supportées, les codecs et l'intégration Avalonia.
|
|
|
|
|
|
Ne pas supposer qu'une bibliothèque .NET couvre à elle seule la capture,
|
|
|
|
|
|
l'annulation d'écho et le rendu sur toutes les plateformes.
|
|
|
|
|
|
|
|
|
|
|
|
Prévoir les permissions caméra/micro, les changements de périphérique,
|
|
|
|
|
|
les interruptions Android, la reconnexion et le redémarrage ICE.
|
|
|
|
|
|
Les appels entrants en arrière-plan nécessitent une intégration aux
|
|
|
|
|
|
notifications système et au cycle de vie Android ; une connexion SignalR
|
|
|
|
|
|
active ne peut pas être présumée.
|
|
|
|
|
|
|
|
|
|
|
|
## Autorisations, confidentialité et exploitation
|
|
|
|
|
|
|
|
|
|
|
|
- Authentifier la signalisation et vérifier côté serveur l'appartenance à
|
|
|
|
|
|
l'appel pour chaque commande et événement, y compris rejoindre un groupe,
|
|
|
|
|
|
inviter, publier une piste et recevoir les flux.
|
|
|
|
|
|
- Prévoir des invitations expirables et gérer les réponses concurrentes de
|
|
|
|
|
|
plusieurs appareils sans accepter plusieurs fois le même participant.
|
|
|
|
|
|
- Délivrer des identifiants TURN temporaires et des autorisations SFU limitées
|
|
|
|
|
|
à l'appel et au participant ; aucun secret permanent dans les clients.
|
|
|
|
|
|
- Limiter les invitations, les participants et les débits selon une politique
|
|
|
|
|
|
produit à définir ; surveiller la capacité et le coût TURN/SFU.
|
|
|
|
|
|
- Ne pas journaliser systématiquement SDP, candidats ICE ou identifiants TURN.
|
|
|
|
|
|
Préférer des métriques de qualité et des identifiants techniques d'appel.
|
|
|
|
|
|
- Distinguer chiffrement du transport et chiffrement de bout en bout :
|
|
|
|
|
|
en connexion directe ou via TURN, les médias restent chiffrés entre les deux
|
|
|
|
|
|
clients ; avec un SFU classique, DTLS-SRTP se termine au SFU. Un chiffrement
|
|
|
|
|
|
de bout en bout des groupes demanderait un mécanisme supplémentaire et une
|
|
|
|
|
|
gestion des clés à concevoir, sans être promis par ce plan.
|
|
|
|
|
|
|
|
|
|
|
|
## Étapes proposées
|
|
|
|
|
|
|
|
|
|
|
|
1. **Prototype multi-plateforme** : valider capture, rendu, codecs et WebRTC
|
|
|
|
|
|
entre Browser, Android et Desktop, y compris via TURN.
|
|
|
|
|
|
2. **Appels à deux** : signalisation authentifiée, cycle de vie d'appel,
|
|
|
|
|
|
coturn, préférence persistante et politique relay-only opérationnelle.
|
|
|
|
|
|
3. **Appels de groupe** : sélectionner et intégrer le SFU, autoriser les
|
|
|
|
|
|
participants, gérer les pistes et la transition depuis un appel direct.
|
|
|
|
|
|
4. **Fiabilisation** : arrière-plan Android, réseau mobile, reprise après
|
|
|
|
|
|
interruption, accessibilité des contrôles et observabilité.
|
|
|
|
|
|
|
|
|
|
|
|
Les appels de groupe font partie de la cible finale, pas d'une simple
|
|
|
|
|
|
extension facultative. Leur modèle de participants doit être anticipé dès
|
|
|
|
|
|
la signalisation des premiers appels à deux.
|
|
|
|
|
|
|
|
|
|
|
|
## Critères de validation
|
|
|
|
|
|
|
|
|
|
|
|
- Audio et vidéo bidirectionnels sur les combinaisons de plateformes ciblées.
|
|
|
|
|
|
- Appel direct autorisé quand le réglage est désactivé et relais disponible
|
|
|
|
|
|
lorsque le réseau l'exige.
|
|
|
|
|
|
- Préférence conservée après reconnexion et relue sur un autre appareil.
|
|
|
|
|
|
- Avec masquage activé, absence d'adresses locales/publiques propres au client
|
|
|
|
|
|
dans la signalisation transmise aux pairs et sélection effective d'un
|
|
|
|
|
|
candidat local `relay`, confirmée par les statistiques WebRTC.
|
|
|
|
|
|
- Aucun repli direct si TURN échoue, y compris après redémarrage ICE,
|
|
|
|
|
|
changement de réseau ou ajout d'un participant.
|
|
|
|
|
|
- En groupe, contrôle d'accès aux pistes, départ et arrivée de participants,
|
|
|
|
|
|
adaptation de qualité et respect individuel de la politique TURN.
|
|
|
|
|
|
- Activation du masquage pendant un appel : suspension des médias,
|
|
|
|
|
|
remplacement vérifié du transport et retour d'état fidèle dans l'interface.
|
|
|
|
|
|
- Échecs de permissions, de signalisation, de TURN et du SFU visibles,
|
2026-10-26 01:00:19 +00:00
|
|
|
|
ressources caméra/micro et connexions libérées à la fin de l'appel.
|
|
|
|
|
|
|
|
|
|
|
|
## Première tranche intégrée : signalisation Android et Desktop Linux
|
|
|
|
|
|
|
|
|
|
|
|
Le périmètre initial retenu est **Android + Desktop Linux**. Il n'ajoute
|
|
|
|
|
|
aucun serveur ni aucune salle : les méthodes suivantes appartiennent au
|
|
|
|
|
|
[ChatHub](../../src/Yavsc.Server/Hubs/ChatHub.Calls.cs) existant.
|
|
|
|
|
|
Les [contrats partagés](../../src/Yavsc.Abstract/Chat/Calls/CallContracts.cs)
|
|
|
|
|
|
sont utilisés par le serveur et PostIt.
|
|
|
|
|
|
|
|
|
|
|
|
| Méthode | Effet |
|
|
|
|
|
|
|---|---|
|
|
|
|
|
|
| `InviteCall(roomName, callee)` | Invite un autre compte présent dans la salle et retourne un identifiant d'appel |
|
|
|
|
|
|
| `AcceptCall(callId)` | Accepte sur un seul appareil, notifie les deux pairs et ferme l'invitation sur les autres appareils |
|
|
|
|
|
|
| `SendCallSignal(callId, signal)` | Transmet l'offre, la réponse ou un candidat ICE uniquement à l'autre appareil accepté |
|
|
|
|
|
|
| `EndCall(callId)` | Annule, refuse ou termine l'appel depuis un appareil autorisé |
|
|
|
|
|
|
|
|
|
|
|
|
Événements : `CallInvitation`, `CallAccepted`, `CallSignal(callId, signal)`
|
|
|
|
|
|
et `CallEnded`. **Accepté ne veut pas dire connecté** : l'événement accepté
|
|
|
|
|
|
exprime le consentement et fournit la politique ICE et les paramètres
|
|
|
|
|
|
STUN/TURN, pas une réussite de l'échange média.
|
|
|
|
|
|
|
|
|
|
|
|
Le serveur vérifie les comptes, la présence dans la salle et le blocage
|
|
|
|
|
|
entre utilisateurs. Les appareils d'un compte reçoivent l'invitation ;
|
|
|
|
|
|
seul le premier qui accepte peut ensuite émettre la réponse et les
|
|
|
|
|
|
candidats. L'appelant reste lié à sa connexion d'origine. Les médias
|
|
|
|
|
|
ne sont jamais diffusés au groupe SignalR de la salle.
|
|
|
|
|
|
|
|
|
|
|
|
La préférence persistée est lue à l'invitation et relue à l'acceptation.
|
|
|
|
|
|
Pour cette première version à deux, si l'un des comptes demande le
|
|
|
|
|
|
masquage, **les deux transports doivent être relayés**, règle conservatrice
|
|
|
|
|
|
plus stricte que la politique individuelle cible. L'acceptation ne peut
|
|
|
|
|
|
pas diminuer la protection annoncée à l'invitation. Sans TURN configuré,
|
|
|
|
|
|
un appel imposant le relais échoue explicitement.
|
|
|
|
|
|
|
|
|
|
|
|
La signalisation refuse les candidats non relayés, les adresses associées
|
|
|
|
|
|
non masquées et les adresses directes dans les champs SDP contrôlés lorsque
|
|
|
|
|
|
le relais est imposé. Ces contrôles de forme ne constituent pas un audit
|
|
|
|
|
|
exhaustif de toutes les extensions SDP possibles : la non-divulgation doit
|
|
|
|
|
|
encore être prouvée avec les SDP et statistiques des moteurs réellement
|
|
|
|
|
|
intégrés. Aucun SDP n'est réécrit.
|
|
|
|
|
|
|
|
|
|
|
|
L'activation du masquage ou le changement de pseudo par l'API de profil
|
|
|
|
|
|
termine l'appel existant ; le client devra libérer les médias et proposer
|
|
|
|
|
|
un nouvel appel. La renégociation transparente du transport n'est pas
|
|
|
|
|
|
implémentée. La déconnexion d'un pair sélectionné, le départ ou l'exclusion
|
|
|
|
|
|
de la salle terminent également l'appel. Pas de reprise automatique après
|
|
|
|
|
|
reconnexion : elle crée une nouvelle identité de connexion.
|
|
|
|
|
|
|
|
|
|
|
|
Les appels sont temporaires, en mémoire et **sur une seule instance API**.
|
|
|
|
|
|
Une invitation expire après 45 secondes, une session acceptée après une
|
|
|
|
|
|
heure ; les identifiants TURN expirent cinq minutes plus tard. Cette borne
|
|
|
|
|
|
initiale ne remplace pas un futur renouvellement d'identifiants pour les
|
|
|
|
|
|
appels longs. Un compte ne peut avoir qu'un appel réservé ou accepté à la
|
|
|
|
|
|
fois. Le registre est limité à 128 appels et 256 candidats par appel.
|
|
|
|
|
|
La tranche ne permet qu'une offre initiale de l'appelant et une réponse ;
|
|
|
|
|
|
les redémarrages ICE et renégociations restent à implémenter.
|
|
|
|
|
|
|
|
|
|
|
|
Configuration serveur, section `AudioVideoCalls` :
|
|
|
|
|
|
|
|
|
|
|
|
- `Enabled` : `false` par défaut, à conserver tant que les moteurs ne sont
|
|
|
|
|
|
pas validés ;
|
|
|
|
|
|
- `StunUrls` : tableau d'URI `stun:` ou `stuns:` ;
|
|
|
|
|
|
- `TurnUrls` : tableau d'URI `turn:` ou `turns:`, avec transport optionnel ;
|
|
|
|
|
|
- `TurnSharedSecret` : secret REST coturn, **uniquement côté serveur**,
|
|
|
|
|
|
à fournir par le gestionnaire de secrets ou la variable d'environnement
|
|
|
|
|
|
`AudioVideoCalls__TurnSharedSecret`, jamais dans le dépôt.
|
|
|
|
|
|
|
|
|
|
|
|
Les credentials TURN temporaires sont calculés côté serveur avec le
|
|
|
|
|
|
format REST coturn (expiration, nonce aléatoire et HMAC-SHA1). Aucun secret
|
|
|
|
|
|
de longue durée n'est envoyé aux clients. Aucun service TURN n'a été
|
|
|
|
|
|
déployé ou configuré par cette tranche.
|
|
|
|
|
|
|
|
|
|
|
|
Le [transport PostIt](../../src/PostIt/PostIt/Services/CallSignalingClient.cs)
|
|
|
|
|
|
utilise la connexion authentifiée du `ChatViewModel`, sans seconde connexion
|
|
|
|
|
|
ni interrogation HTTP. Il expose les commandes et événements typés et
|
|
|
|
|
|
signale les interruptions ; il ne capture aucun média. L'interface ne
|
|
|
|
|
|
propose pas encore de bouton d'appel ; une éventuelle invitation est
|
|
|
|
|
|
signalée comme non utilisable faute de moteur natif, sans acceptation
|
|
|
|
|
|
automatique.
|
|
|
|
|
|
|
2026-10-26 03:05:23 +00:00
|
|
|
|
### Travail restant pour la cible Internet multi-plateforme
|
2026-10-26 01:00:19 +00:00
|
|
|
|
|
2026-10-26 03:05:23 +00:00
|
|
|
|
- Android : l'approche Java/JNI libwebrtc a été écartée à la demande du
|
2026-10-26 04:15:19 +00:00
|
|
|
|
projet ; aucun adaptateur libwebrtc expérimental n'est conservé.
|
|
|
|
|
|
L'adaptateur SRTP LAN réutilise désormais la capture Podcast ; la solution
|
|
|
|
|
|
compatible avec la cible Internet reste à choisir.
|
2026-10-26 03:05:23 +00:00
|
|
|
|
- Desktop Linux : le transport SRTP LAN est raccordé, mais ne remplace pas
|
|
|
|
|
|
les validations matérielles ni une solution de connectivité Internet.
|
2026-10-26 01:00:19 +00:00
|
|
|
|
- Côté partagé : relier consentement, états réels du moteur, mise en
|
|
|
|
|
|
sourdine, arrêt et libération des ressources à la signalisation.
|
|
|
|
|
|
- Valider un appel Android ↔ Desktop Linux avec caméra avant et microphone
|
|
|
|
|
|
réels, rendu et audio distants, VP8/Opus, puis transport TURN sélectionné
|
|
|
|
|
|
dans les statistiques, sans repli direct lorsque le masquage est demandé.
|
|
|
|
|
|
|
|
|
|
|
|
Les tests de cette tranche portent sur les contrats, autorisations, courses
|
|
|
|
|
|
d'acceptation, expirations, limites, interruption et préférence persistée.
|
|
|
|
|
|
La compilation des applications Android et Desktop ne prouve pas le
|
|
|
|
|
|
fonctionnement de WebRTC natif : le crash antérieur n'est pas résolu.
|
|
|
|
|
|
|
|
|
|
|
|
## Retour sur l'essai Android du 25 octobre 2026
|
|
|
|
|
|
|
|
|
|
|
|
Le laboratoire indépendant a été supprimé ; il ne constitue pas une base
|
|
|
|
|
|
de salles de discussion ni une implémentation de PostIt. La suite doit
|
|
|
|
|
|
réutiliser le ChatHub existant pour la signalisation.
|
|
|
|
|
|
|
|
|
|
|
|
L'essai en échec opposait un téléphone Android 15 arm64 à Chromium,
|
|
|
|
|
|
en mode TURN uniquement, avec signalisation HTTP locale et TURN/TCP
|
|
|
|
|
|
accessibles par redirections USB adb. Il n'utilisait ni ChatHub ni
|
|
|
|
|
|
PostIt.Desktop Linux.
|
|
|
|
|
|
|
|
|
|
|
|
Les observations doivent être distinguées :
|
|
|
|
|
|
|
|
|
|
|
|
- Camera2, la capture audio et un premier rendu EGL local ont démarré.
|
|
|
|
|
|
Cela ne valide ni le transport ni le rendu distant.
|
|
|
|
|
|
- Le processus Android a subi un SIGABRT dans
|
|
|
|
|
|
`libjingle_peerconnection_so.so`. Une première pile passait par
|
|
|
|
|
|
`PeerConnection.nativeAddIceCandidate` ; après modification du traitement
|
|
|
|
|
|
des candidats, un arrêt natif persistait sur `network_thread`.
|
|
|
|
|
|
- Le test a attendu un échange média qui n'est jamais arrivé. Le dernier
|
|
|
|
|
|
rapport Browser indiquait `connection: new`, zéro octet audio/vidéo et
|
|
|
|
|
|
aucune paire ICE sélectionnée ; aucun rapport Android n'a validé l'appel.
|
|
|
|
|
|
- Le problème a été reproduit avec les SDK libwebrtc 150.7871.04 et
|
|
|
|
|
|
144.7559.15. L'attente des descriptions distantes, la résolution du
|
|
|
|
|
|
`sdpMid` et l'ajout asynchrone des candidats n'ont pas suffi.
|
|
|
|
|
|
|
|
|
|
|
|
Il s'agit donc d'un **crash natif pendant la tentative d'établissement**,
|
|
|
|
|
|
pas d'un refus de codec ou d'un échec TURN identifié. Le dernier appel JNI
|
|
|
|
|
|
visible ne prouve pas la cause du crash. Sans message fatal détaillé ni
|
|
|
|
|
|
pile native symbolisée, un défaut du code expérimental, de son intégration
|
|
|
|
|
|
Java/JNI ou de libwebrtc reste à départager. Rien ne démontre une
|
|
|
|
|
|
impossibilité de WebRTC sur Android ou une défaillance du ChatHub.
|
|
|
|
|
|
|
|
|
|
|
|
Les essais Browser/GStreamer réussis utilisaient des sources synthétiques
|
|
|
|
|
|
et un décodage sans affichage côté GStreamer : ils ne valident pas
|
|
|
|
|
|
PostIt.Desktop Linux, ses périphériques réels ou son rendu Avalonia.
|
|
|
|
|
|
La validation multi-plateforme demeure incomplète.
|