Webhook
Webhook 会在事情发生的那一刻,把消息发给另一个工具:开始播放、标为已看、新增了一部电影。Home Assistant、Trakt 和 Simkl 的同步桥接、Discord 和 Telegram 的通知桥接都能读取。格式与 Emby 的 Webhook 相同,所以为 Emby 做的工具不用改就能接。所有方案都免费使用。
新增 Webhook#
- 在管理后台打开 系统设置 → 集成 → Webhook,选择 新增 Webhook。
- 填入名称和接收方的地址。地址可以在你的局域网里。
- 勾选要发送的事件,然后在列表上选择 发送测试,确认对方收得到。
可以新增多个 Webhook。每个都有自己的事件,也可以只针对部分成员或部分媒体库(留空表示全部)。表单里的 示例内容 会显示事件的样子。
事件#
代码就是接收方在 Event 字段里看到的值。
| 代码 | 什么时候发送 |
|---|---|
library.new |
新作品刮削完成,ID 都齐了才发送。新媒体库的第一次扫描不发送。 |
playback.start |
开始播放,每次观看只发一次。 |
playback.pause、playback.unpause |
暂停,以及暂停后继续。 |
playback.stop |
播放结束。PlayedToCompletion 说明是否看完。 |
item.markplayed、item.markunplayed |
成员把作品标为已看或未看。来自账号同步和导入的变更不发送。 |
item.rate |
成员加入或取消收藏,两种情况用同一个代码。 |
发送测试 会发出 system.notificationtest,不受开关和事件勾选影响。
发送的内容#
每条消息都有 Title、Date(UTC)、Event 和 Server(Name、Id、Version、ProductName、ProductVersion)。Server.Version 是兼容 Emby 的版本号;要显示 Kryspal 的版本,请用 Server.ProductVersion。与成员有关的事件还有 User(Name、Id)和 Item,后者的格式与 Emby API 里的作品相同。Item.ProviderIds 放 TMDB、IMDb、TVDB 的 ID,没有时是 {}。播放事件另有 Session(设备和地址)和 PlaybackInfo(PositionTicks、PlayedToCompletion)。
每个 Webhook 可以选格式:
- JSON(默认):内容直接作为请求本体,
Content-Type: application/json。 - 表单(multipart):同样的内容放在名为
data的表单字段里。部分旧工具只认这种。
投递#
- 回应 2xx 状态码就算收到,服务器最多等 15 秒。
- 失败会再试三次,间隔约 10 秒、1 分钟、5 分钟。重定向算失败,不会跟随。
- 回应 410 会立刻关闭这个 Webhook;连续失败超过 24 小时也会关闭。两种情况都会在概况出现 Webhook 已停用 的提醒,Webhook 上写着原因,重新开启即可恢复。
- 事件在后台发送,不会拖慢播放或扫描。服务器重启时,还在排队的事件不会补发。
- 每个 Webhook 最近 50 次的投递列在 最近的投递 里,有状态和简短的错误代码,不保存消息本身。
- 局域网地址可以使用;链路本地地址和云端元数据地址会被挡下。只支持
http和https。 - 带密钥的地址(
?token=…)在列表和日志里会隐藏参数值。编辑 Webhook 时,地址留空表示保留原来的。
验证发送方#
如果希望对方确认消息确实来自你,就设置 密钥。之后每条消息会带三个 Standard Webhooks 格式的标头:
| 标头 | 内容 |
|---|---|
webhook-id |
消息 ID,重试时相同。 |
webhook-timestamp |
Unix 时间,单位秒。 |
webhook-signature |
v1, 加上对 id.timestamp.body 做 HMAC-SHA256 的 base64,密钥照输入的原样使用。 |
不设密钥就什么都不加,和 Emby 一样。密钥可以更换或移除,但无法读回。
示例:Home Assistant#
在 Home Assistant 建一个 Webhook 触发的自动化,再把它的地址 http://<home-assistant>:8123/api/webhook/kryspal-playback 填进新的 Webhook,格式选 JSON。
automation:
- alias: 开始播放电影时调暗灯光
triggers:
- trigger: webhook
webhook_id: kryspal-playback
allowed_methods: [POST]
local_only: true
conditions:
- condition: template
value_template: "{{ trigger.json.Event == 'playback.start' and trigger.json.Item.Type == 'Movie' }}"
actions:
- action: light.turn_off
target:
entity_id: light.living_room