Aller au contenu
Documentation
Télécharger
Français

État et événements

Sound Show transmet l’état du spectacle après authentification et à chaque changement. Construisez votre contrôleur à partir de ces instantanés et utilisez la référence des commandes pour demander des modifications.

Un message state remplace tout l’état local. Il arrive automatiquement après hello_ok, après des changements généraux ou de projet, et en réponse à request_state. Cet exemple réduit montre les champs principaux ; les vrais projets ont des tableaux remplis et des métadonnées supplémentaires.

{
"type": "state",
"protocol_version": 2,
"server_time_ms": 1712345678901,
"state": {
"project": { "name": "My show", "categories": [] },
"players": [],
"playable_runtime": [],
"playlists": { "current_index": 0, "playlists": [] },
"instructions": { "current_index": 0, "players": [] },
"timers": [],
"logical_devices": [],
"control": {
"next_sound_volume": 70,
"selected_category_id": null,
"low_volume_active": false,
"volume_level_presets": [],
"active_volume_level_ids": [],
"effective_volume_level_id": null
},
"capabilities": { "audio_controls": [], "manual_grid_layout": false },
"audio_controls": { "revision": 1, "logical_devices": [], "players": [] },
"lights": { "revision": 1, "lights": [] }
}
}

Gérez un projet absent ou null, les tableaux vides, les champs facultatifs et les nouveaux champs inconnus. Ces pages décrivent la v2 actuelle. Une ancienne version de Sound Show 2 peut proposer moins de champs, commandes ou fonctions ; vérifiez hello_ok.features et les capacités avant d’utiliser une fonction facultative.

Instantanés de domaine en direct

Section « Instantanés de domaine en direct »

Après l’état complet, la plupart des mises à jour remplacent un seul domaine, une partie nommée de l’état. Un tableau vide a un sens : players: [] efface les lecteurs courants. Ne fusionnez pas les entrées avec l’ancienne liste.

type du message Champ local à remplacer Envoi
control_snapshot control Réponses directes aux commandes de niveau ; changements des contrôles de tous les opérateurs avec runtime_snapshots.
players_snapshot players Changements des lecteurs.
instructions_snapshot instructions Avec runtime_snapshots.
playlists_snapshot playlists Avec runtime_snapshots.
playable_runtime_snapshot playable_runtime Avec runtime_snapshots.
logical_devices_snapshot logical_devices Changements des sorties.
timers_snapshot timers Changements des minuteries.
audio_controls_snapshot audio_controls Changements des effets ; comparer revision.
lights_snapshot lights Changements des lumières ; comparer revision.

Chaque message de domaine contient le champ de données du même nom et server_time_ms. Exemple :

{
"type": "players_snapshot",
"players": [],
"server_time_ms": 1712345678901
}

Les messages de contrôles audio et de lumières ont aussi une révision de domaine :

{
"type": "audio_controls_snapshot",
"revision": 5,
"audio_controls": { "revision": 5, "logical_devices": [], "players": [] },
"server_time_ms": 1712345678901
}

Pour ces deux domaines, ignorez une révision inférieure à celle déjà appliquée au domaine. Ne comparez pas les révisions entre domaines. Un state complet réinitialise la référence ; effacez tout l’état local et les révisions à la déconnexion. Appliquez les autres domaines dans l’ordre de réception.

Demandez runtime_snapshots dans hello.features. Sans cela, les changements de contrôles, instructions et listes utilisent des états complets regroupés, sauf les réponses directes aux contrôles. Une modification de la seule activité des éléments ne déclenche pas d’état complet pour ces clients.

Les changements d’exécution sont regroupés par cycles de 50 ms. Cela ne garantit ni un message toutes les 50 ms ni un journal de chaque modification intermédiaire. Un état complet peut remplacer des mises à jour de domaine en attente. Voir le traitement de tous les instantanés actuels dans l’exemple JavaScript.

Pour… Utiliser…
Déclencher un bouton de projet project.categories[].playables[].id comme playable_id.
Sélectionner une catégorie project.categories[].id comme category_id.
Arrêter, mettre en pause, déplacer ou régler une instance active players[].id comme player_id.
Contrôler une sortie logical_devices[].id comme logical_device_id.
Activer un préréglage de volume control.volume_level_presets[].id comme level_id.
Régler un effet id du descripteur comme control_id, avec une cible lecteur ou périphérique logique actuelle.
Régler une lumière lights.lights[].id comme project_light_id.
Lire un élément de liste Positions actuelles de liste et de file, à partir de zéro.
Sélectionner une instruction Position actuelle du lecteur d’instructions, à partir de zéro, et path de l’élément.
Contrôler une minuterie Sa position actuelle à partir de zéro comme timer_index.

