Communitygithub.com

timerise-ai/digital-signage

Agent技能:构建数字标牌模块 —— 媒体库、每屏播放列表、显示屏注册、PIN码和配置URL设备配对、支持失速恢复的全屏TV播放器、屏幕健康监控和远程控制 —— 基于Next.js App Router和Firestore或Supabase。

digital-signage 是什么?

该技能提供了一个完整的数字标牌模块,专为在实体场所运行无人值守屏幕而设计,适用于Next.js App Router与Firestore或Supabase/Postgres后端。核心架构强调健壮性和低成本运维:设备通过30-60秒的轮询获取播放列表和内容,而非实时流,以应对廉价电视棒和不稳定的网络环境;播放列表直接存储在显示屏的`adIds`数组中,避免复杂关联查询;媒体上传从浏览器直接到对象存储,绕过API路由以节省计算资源。技能覆盖了从管理员CRUD操作、显示注册与配对(PIN码或配置URL)、全屏播放器循环(含图片加载超时、视频卡住恢复、故障跳过)到运维层(心跳健康检查、远程控制、紧急接管)的完整流程。它还提供一系列硬性规则和架构决策(如永不从渲染状态派生轮询间隔、永不将暂停和删除重载为同一个布尔值、为每个屏幕签发独立的可撤销令牌等),以确保系统在长时间无监督运行中保持可靠。整个技能以模块化方式提供,包含适配指南、数据模型设计、后端实现(Firestore和Supabase双版本)、API路由、配对流程、播放器运行时、管理后台UI以及运维功能等详细参考资料。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add timerise-ai/digital-signage

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

数字标牌 —— 显示屏与广告

实体场所的屏幕不是网页。它在廉价的电视棒上无人值守运行数月,没人盯着控制台,故障模式是一帧画面冻结一周而无人察觉。下面的每一个决策都是为了应对这种情况而存在的。

此技能包含一个完整模块:媒体和播放列表的管理员CRUD、显示屏注册、PIN码和配置URL配对、全屏播放器,以及使其可管理的运维层(健康监控、预览、远程控制)。

何时使用

在实体空间中构建或扩展循环播放媒体的屏幕,基于Next.js App Router和Firestore或Supabase/Postgres。

何时不使用

  • Web广告投放(展示量、竞价、跟踪像素、第三方标签)—— 这是不同的问题,需要不同的基础设施。
  • 交互式信息亭,用户通过点击进行交易。标牌是单向的。
  • 营销页面上的单个嵌入视频。使用<video>标签即可。
  • 通用的Next.js、CMS或身份验证设置 —— 假定这些已存在。

