Il semble que sur l’application mobile, on ne puisse que créer des salles, mais en cliquant directement sur une salle déjà créée, on ne peut pas y accéder. Cependant, si on accède directement à /resenha/r/topic, cela fonctionne. Est-ce un bug ?
Ça fonctionne très bien sur mon téléphone. As-tu mis à jour ton instance Discourse cette semaine ?
Les plugins expérimentaux nécessitent des mises à jour fréquentes.
Beaucoup de mises à jour ce mois-ci, mais la principale est le support optionnel et par salle de SFU via LiveKit.
Le WebRTC P2P complet reste le transport principal et par défaut, mais le SFU est désormais également pris en charge pour les personnes qui doivent gérer des centaines de participants dans une seule salle.
Nous avons également apporté de nombreuses améliorations, comme des sélecteurs d’appareils audio et vidéo dans les contrôles de salle et de widget, la possibilité de mentionner les salles Resenha via l’auto-complétion # dans les chats et les publications, des options de mise en page des salles, et plus encore.
Merci pour cela, la SFU était le véritable élément manquant. C’est ce qui m’avait initialement poussé à maintenir un fork séparé ; maintenant qu’elle est prise en charge en amont, je peux mettre fin à ce fork et suivre directement resenha.
J’avais hésité à vous poser des questions sur LiveKit car je ne savais pas si vous souhaitiez aller dans cette direction. Maintenant que c’est le cas : êtes-vous ouvert aux PR pour de nouvelles fonctionnalités et de petites améliorations ?
@Falco Salut, j’ai rencontré quelques problèmes reproductibles lors des tests de la version mise à jour de Resenha. Je partage mes observations ainsi que les correctifs que j’applique localement, au cas où ils seraient utiles pour le projet en amont.
1. L’interface admin ignore silencieusement room_type : les salles de type “stage” ne peuvent jamais conserver ce statut
app/controllers/resenha/admin_rooms_controller.rb:65 (room_params) omet :room_type de la liste des paramètres autorisés, et admin_room_serializer.rb ne le sérialise jamais.
Toute attribution de type “stage” effectuée via l’interface admin est ignorée ; les salles sont créées en mode “ouvert” et “repassent” en mode “ouvert” lors de toute modification ultérieure via l’admin. Confirmé via les logs de production ; le contrôleur côté utilisateur l’autorise, seul le chemin admin le perd.
# admin_rooms_controller.rb — ajouter :room_type à la liste des paramètres autorisés, puis :
if permitted.key?(:room_type)
value = Resenha::Room::ROOM_TYPES[permitted[:room_type].to_s]
raise Discourse::InvalidParameters.new(:room_type) if value.nil?
permitted[:room_type] = value
end
# admin_room_serializer.rb — sérialiser room_type afin que le formulaire s'initialise correctement
2. Un room_type invalide bascule silencieusement sur “ouvert”
app/controllers/resenha/rooms_controller.rb:575 — ROOM_TYPES[...] || ROOM_TYPE_OPEN.
Tout room_type malformé ou obsolète dans une modification de salle par ailleurs valide transforme silencieusement une salle de type “stage” en salle “ouverte”. Renvoyer une erreur 400 permet de rendre visible l’appelant fautif plutôt que de corrompre la salle.
value = Resenha::Room::ROOM_TYPES[permitted[:room_type].to_s]
raise Discourse::InvalidParameters.new(:room_type) if value.nil?
permitted[:room_type] = value
3. Le heartbeat réanime un utilisateur qui vient de quitter (présence fantôme)
rooms_controller.rb:234 (heartbeat) réajoute la présence sans condition, donc si un heartbeat est en cours d’exécution lorsque leave (:220) est traité en second, il recrée l’utilisateur parti.
Le fantôme persiste jusqu’à la suppression par expiration du TTL, qui n’est pas diffusée — les clients l’affichent “dans la salle” pendant jusqu’à une minute.
Reproduit sur appareil ; le “kick” présente la même vulnérabilité.
# ParticipantTracker : marqueur de suppression de 15s
def mark_left(room_id, user_id) = redis.setex(left_key(room_id, user_id), 15, "1")
def recently_left?(room_id, user_id) = redis.exists?(left_key(room_id, user_id))
# leave/kick → mark_left ; join/livekit_token → clear_left ; heartbeat :
return head :no_content if Resenha::ParticipantTracker.recently_left?(@room.id, current_user.id)
4. Un webhook participant_left obsolète “kick” une session fraîche
livekit_webhooks_controller.rb:37/57 — les départs sont appariés uniquement par l’identité de l’utilisateur.
En cas de déconnexion/reconnexion rapide, le participant_left de la session remplacée arrive en retard et expire la présence de la nouvelle session (l’utilisateur est “kické” ~3s après la reconnexion, puis revient ~15s plus tard).
Reproduit sur appareil ; l’heuristique gone_at ne peut pas distinguer les sessions lorsque la reconnexion précède la déconnexion de l’ancienne session.
# participant_joined → enregistrer le SID actif
Resenha::ParticipantTracker.set_livekit_sid(room.id, user_id, event.dig("participant", "sid"))
# expire_participant → ignorer le départ d'une session remplacée
known = Resenha::ParticipantTracker.livekit_sid(room.id, user_id)
return if sid.present? && known.present? && sid != known
5. DeleteRoom 404 après le dernier départ inonde les logs
lib/resenha/livekit/room_service_client.rb:84 avertit sur toute réponse non-200.
Le SFU ferme automatiquement une salle dès qu’elle est vide, donc le DeleteRoom du dernier départ entre souvent en concurrence avec cette fermeture — “la salle demandée n’existe pas” est l’état final attendu, et non une erreur.
Cela apparaît dans Logster à chaque dernier départ.
elsif method == "DeleteRoom" && response.status == 404
Rails.logger.debug("[resenha-livekit] DeleteRoom no-op pour la salle #{room.id} : déjà fermée")
true
Je peux envoyer une pull request si vous le souhaitez.
Comme je l’ai dit précédemment, je ne connais pas votre direction dans son intégralité, mais vous pouvez jeter un œil à la mienne, car j’ai publié un message ici → Discourse Desktop Mac App - #10 by nicolsdennis
Ce serait absolument génial : cela aurait tout à fait de sens de l’intégrer au mécanisme de diffusion en direct, ce qui fournirait le canal de chat associé dans le cadre d’une expérience intégrée et élégante.
Salut, lorsque je change le nom de la salle, le slug ne se met pas à jour. De plus, je ne peux pas supprimer de salles — j’obtiens une erreur serveur.
Il serait aussi sympa de pouvoir modifier visuellement l’ordre des salles et leur apparence.
Merci pour ce rapport détaillé, j’ai juste fusionné une PR pour cela :
J’ai remarqué quelques petits problèmes d’interface et d’expérience utilisateur liés aux salons vocaux privés :
1. L’icône micro de verrouillage/privé est trop petite.
C’est génial d’avoir une icône indiquant le statut de confidentialité d’un salon ; malheureusement, elle est trop petite et se superpose beaucoup à l’icône. De plus, elle n’est pas cohérente avec le reste de la barre latérale :
![]()
2. La liste des participants est difficile à trouver
On ne peut accéder à la liste des participants d’un salon vocal privé qu’à partir de l’appel en cours.
Ce n’est pas très intuitif. Je m’attendais à pouvoir modifier les participants/invités depuis les paramètres disponibles lorsque le salon vocal est inactif. Il y a plein de paramètres disponibles lorsqu’il est inactif (y compris public vs privé, nombre maximal de participants, etc.), mais pas la liste des participants proprement dite.
J’ai apporté des correctifs pour les deux, merci pour le rapport @nathank !
Je me demande s’il est possible de lier une salle spécifique depuis les liens href. Je souhaite ajouter un raccourci vers une seule salle de test pour simplifier notre UX.
Oui, c’est désormais possible dans ce format
Il convient également de souligner les améliorations récentes :
Prise en charge des serveurs STUN/TURN privés via l’authentification coturn
Cela vous permet de garder votre instance coturn restreinte à votre usage, et sa configuration est très simple grâce à un secret partagé entre Discourse et Coturn.
Prise en charge de l’enregistrement des sessions lors de l’utilisation de LiveKit
Tout cela est accessible via l’interface d’appel : un seul clic pour démarrer l’enregistrement, un seul clic pour l’arrêter.
Prise en charge des drapeaux pour les participants aux appels
Bien que le drapeau manque de contexte, les utilisateurs peuvent le fournir via la zone de texte.
Menu clic droit sur les vignettes vidéo
Permet de régler facilement le volume d’un participant, ou de l’expulser, etc.
Option pour une qualité supérieure de la voix, de la vidéo et du partage d’écran
Ma fonctionnalité préférée de la semaine : elle permet aux utilisateurs d’opter pour des limites de débit bien plus élevées, offrant ainsi une bien meilleure qualité audio/vidéo.
S’agit-il de mon instance ou y a-t-il probablement quelque chose à examiner ? Je reçois une erreur 500 lorsque j’essaie de supprimer des salons vocaux depuis le panneau d’administration :
ActiveRecord::InvalidForeignKey (PG::ForeignKeyViolation: ERROR: update or delete on table "resenha_rooms" violates foreign key constraint "fk_rails_ID" on table "resenha_sessions" DETAIL: Key (id)=(1) is still referenced from table "resenha_sessions".
Merci pour le rapport, la correction a été fusionnée
Merci pour cette correction ultra-rapide ; elle a fonctionné comme prévu.
Juste une petite remarque pour la suite : la modification du nom de la salle par défaut n’a pas mis à jour le chemin /resenha/r/watercooler, mais j’ai pu supprimer l’ancienne salle par défaut et en ajouter une nouvelle.
J’ai maintenant rendu le slug explicitement modifiable, de sorte qu’il fonctionne comme les catégories
Vous pouvez également ajouter quelques paramètres d’URL pour ouvrir d’une manière spécifique :
https://discourse-on-a-pi5.falco.dev/resenha/r/watercooler?join entre simplement dans la salle, sans bouton « Rejoindre » à cliquer
https://discourse-on-a-pi5.falco.dev/resenha/r/watercooler?join&widget (ajouté plus tôt cette semaine), s’ouvre et passe en mode widget
https://discourse-on-a-pi5.falco.dev/resenha/r/watercooler?join&chat s’ouvre en mode chat

