从工作表到屏幕
- 从模板开始。将模板保存为 CSV 或 XLSX,或使用列相同的自有工作表。
- 每条排程填一行。写明屏幕(或文件夹、标签)、文件、开始和结束。
- 导入。将文件拖到仪表板排程标签页的导入对话框,或运行
screenrig schedule import FILE。 - 更正有错误的行。每个错误都指明行、列和代码。在对话框中编辑单元格,或编辑工作表后重新导入。
- 检查预览。列出工作表生成的层级、它更改或移除的层级,以及它涉及的屏幕的日历。
- 发布。所有行一起应用,或都不应用。
第 1 到 5 步不写入任何内容。屏幕需要时区(screen set-timezone)和默认播放列表(screen assign),行才能为其排程,且文件必须是已批准的图像或视频。
工作表
第一行为列名。之后每一行是一条排程。空行会被跳过。工作表是 CSV 文件(UTF-8,逗号或分号分隔)或 XLSX 工作簿,XLSX 工作簿读取其第一个工作表。
| 列 | 也读作 | 包含内容 |
|---|---|---|
target | screen, screen code, code, room, room id, screen name, screen id | 该行排程的屏幕。必填 |
content | file, file name, media, asset, playlist | 播放的内容。必填 |
start | start date, from, begin | 该行开始的时间 |
end | end date, until, stop | 该行结束的时间 |
timezone | time zone, tz | 该行时间所用的时区 |
days | weekdays, day | 该行播放的星期 |
daily start | window start, time from | 每个播放窗口开启的时刻 |
daily end | window end, time to | 每个播放窗口关闭的时刻 |
priority | 0 到 100。高的优先于低的播放。默认 0 | |
name | level, label | 该行生成的层级的名称 |
display | displays, output | 该行播放所在的视频墙输出,如 1 或 1,2 |
表头匹配时忽略大小写、空格和标点。没有任何内容读取的列会被忽略,预览会列出它。一行需要 target、content,以及 start、end、days 或每日时间窗口中的至少一项。
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,
- 第 2 行在代码为
LOBBY-01的屏幕上播放welcome-spring.jpg,从 11 月 5 日下午 6 点到 11 月 8 日凌晨 2 点,太平洋时间。 - 第 3 行在文件夹
Casino Floor及其内部文件夹的每个屏幕上播放happy-hour.mp4,工作日下午 4 点到 7 点,从 11 月 5 日到 11 月 30 日结束。 - 第 4 行在带标签
elevators的每个屏幕上播放播放列表Holiday loop,从 12 月 1 日上午 9 点到 12 月 25 日结束。
目标
目标可以是以下之一:
- 屏幕。屏幕 id、屏幕任意字段的值(房间代码、门店编号)或屏幕名称。
--code-field或code_field将匹配限制在一个字段,如code或room_id。 - 文件夹。
folder:NAME或folder:Parent/Child。覆盖该文件夹及其内部的每个文件夹。 - 标签。
tag:NAME覆盖带该标签的每个屏幕。
一个单元格中的多个目标用 ; 或 | 分隔,如 LOBBY-01;LOBBY-02|tag:elevators。
内容
- 文件。项目中某个媒体文件的名称,或转换后上传文件的原始文件名。文件全屏播放。首次提交使用某文件时,会创建单文件播放列表
Scheduled: FILE,之后的导入复用它。 - 播放列表。
playlist:NAME或播放列表 id。该播放列表有已批准的版本,且不是模板。
时间
- 日期和时间。读取
2026-11-05 18:00、2026-11-05T18:00、11/5/2026 6:00 PM和电子表格日期单元格。带偏移量的时间(如Z或+02:00)会被拒绝。 - 每个屏幕自己的时钟。时间按该行涉及的屏幕的时钟读取,所以无论屏幕在哪里,
18:00都是下午 6 点。 - 其他时区。
timezone单元格(或请求的timezone)表示该行按该时区书写。当该行的所有屏幕共用一个时区时,时间会转换为屏幕的时区。覆盖多个时区屏幕的行会让timezone为空,并按每个屏幕自己的时钟读取。 - 只有日期的结束时间在当天结束时关闭:
2026-11-30在 11 月 30 日结束时结束。只有日期的开始时间从午夜开始。 - 没有结束时间会让该行一直播放,直到之后的导入将其移除。预览以
open_end警告。 - 星期。
Mon-Fri、Mon,Wed,Fri、Sat,Sun、weekdays、weekends或daily。带days但没有每日时间窗口的行,在这些日子全天播放。 - 每日时间窗口。
daily start和daily end给出每天的时段,如16:00和19:00或4:00 PM和7:00 PM。两者都要填。结束时间等于或早于开始时间时跨越午夜,并归属于开始的那一天。没有days时,该窗口每天适用。
预览与错误
预览在写入任何内容之前检查每一行和每个单元格。有错误的行连同其单元格一起显示,每个错误指明列、代码和要更改的内容。
| 代码 | 列 | 含义与修复 |
|---|---|---|
required | target, content, daily start, daily end | 单元格为空,或每日时间窗口的单元格只填了一个。请填写 |
unknown_screen | target | 没有屏幕具有该 id、字段值或名称。检查代码,或 code_field 指定的字段 |
ambiguous_screen | target | 该值匹配多个屏幕。请使用屏幕 id 或唯一的代码 |
unknown_folder | target | 没有该名称的屏幕文件夹。检查拼写 |
ambiguous_folder | target | 多个文件夹使用该名称。写出路径,例如 folder:Hotel/Casino Floor |
unknown_tag | target | 没有屏幕带有该标签。检查拼写 |
unknown_file | content | 没有该名称的文件或播放列表。上传文件,或更正名称 |
ambiguous_file | content | 多个文件使用该名称。重命名其一,或写 playlist:NAME |
not_playable | content | 文件不是图像或视频,媒体正在等待审核,或播放列表是模板或没有已批准的版本。批准它,或另选一个 |
invalid_time | start, end, daily start, daily end | 单元格不是日期和时间,或带有时区偏移量。写 2026-11-05 18:00 |
reversed_times | end | 结束时间不晚于开始时间。更正其中之一 |
past_end | end | 结束时间已过。改到更晚,或移除该行 |
no_timing | start | 该行没有说明时间。请给出开始、结束、星期或每日时间窗口 |
invalid_value | days, priority, display | 单元格不是星期列表(如 Mon-Fri)、0 到 100 的整数,或显示编号(如 1,2) |
timezone | timezone | 时区未知,或目标包含多个时区的屏幕。请使用如 America/Los_Angeles 的时区,或留空 |
screen_not_ready | target | 屏幕没有时区或默认播放列表。运行 screen set-timezone 或 screen assign |
overlap | priority | 同一屏幕上两行在同一时间以相同优先级生效。给其中一行不同的优先级,或移动一个时间 |
limit | target | 某个屏幕的自有层级将超过 32 个,或组织的活动将超过 100 个(每个共享层级算一个)。合并行,或以文件夹或标签为目标 |
两个警告不会阻止导入。open_end 标记没有结束时间的行。outranked 标记在某屏幕上被共享层级(面向多个屏幕、文件夹或标签的行)覆盖播放的行。
没有行的工作表、不是 UTF-8 的文件、超过 5,000 行、超过 8 MiB 的文件,或会写入超过 400 个屏幕自有排程的提交,会被拒绝并说明原因。
层级
内容、时间、优先级、名称和显示一致的行合并为一个层级。目标不参与比较,所以十行在十个屏幕上于相同时间播放同一文件,只生成一个层级。
- 一个屏幕会在该屏幕自己的排程中生成一个条目。
- 多个屏幕、一个文件夹或一个标签生成一个共享层级,即针对该受众的活动。共享层级优先于屏幕的自有层级。
分组把场馆的 200 个屏幕变成一个活动,而不是 200 个条目,工作表中的一处更正只改变一个层级。name 列指定共享层级。没有时,它以导入、内容和目标命名,如 Spring promos: happy-hour.mp4 on Casino Floor。
再次导入
导入的 name 标识该导入,默认值为 import。以相同名称再次导入:
- 更新它生成的层级,即使行的日期已更改;
- 为新行添加层级;
- 移除工作表中已不存在其行的层级;
- 工作表相同时不改变任何内容。
导入生成的层级在其 id 中带有该导入(屏幕的条目以 imp_ 开头),活动带有 import 标记。你手动创建的层级不会被触碰。一张工作表使用一个名称,另一张使用不同的名称。
运行导入
控制台
打开项目的排程标签页并选择导入。拖入 CSV 或 XLSX 文件。对话框以表格显示各行,每个错误显示在其单元格旁,你可以就地编辑单元格。然后显示导入所改变屏幕的合成日历。发布即提交。
命令行
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 只预览,不写入任何内容。当每一行都有效时,--commit 应用工作表。
| 选项 | 含义 |
|---|---|
--name NAME | 导入名称,1 到 80 个字符。默认值为不带扩展名的文件名 |
--timezone ZONE | 行没有 timezone 时,时间所用的时区 |
--code-field FIELD | 只从此屏幕字段读取屏幕代码 |
--commit | 应用工作表 |
--format csv|xlsx | schedule template:模板的格式 |
--output FILE | schedule template:保存位置 |
命令对有效的工作表以 0 退出,行有错误时以 8 退出(不写入任何内容),预览之后项目已更改时以 5 退出(再次运行)。FILE 是 .csv、.xlsx 或 .json 文件,或用 - 表示标准输入。JSON 文件保存行对象数组,或 {"rows": [...]},以列名为键。
API
以 JSON 行发送工作表,或以 CSV 或 XLSX 请求体发送并用查询参数传设置。预览需要读权限。提交需要具有写权限的凭据,由能在仪表板中批准的人员授予。
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"}
]
}'
同一张工作表作为文件:
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
应答(节选):
{
"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 按工作表给出的原样返回每行的单元格,客户端据此更正后再次发送这些行。没有任何行有错误时,valid 为 true。calendar 的结构与 GET /api/schedule/calendar 相同,显示导入在提交后屏幕会变成的样子。
提交发送同一张工作表及其预览的 fingerprint,作为 JSON 请求体的成员,或在发送文件时作为查询参数。发送 Idempotency-Key 可安全重试。
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
应答包含 preview 和 applied、已创建、已更新、未更改和已移除的计数,以及已写入的屏幕和已创建的播放列表。提交会被拒绝且不写入任何内容,原因为:
| 问题 | 状态 | 含义与修复 |
|---|---|---|
schedule_import_invalid | 422 | 有行存在错误。更正后再次预览 |
schedule_import_stale | 409 | 屏幕、媒体、播放列表或层级自预览后已更改,或各行的读取结果不同。再次预览,并使用新的指纹提交 |
GET /api/schedule/imports/template?format=csv 和 format=xlsx 返回模板。
限制
- 每个工作表最多 5,000 行和 8 MiB。
- 每个屏幕 32 个自有层级。一个组织在其所有项目中最多有 100 个活动,每个共享层级算一个。
- 每次提交最多写入 400 个屏幕的自有排程。一个文件夹或标签行可覆盖任意数量的屏幕。
- 导入名称为 1 到 80 个字符。