Les ID de lecteur décrivent des instances actives, pas une identité permanente de projet à conserver. Un élément peut avoir plusieurs lecteurs. Recherchez les source_playable_id ou state_playable_id correspondants dans l’instantané courant et choisissez explicitement l’instance voulue. Les noms servent à l’affichage, mais ne sont pas forcément uniques.

project.categories[] contient, pour les catégories, id, name, color, is_hidden, le champ facultatif icon_url et playables. Un élément comprend :

{
"id": "playable-id",
"name": "Wind",
"kind": "sound",
"color": "#3b82f6",
"tags": [],
"is_searchable": true,
"runtime_state_key": "playable-id",
"target_category_id": null
}

Les types courants sont sound, video, image, random, timer, playlist, action, webbrowser, category_link et instruction. Acceptez aussi les types nouveaux ou unsupported. Les métadonnées facultatives comprennent icon_url, les raccourcis clavier et les identifiants d’actions au clic configurées.

playable_runtime contient des entrées avec state_playable_id, play_count, is_locked et is_playing. Faites correspondre le runtime_state_key d’un élément, ou son id si le champ manque, à state_playable_id. Les éléments liés peuvent partager activité et verrouillage. Ce verrouillage du bouton de projet diffère du verrouillage des contrôles d’un lecteur actif.

Les catégories peuvent avoir un grid_layout facultatif avec enabled, columns, rows, pages, positions et revision. Vérifiez capabilities.manual_grid_layout avant de l’utiliser. Un client peut ignorer ces données et afficher la liste ordinaire ; aucune commande distante ne modifie la disposition.

{
"id": "runtime-player-id",
"kind": "sound",
"title": "Wind",
"color": "#3b82f6",
"panel_position": 0,
"position_seconds": 12.3,
"duration_seconds": 95,
"start_time_seconds": 5,
"stop_time_seconds": 90,
"timeline_duration_seconds": 95,
"volume_percent": 70,
"muted": false,
"is_playing": true,
"is_locked": false,
"loop_enabled": true,
"output_logical_device_id": "main",
"source_playable_id": "playable-id",
"state_playable_id": "playable-id"
}

Affichez directement volume_percent. Le champ brut distinct volume, s’il existe, n’est pas un pourcentage à multiplier par 100 ; l’application peut utiliser une échelle non linéaire.

Les champs de timeline sont en secondes. start_time_seconds, stop_time_seconds et timeline_duration_seconds peuvent manquer ou valoir null. Utilisez-les pour relier la fenêtre rognée à la timeline source lors d’un déplacement. Autres champs facultatifs : remaining_playback_seconds, markers et icon_url.

Sorties et contrôles partagés

Section « Sorties et contrôles partagés »

logical_devices[] fournit id, label, display_label, color, output_role, available, selected et volume_percent. Utilisez display_label pour l’affichage et id pour les commandes.

control expose le volume du prochain déclenchement, la catégorie sélectionnée, volume_level_presets, active_volume_level_ids et effective_volume_level_id. Les préréglages contiennent id, name, direction (both, up_only ou down_only), target_volume_percent, fade_down_ms et fade_up_ms. low_volume_active sert aux anciens contrôleurs. Lisez les ID actifs dans l’instantané : d’autres opérateurs peuvent aussi les modifier.

Listes de lecture, instructions et minuteries

Section « Listes de lecture, instructions et minuteries »
Domaine Champs utiles
playlists current_index et playlists[]. Chaque liste a id, title, autoplay, loop_enabled et queue. Les éléments de file ont playable_id, title et éventuellement icon_url. Les métadonnées d’exécution peuvent inclure active_item_id, active_item_title et active_player_id.
instructions current_index et players[]. Les lecteurs ont id, title, has_instruction, waiting_for_go, next_instruction_text et items. Les éléments exposent item_id, title, kind, depth, path, can_set_next, is_next_to_play et is_visibly_playing.
timers Tableau avec id numérique, mode, is_running, is_locked, elapsed_ms, duration_ms, remaining_ms et is_over_time. Les durées sont en millisecondes.

Pour prévisualiser GO, préférez l’élément suivant le plus profond avec un path non vide et un kind différent de group ; à défaut, prenez n’importe quel élément suivant le plus profond. Pour sélectionner le suivant, utilisez son vrai path, pas un chemin déduit du titre ou de la profondeur.

Contrôles audio et capacités

Section « Contrôles audio et capacités »

capabilities.audio_controls[] décrit les contrôles d’effets disponibles. Chaque descripteur fournit :

