De la feuille aux écrans
- Partez du modèle. Enregistrez le modèle en CSV ou XLSX, ou utilisez votre propre feuille avec les mêmes colonnes.
- Remplissez une ligne par ligne d’horaire. Nommez l’écran (ou un dossier ou une étiquette), le fichier, le début et la fin.
- Importez-la. Déposez le fichier dans la boîte de dialogue Importer de l’onglet Horaire du tableau de bord, ou exécutez
screenrig schedule import FILE. - Corrigez les lignes en erreur. Chaque erreur nomme la ligne, la colonne et un code. Modifiez la cellule dans la boîte de dialogue, ou modifiez la feuille et importez-la de nouveau.
- Vérifiez l’aperçu. Il liste les niveaux que la feuille crée, ceux qu’elle modifie ou supprime, et le calendrier des écrans qu’elle touche.
- Publiez. Toutes les lignes s’appliquent ensemble ou aucune ne s’applique.
Les étapes 1 à 5 n’écrivent rien. Un écran a besoin d’un fuseau horaire (screen set-timezone) et d’une liste de lecture par défaut (screen assign) avant qu’une ligne puisse le programmer, et un fichier doit être une image ou une vidéo approuvée.
La feuille
La première ligne nomme les colonnes. Chaque ligne suivante est une ligne d’horaire. Les lignes vides sont ignorées. Une feuille est un fichier CSV (UTF-8, séparé par des virgules ou des points-virgules) ou un classeur XLSX, et un classeur XLSX est lu à partir de sa première feuille.
| Colonne | Lu aussi comme | Contenu |
|---|---|---|
target | screen, screen code, code, room, room id, screen name, screen id | Les écrans que la ligne programme. Requis |
content | file, file name, media, asset, playlist | Ce qui est diffusé. Requis |
start | start date, from, begin | Quand la ligne commence |
end | end date, until, stop | Quand la ligne se termine |
timezone | time zone, tz | Le fuseau dans lequel les heures de la ligne sont écrites |
days | weekdays, day | Les jours de la semaine où la ligne est diffusée |
daily start | window start, time from | L’heure du jour où chaque plage de diffusion s’ouvre |
daily end | window end, time to | L’heure du jour où chaque plage de diffusion se ferme |
priority | De 0 à 100. Une valeur élevée l’emporte sur une valeur basse. Par défaut : 0 | |
name | level, label | Un nom pour le niveau que crée la ligne |
display | displays, output | Les sorties du mur vidéo sur lesquelles la ligne est diffusée, comme 1 ou 1,2 |
Les en-têtes correspondent sans tenir compte de la casse, des espaces et de la ponctuation. Une colonne que rien ne lit est ignorée, et l’aperçu la liste. Une ligne a besoin d’un target, d’un content et d’au moins un parmi start, end, days ou une plage quotidienne.
Screen,File,Start,End,Timezone,Days,Daily start,Daily end,Priority,Name
LOBBY-01,welcome-spring.jpg,2026-11-05 18:00,2026-11-08 02:00,America/Los_Angeles,,,,0,
folder:Casino Floor,happy-hour.mp4,2026-11-05,2026-11-30,,Mon-Fri,16:00,19:00,5,Happy hour
tag:elevators,playlist:Holiday loop,2026-12-01 09:00,2026-12-26,,,,,0,
- La ligne 2 diffuse
welcome-spring.jpgsur l’écran dont le code estLOBBY-01de 18 h le 5 novembre à 2 h le 8 novembre, heure du Pacifique. - La ligne 3 diffuse
happy-hour.mp4sur chaque écran du dossierCasino Flooret des dossiers qu’il contient, de 16 h à 19 h en semaine, du 5 novembre à la fin du 30 novembre. - La ligne 4 diffuse la liste de lecture
Holiday loopsur chaque écran portant l’étiquetteelevators, de 9 h le 1er décembre à la fin du 25 décembre.
Cibles
Une cible est l’une des suivantes :
- Un écran. Un identifiant d’écran, la valeur d’un champ quelconque de l’écran (un code de salle, un numéro de magasin) ou le nom de l’écran.
--code-fieldoucode_fieldlimite la correspondance à un seul champ, commecodeouroom_id. - Un dossier.
folder:NAMEoufolder:Parent/Child. Il atteint le dossier et tous les dossiers qu’il contient. - Une étiquette.
tag:NAMEatteint chaque écran portant l’étiquette.
Plusieurs cibles dans une même cellule sont séparées par ; ou |, comme dans LOBBY-01;LOBBY-02|tag:elevators.
Contenu
- Un fichier. Le nom d’un fichier multimédia du projet, ou le nom de fichier d’origine d’un téléversement converti. Le fichier est diffusé en plein écran. La première validation qui utilise un fichier crée la liste de lecture à fichier unique
Scheduled: FILE, et les importations suivantes la réutilisent. - Une liste de lecture.
playlist:NAMEou un identifiant de liste de lecture. La liste de lecture a une version approuvée et n’est pas un modèle.
Heures
- Dates et heures.
2026-11-05 18:00,2026-11-05T18:00,11/5/2026 6:00 PMet les cellules de date des tableurs sont lues. Une heure avec un décalage commeZou+02:00est refusée. - L’horloge propre à chaque écran. Les heures sont lues sur l’horloge des écrans que la ligne atteint, donc
18:00correspond à 18 h où que l’écran se trouve. - Un autre fuseau. Une cellule
timezone(ou letimezonede la requête) indique que la ligne est écrite dans ce fuseau. Les heures sont converties dans le fuseau des écrans quand tous les écrans de la ligne partagent un même fuseau. Une ligne qui atteint des écrans de plusieurs fuseaux laissetimezonevide et lit l’horloge propre à chaque écran. - Une date seule comme fin ferme ce jour :
2026-11-30se termine à la fin du 30 novembre. Une date seule comme début commence à minuit. - Sans fin la ligne reste diffusée jusqu’à ce qu’une importation ultérieure la supprime. L’aperçu avertit avec
open_end. - Jours.
Mon-Fri,Mon,Wed,Fri,Sat,Sun,weekdays,weekendsoudaily. Une ligne avecdayset sans plage quotidienne est diffusée toute la journée ces jours-là. - Une plage quotidienne.
daily startetdaily enddonnent les heures de chaque jour, comme16:00et19:00ou4:00 PMet7:00 PM. Donnez les deux. Une fin égale ou antérieure au début passe minuit et appartient au jour où elle commence. Sansdays, la plage s’applique tous les jours.
Aperçu et erreurs
L’aperçu vérifie chaque ligne et chaque cellule avant que rien soit écrit. Une ligne en erreur est montrée avec ses cellules, et chaque erreur nomme la colonne, un code et ce qu’il faut changer.
| Code | Colonne | Signification et correction |
|---|---|---|
required | target, content, daily start, daily end | La cellule est vide, ou une seule des cellules de la plage quotidienne est remplie. Remplissez-la |
unknown_screen | target | Aucun écran n’a cet identifiant, cette valeur de champ ni ce nom. Vérifiez le code, ou le champ que nomme code_field |
ambiguous_screen | target | La valeur correspond à plusieurs écrans. Utilisez l’identifiant de l’écran ou un code unique |
unknown_folder | target | Aucun dossier d’écrans ne porte ce nom. Vérifiez l’orthographe |
ambiguous_folder | target | Plusieurs dossiers portent ce nom. Écrivez le chemin, comme folder:Hotel/Casino Floor |
unknown_tag | target | Aucun écran n’a l’étiquette. Vérifiez l’orthographe |
unknown_file | content | Aucun fichier ni aucune liste de lecture ne porte ce nom. Téléversez le fichier, ou corrigez le nom |
ambiguous_file | content | Plusieurs fichiers portent ce nom. Renommez-en un, ou écrivez playlist:NAME |
not_playable | content | Le fichier n’est pas une image ni une vidéo, le média attend un examen, ou la liste de lecture est un modèle ou n’a pas de version approuvée. Approuvez-la, ou choisissez-en une autre |
invalid_time | start, end, daily start, daily end | La cellule n’est pas une date et une heure, ou elle porte un décalage de fuseau. Écrivez 2026-11-05 18:00 |
reversed_times | end | La fin n’est pas après le début. Corrigez l’une ou l’autre |
past_end | end | La fin est passée. Reculez-la, ou retirez la ligne |
no_timing | start | La ligne ne dit rien sur le moment. Donnez un début, une fin, des jours ou une plage quotidienne |
invalid_value | days, priority, display | La cellule n’est pas une liste de jours comme Mon-Fri, un nombre entier de 0 à 100, ou des numéros d’affichage comme 1,2 |
timezone | timezone | Le fuseau est inconnu, ou la cible contient des écrans de plusieurs fuseaux. Utilisez un fuseau comme America/Los_Angeles, ou laissez vide |
screen_not_ready | target | Un écran n’a pas de fuseau horaire ou pas de liste de lecture par défaut. Exécutez screen set-timezone ou screen assign |
overlap | priority | Deux lignes sont en vigueur en même temps sur un écran à la même priorité. Donnez une priorité différente à l’une, ou déplacez une heure |
limit | target | Un écran aurait plus de 32 niveaux propres, ou l’organisation plus de 100 campagnes (chaque niveau partagé en est une). Fusionnez des lignes, ou ciblez un dossier ou une étiquette |
Deux avertissements n’arrêtent pas une importation. open_end marque une ligne sans fin. outranked marque une ligne qu’un niveau partagé (une ligne pour plusieurs écrans, un dossier ou une étiquette) recouvre sur un écran.
Une feuille sans ligne, un fichier qui n’est pas en UTF-8, plus de 5 000 lignes, un fichier de plus de 8 MiB, ou une validation qui écrirait plus de 400 horaires propres d’écrans est refusé avec la raison.
Niveaux
Les lignes qui s’accordent sur le contenu, les heures, la priorité, le nom et l’affichage forment un seul niveau. La cible ne fait pas partie de la comparaison, donc dix lignes qui diffusent le même fichier aux mêmes heures sur dix écrans forment un seul niveau.
- Un écran crée une entrée dans l’horaire propre à cet écran.
- Plusieurs écrans, un dossier ou une étiquette créent un niveau partagé, une campagne sur cette audience. Un niveau partagé l’emporte sur les niveaux propres d’un écran.
Le regroupement transforme les 200 écrans d’un lieu en une seule campagne plutôt qu’en 200 entrées, et une correction dans la feuille modifie un seul niveau. La colonne name nomme un niveau partagé. Sans elle, le niveau porte le nom de l’importation, du contenu et de la cible, comme dans Spring promos: happy-hour.mp4 on Casino Floor.
Importer de nouveau
Le name d’une importation l’identifie, et la valeur par défaut est import. Importer de nouveau sous le même nom :
- met à jour les niveaux qu’elle a créés, même quand les dates d’une ligne ont changé ;
- ajoute les niveaux des nouvelles lignes ;
- supprime les niveaux dont les lignes ont disparu de la feuille ;
- ne change rien quand la feuille est la même.
Les niveaux créés par une importation la portent dans leur identifiant (les entrées d’un écran commencent par imp_) et les campagnes portent une marque import. Les niveaux créés à la main ne sont jamais touchés. Utilisez un nom pour une feuille, et un autre nom pour une autre feuille.
Exécuter une importation
Tableau de bord
Ouvrez l’onglet Horaire d’un projet et choisissez Importer. Déposez un fichier CSV ou XLSX. La boîte de dialogue montre un tableau des lignes avec chaque erreur à côté de sa cellule, et vous modifiez la cellule sur place. Elle montre ensuite le calendrier composé des écrans que l’importation modifie. Publier le valide.
Ligne de commande
screenrig schedule template --output schedule.csv
screenrig schedule import schedule.csv --name "Spring promos" --timezone America/Los_Angeles
screenrig schedule import schedule.csv --name "Spring promos" --timezone America/Los_Angeles --commit
schedule import fait un aperçu et n’écrit rien. --commit applique la feuille quand toutes les lignes sont valides.
| Option | Sens |
|---|---|
--name NAME | Le nom de l’importation, de 1 à 80 caractères. Par défaut, le nom du fichier sans son extension |
--timezone ZONE | Le fuseau dans lequel les heures sont écrites quand une ligne n’a pas de timezone |
--code-field FIELD | Lire un code d’écran seulement dans ce champ d’écran |
--commit | Appliquer la feuille |
--format csv|xlsx | schedule template : le format du modèle |
--output FILE | schedule template : où l’enregistrer |
La commande se termine avec le code 0 pour une feuille valide, 8 quand des lignes ont des erreurs (rien n’est écrit) et 5 quand le projet a changé depuis l’aperçu (exécutez-la de nouveau). FILE est un fichier .csv, .xlsx ou .json, ou - pour l’entrée standard. Un fichier JSON contient un tableau d’objets de ligne, ou {"rows": [...]}, indexés par nom de colonne.
API
Envoyez la feuille sous forme de lignes JSON, ou comme corps CSV ou XLSX avec les réglages en paramètres de requête. L’aperçu demande un accès en lecture. La validation demande des identifiants avec accès en écriture, qu’accorde une personne qui peut approuver dans le tableau de bord.
curl -s https://api.screenrig.ai/api/schedule/imports/preview \
--header "Authorization: Bearer $SCREENRIG_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"name": "Spring promos",
"timezone": "America/Los_Angeles",
"rows": [
{"target": "LOBBY-01", "content": "welcome-spring.jpg", "start": "2026-11-05 18:00", "end": "2026-11-08 02:00"},
{"target": "folder:Casino Floor", "content": "happy-hour.mp4", "start": "2026-11-05", "end": "2026-11-30",
"days": "Mon-Fri", "daily_start": "16:00", "daily_end": "19:00", "priority": 5, "name": "Happy hour"}
]
}'
La même feuille en fichier :
curl -s "https://api.screenrig.ai/api/schedule/imports/preview?name=Spring%20promos&timezone=America/Los_Angeles" \
--header "Authorization: Bearer $SCREENRIG_TOKEN" \
--header "Content-Type: text/csv" \
--data-binary @schedule.csv
La réponse, abrégée :
{
"name": "Spring promos",
"valid": false,
"fingerprint": "FINGERPRINT",
"columns": ["target", "content", "start", "end", "days", "daily_start", "daily_end", "priority", "name"],
"summary": {"rows": 2, "rows_with_errors": 1, "levels": 1, "creates": 1, "updates": 0,
"unchanged": 0, "removes": 0, "screens": 1, "playlists": 1},
"rows": [
{"row": 2, "status": "ok", "level": "LEVEL_KEY"},
{"row": 3, "status": "error",
"errors": [{"column": "content", "code": "unknown_file",
"message": "No file or playlist is named \"happy-hour.mp4\"."}]}
],
"levels": [{"key": "LEVEL_KEY", "action": "create", "home": "screen", "screen_id": "scr_LOBBY",
"content": {"kind": "file", "id": "med_WELCOME", "name": "welcome-spring.jpg"},
"screens": 1, "priority": 0, "from": "2026-11-05T18:00", "until": "2026-11-08T02:00", "rows": [2]}],
"removals": []
}
rows[].cells renvoie les cellules de chaque ligne telles que la feuille les a données, pour qu’un client les corrige et renvoie les lignes. valid est true quand aucune ligne n’a d’erreur. calendar a la forme de GET /api/schedule/calendar et montre les écrans que l’importation modifie tels qu’ils seraient après une validation.
La validation envoie la même feuille et le fingerprint de son aperçu, comme membre du corps JSON ou comme paramètre de requête avec un fichier. Envoyez un Idempotency-Key pour réessayer sans risque.
curl -s https://api.screenrig.ai/api/schedule/imports \
--header "Authorization: Bearer $SCREENRIG_TOKEN" \
--header "Idempotency-Key: spring-promos-1" \
--header "Content-Type: application/json" \
--data @commit.json
La réponse contient preview et applied, les décomptes de ce qui a été créé, mis à jour, laissé inchangé et supprimé, avec les écrans écrits et les listes de lecture créées. Une validation est refusée, sans rien écrire, comme suit :
| Problème | Statut | Signification et correction |
|---|---|---|
schedule_import_invalid | 422 | Des lignes contiennent des erreurs. Corrigez-les et refaites un aperçu |
schedule_import_stale | 409 | Des écrans, médias, listes de lecture ou niveaux ont changé depuis l’aperçu, ou les lignes se lisent autrement. Refaites un aperçu et validez avec la nouvelle empreinte |
GET /api/schedule/imports/template?format=csv et format=xlsx répondent au modèle.
Limites
- 5 000 lignes et 8 MiB par feuille.
- 32 niveaux propres par écran. Une organisation contient jusqu’à 100 campagnes, tous projets confondus, et chaque niveau partagé en est une.
- 400 horaires propres d’écrans écrits par validation. Une ligne de dossier ou d’étiquette atteint un nombre quelconque d’écrans.
- Un nom d’importation compte de 1 à 80 caractères.