架构

 管理员(浏览器)                    服务器                        设备(电视)
 ─────────────────                  ──────                       ───────────
 媒体上传 ──────────────► 对象存储 ◄──── 公开/签名URL ─┐
 广告CRUD ─────────┐                                                 │
 播放列表编辑 ───┼──► /api/admin/*  ──► 广告 + 显示屏 ─┐           │
 发送命令 ───────┘      (员工认证)      (限定范围)   │           │
                                                      ▼           │
 配对屏幕 ◄──── PIN码 ────────────► /api/display/pair  │           │
                                     为每个显示屏颁发   │           │
                                     令牌               ▼           │
                                    /api/display/playlist ── 轮询 ──┤
                                     ▲ 解析广告ID → 广告            │
                                     └── 上传遥测数据,              │
                                         下发命令           播放器循环

整个运行时只依赖一种请求类型:设备轮询/api/display/playlist,上传遥测数据并接收内容和命令。所有的运维操作都通过这个通道进行。

关键事实 —— 在设计任何东西之前请先阅读

  1. 播放列表是显示屏上的有序数组,而不是一个独立的实体。 display.adIds: string[] 就是 播放列表 —— 顺序是自由的,无需连接,一次读取。只有当相同内容必须在多个屏幕上运行时,才引入独立的播放列表实体;参见 data-model.md 了解权衡,以及 extensions.md 了解迁移方案。
  2. 使用轮询,而非流式传输。 30-60秒的轮询更便宜,能适应休眠的网络堆栈,并且会自动重新连接。实时通信是可选的升级,而不是基础。使用ETag缓存响应,否则你将每次轮询都为每个屏幕支付全量读取的成本。
  3. 媒体上传直接由浏览器到存储,绝不经过API路由。路由处理程序有主体大小限制,并且在代理传输字节时会消耗计算资源。
  4. 设备是不可信的且无人值守。 它在任何人可以走上去的硬件上的localStorage中保存一个长期有效的凭证。该凭证必须是每个屏幕独立的,并且可以撤销。
  5. 播放器必须永不停止。 每个媒体元素都必须有超时、错误处理程序和跳过方式。一个有问题的素材会前进,而不是卡住。

硬性规则

绝不从渲染状态派生轮询间隔。 在稳定的间隔上进行轮询,并从ref读取幻灯片状态。一个效果依赖于幻灯片索引的计时器在每次幻灯片切换时都会被销毁并重新创建,因此比幻灯片持续时间长的刷新永远不会触发;行为契约将轮询的定时绑定到挂钟时间。

绝不将“暂停”和“删除”重载为同一个布尔值。 使用active表示操作员意图,并使用单独的deletedAt表示生命周期,否则删除的项目一旦有人重新启用它就会重新出现。

绝不信任客户端提供的租户/位置范围。 从经过身份验证的员工会话或令牌解析到的显示屏行中在服务器端派生它,并在每个[id]路由上强制执行 —— 返回404,而非403,这样ID就无法被探测。

绝不为每个屏幕签发一个共享令牌。 在配对时为每个显示屏签发自有的令牌,只存储其哈希值,并使撤销成为一个单行更新。

绝不在onLoad之前开始图片的持续时间计时器。 在速度慢的电视上,否则幻灯片在可见之前就会过期。

绝不将持久的屏幕状态放入一次性命令中。 空白和接管必须能在设备每日重新加载和电源循环后幸存 —— 将它们作为每个轮询上的状态(mode)传递,并将确认清除的命令通道保留给真正的一次性命令,如重新加载。并且,任何效果是重新加载的命令必须在重新加载之前持久化其确认,否则服务器将永远重新发送它。

快速开始

  1. 为你的应用填充接口契约并确认域名重命名 —— adaptation.md。
  2. 建模实体并选择数组vs连接表 —— data-model.md。
  3. 创建表/集合、索引、安全规则和媒体存储桶 —— firestore-backend.md 或 supabase-backend.md。
  4. 构建设备和管理员端点,包括配对和令牌验证 —— api-routes.md。
  5. 让一个屏幕配对 —— pairing.md —— 然后投入播放器循环 —— player-runtime.md。
  6. 构建后台管理:媒体库、显示屏列表、播放列表编辑器 —— admin-ui.md。
  7. 在投入生产前添加健康监控、预览和远程控制 —— operations.md。
  8. 对照 player-runtime.md 中的行为契约表进行验证 —— 拔掉网线,在循环中删除当前广告,发出重载命令 —— 并将播放器机器测试作为回归覆盖。

参考目录

根据触发关键词加载相应的参考文档。对于全新设计,请先阅读 data-model.md。

api-routes.md 和 operations.md 中的代码基于Firestore作为标准后端编写;supabase-backend.md 定义了所有替代方案 —— 替换 adIds 的连接表,以及服务函数的SQL等价物。

场景触发关键词参考文档
将本模块适配到现有应用adapt, rename, seam, integrate, tenant, host appadaptation.md
实体、字段、播放列表形状schema, model, Ad, Display, playlist, junction, soft deletedata-model.md
Firestore/Firebase后端Firestore, firebase-admin, security rules, composite index, Firebase Storagefirestore-backend.md
Supabase/Postgres后端Supabase, Postgres, RLS, migration, storage bucket, Realtimesupabase-backend.md
端点、配对、令牌、缓存API route, pairing, PIN, token, ETag, scope check, zodapi-routes.md
让一个屏幕配对pairing, PIN, provisioning URL, hub, credential, unpairpairing.md
TV播放器循环player, loop, crossfade, video stall, rotation, portrait, wake lock, offlineplayer-runtime.md
后台管理UIadmin, upload, media library, playlist editor, provisioning URLadmin-ui.md
健康监控、预览、远程控制heartbeat, last seen, offline, preview, reload, blank, emergency takeover, audit logoperations.md
调度、复用、报告dayparting, start date, campaign, shared playlist, proof of play, precache, multi-zoneextensions.md
模板为何与简单移植不同provenance, ledger, rationale, kept, addedprovenance.md

相关技能