Champ Sens
id, label Identifiant du protocole et libellé d’affichage.
scopes Types de cible pris en charge : logical_device et/ou player.
min, max, default_value Bornes natives et valeur de réinitialisation.
suggested_step Pas de réglage suggéré.
unit, scale Unité d’affichage et échelle. log2 exprime les pas en octaves.
display_multiplier Multiplier les valeurs natives pour l’affichage ; diviser la saisie par ce facteur avant l’envoi.

Par exemple, un rapport de 0.5 avec display_multiplier: 100 s’affiche comme 50%. Utilisez le catalogue annoncé plutôt que des plages codées en dur.

audio_controls contient revision, logical_devices[] et players[]. Chaque cible a kind, id, label, available, locked et un objet values associant les ID de contrôle aux valeurs natives. Les contrôles linéaires évoluent linéairement ; les contrôles log2, géométriquement.

lights contient revision et lights[]. Chaque lumière a id, name, capability (actuellement level) et available. Son value_percent est omis si l’adaptateur est indisponible. Affichez cette indisponibilité sans l’interpréter comme zéro.

Les entrées peuvent inclure un icon_url relatif et opaque, comme /asset/file?id=opaque-asset-id. Résolvez-le par rapport à l’adresse HTTP du serveur distant et récupérez-le en HTTP. Les icônes ne sont pas des messages WebSocket.

Utilisez l’URL fournie sans fabriquer d’identifiants ni envoyer de chemins de fichier. Mettez les icônes en cache pour la session courante ; leurs ID peuvent changer après redémarrage. Un changement de projet peut rendre une ressource indisponible : prévoyez une image de remplacement. Les instantanés n’exposent pas les chemins locaux.

Une connexion authentifiée peut recevoir :

{
"type": "error",
"code": "invalid_value",
"command_id": "eq-change-1",
"message": "Human-readable error description"
}

code et command_id sont facultatifs. Les erreurs audio/lumière comprennent unknown_control, target_locked, target_not_found, invalid_value, target_unavailable ou command_failed. Les anciens traitements peuvent ne renvoyer que message. N’interprétez pas le texte lisible comme un code stable. Une erreur peut laisser la connexion ouverte ; continuez à traiter les instantanés.

Limite Comportement du client
Premier message dans les 10 secondes Envoyer hello dès l’ouverture.
16 connexions WebSocket simultanées Réutiliser les connexions et fermer les clients inutilisés. Les sockets non authentifiés comptent aussi.
64 KiB par message ou trame entrant Une petite commande JSON par message.
Rafale de 60 commandes, renouvelée à 20 par seconde par connexion Limiter les curseurs et regrouper les valeurs en attente. Ping et rafraîchissement consomment aussi ce quota.
Cinq mauvais mots de passe depuis une adresse en 60 secondes Corriger le mot de passe et attendre : les nouvelles ouvertures WebSocket sont bloquées pendant 60 secondes avec HTTP 429 et Retry-After.

Une commande refusée par la limite de débit n’est pas appliquée et renvoie code: "rate_limited". Un excès prolongé peut fermer la connexion. Respectez Retry-After lorsque le client expose la réponse HTTP. Si le navigateur ne signale qu’un échec après des erreurs d’authentification répétées, attendez au moins 60 secondes. Ne réessayez pas aveuglément une lecture, une bascule ou GO : cela pourrait provoquer une deuxième action.

Si hello_ok.features contient ping, un client authentifié peut envoyer {"type":"ping"} et attendre {"type":"pong"}. La télécommande intégrée envoie un ping toutes les dix secondes et, à cette vérification, se reconnecte si aucun message valide n’a été reçu depuis plus de 25 secondes. Les domaines inchangés peuvent sinon rester silencieux.

Pour un contrôleur permanent :

  1. Désactivez l’envoi dès la fermeture du socket ou l’échec de la surveillance.
  2. Effacez l’état en cache, les ID des lecteurs et le suivi des révisions.
  3. Reconnectez-vous avec un délai plafonné qui augmente après les échecs. Respectez les erreurs d’authentification et limites de débit.
  4. Envoyez un nouveau hello, attendez le nouvel état complet state et retrouvez les cibles.
  5. Réactivez les contrôles à partir de cet état. Ne rejouez pas les déclenchements, bascules ou GO en attente après reconnexion.

Les maintiens de volume liés à la connexion sont libérés à sa fermeture. Considérez la reconnexion comme une nouvelle session, même si l’adresse du serveur n’a pas changé.

Modifier Autoriser les origines externes dans Sound Show s’applique immédiatement et déconnecte les clients. Une fois désactivé, les navigateurs d’autres origines ne peuvent plus se reconnecter. Voir les télécommandes web personnalisées pour la configuration et les restrictions du navigateur.