@conetic/prestoplay-analysis(英语:
PRESTOPLE 插件, 报告在 变速器分析事件规格(v0.3)——0.2.0有效载荷 所列修正案 变动情况 作为JSON Posts 到一个 分析终点,每个请求或分批一个事件.
插件拥有玩家所能告诉的一切 — 回放状态、 寻求、 跟踪
变化、错误、时间——加 event_id, (中文(简体) ), sequence, (中文(简体) ), playback_id时钟
校正 设备检测 主机应用程序提供航班,
语句和目录背景,玩家无法知道.
第一次融合这个? 开始 总部。 。 。 .
安装
npm install @conetic/prestoplay-analytics
向公众公布 npm 登记册——没有登记册配置或标志 需要帮助. 总部 有完整的设置.
@castlabs/prestoplay 是同级依赖(v6). 插件没有运行时间
其自依缘.
快开始
import { clpp } from '@castlabs/prestoplay'
import '@castlabs/prestoplay/cl.mse'
import '@castlabs/prestoplay/cl.dash'
import { registerVoyagerAnalytics } from '@conetic/prestoplay-analytics'
// 1. Register BEFORE any player is constructed.
registerVoyagerAnalytics(clpp)
// 2. Static context goes in the player constructor config.
const player = new clpp.Player('#video', {
license: CLPP_LICENSE,
voyagerAnalytics: {
endpoint: 'https://<analytics-host>/api/v1/analytics/events',
serverTime: bootstrap.serverTime,
batchSize: 5, // optional; 1 (one POST per event) by default
flight: {
tail_number: 'N123AZ',
flight_number: 'XY0189',
departure_iata: 'GIG',
arrival_iata: 'OPO',
takeoff_time: '2026-01-08T16:13:00.000Z',
},
session: {
session_id: bootstrap.sessionId,
device_id: bootstrap.deviceId, // onboard router ID, host-supplied
},
system: { oem: 'ACME', app_version: '2.4.1' },
},
})
// 3. Per-playback context goes in the load() config.
await player.load({
source: { url: asset.manifestUrl, type: clpp.Type.DASH },
startTime: resumePositionSeconds,
voyagerAnalytics: {
gui_path: 'home/categories/kids',
media_id: '9090929',
media: {
media_title: 'Bart Gets Famous',
media_type: 'SERIES_EPISODE',
series_title: 'The Simpsons',
season_number: 5,
episode_number: 12,
distributor: 'Warner Bros Discovery',
category: 'Kids',
genres: ['Comedy', 'Animation'],
original_language: 'en',
release_year: 2023,
duration_ms: 1420000,
},
},
})
这就是整体整合。 七事从之.
没有捆绑
<script src="node_modules/@castlabs/prestoplay/cl.core.js"></script>
<script src="node_modules/@conetic/prestoplay-analytics/dist/index.global.js"></script>
<script>
VoyagerAnalytics.registerVoyagerAnalytics(clpp)
</script>
三件事会咬人
1. 在构建玩家之前登记. PRESToplay 消耗插件
工厂内部 Player 建筑师. registerVoyagerAnalytics() 之后
new clpp.Player(...) 对那个玩家没有任何影响 却默默失败了.
2. 每局键属于 load() 配置 绝不是构造器配置 .
SDK 合并 [constructorConfig, loadConfig, source] 和嵌入对象合并
而不是替换. media, (中文(简体) ), media_id 财务报告和审定财务报表 gui_path 放置在构造器中
配置会血流成河 静态背景
(单位:千美元)endpoint, (中文(简体) ), flight, (中文(简体) ), session, (中文(简体) ), system属于构造器配置;
每个播放上下文属于 load()。 。 。 .
3. 海关运输不得作为类例. 同样的合并副本
原始的,功能的, Dates和平地物体,以及 安静地放下任何东西
带有非平面原型。通过工厂函数或普通对象:
voyagerAnalytics: { transport: () => new MyTransport() } // works
voyagerAnalytics: { transport: new MyTransport() } // silently dropped
运输 send(payload, { events, unloading }) 收到一个请求
一次值 : payload 单体,或当批量时,一组
他们,和 events 以相同的顺序列出内部的事件.
另请注意: 插件不运行于 clpp.PlaylistPlayer 内
单控制器播放列表模式,它完全禁用插件 .
配置
所有密钥都在下面 voyagerAnalytics 在玩家配置中.
静态- 构造器配置
| 密钥 | 类型 | 默认 | 说明 |
|---|---|---|---|
endpoint | string | —— 说 | 分析端点 URL. 绝对或同源. |
headers | Record<string,string> | {} | 额外的请求头,例如:. {'x-api-key': '…'}。见下文信标提示. |
keepalive | boolean | true | 发送每次事件 fetch(..., {keepalive: true}) 因此,一个在飞行中 撕裂的要求仍然完成。 设定 false 只有在终点是同一来源的服务工人时: Firefox 路线在工人周围持续请求。 卸载路径总是使用保存后 sendBeacon。 。 。 . |
envelope | 'mms' | 'raw' | 'mms' | mms 员额 {type, payload, occurredAt}· ; raw 张贴赤裸事件对象. |
batchSize | number | 1 | 每个请求的事件. 1 每起事件都是自己发的 1以上, 活动队列, 并作为 JSON 阵列一起出去 —— 见 击打。 。 。 . |
batchFlushMs | number | 0 | 不完全的批次可能要等很久才发出. 0 =无时间限制。 忽略当 batchSize 为 1. |
disabledEvents | EventName[] | [] | 事件名称从未发布. 事发前检查过了 所以 sequence 没有洞. |
transport | 'http' | 'mock' | Transport | () => Transport | http 何时 endpoint 已经设定, 否则 mock | 交付机制. |
serverTime | RFC 3339 字符串 | —— 说 | 服务器在会话开始时的时间, 为时钟校正 。 大力推荐. |
flight | FlightContext | —— 说 | 斯谱 4.2. 顺利通过. |
session | SessionContext | —— 说 | 标本4.3: session_id 财务报告和审定财务报表 device_id。 。 。 . |
system | SystemContext | —— 说 | 谱 4.5: oem 财务报告和审定财务报表 app_version。 。 。 . |
device | Partial<DeviceContext> | 检测 | 超过检测值 . |
onEvent | (event, body) => void | —— 说 | 无论运输方式如何, 对检查人员和调试人员来说——不是交付保证. |
enabled | boolean | true | false 加载插件但禁用所有报告. |
trackChangeCoalesceMs | number | 50 | 将同步音频+字幕更改合并到一个事件的窗口 . |
trackDiscoveryMs | number | 1500 | 多长时间 LOADEDMETADATA 等待轨道列表, 当它看起来还是空的 。 文本音轨在内容负载后注册; 立即报告生成空 available_subtitle_languages 有的跑来跑去,有的跑来跑去. 0 关闭等待。 不影响 time_to_metadata_ms。 。 。 . |
seekSettleMs | number | 250 | 玩家头在报告搜索前必须安顿多久,所以擦拭器拖曳是一个事件,而不是每个中间位置一个(6.6. |
minSeekDeltaMs | number | 1000 | 最小的跳跃报告为乘客寻找. |
userGestureWindowMs | number | 2000 | 用户的手势是多久才写到 video.currentTime 算作客运动作 见 请求 见下文. |
debug | boolean | false | 日志插件诊断. |
反弹.. load() 配置
| 密钥 | 类型 | 雷克语 | 说明 |
|---|---|---|---|
media_id | string | 对 | 目录标识符,在插曲/音轨级别. |
media | MediaMetadata | 对 | Spec 4.6目录元数据,以下修改. 发送到 PLAY 只有这个. |
gui_path | string | 对 | 为到达资产而走的导航路径 . |
start_position_ms 从玩家自己读取 startTime - 别重复它.
这个 media 块
media_title 电影 电影
插曲 赛道 章节 没有 episode_title。家长进入
series_title,其位置在 episode_number数字 :
media_type | media_subtype | media_title | series_title | season_number | episode_number | author_or_artist |
|---|---|---|---|---|---|---|
MOVIE | —— 说 | 电影 | —— 说 | —— 说 | —— 说 | —— 说 |
SERIES_EPISODE | 譬如说. SITCOM | 剧集 | 显示 (韩语) | {\fn华文楷体\fs16\1che0e0e0}雷克. | {\fn华文楷体\fs16\1che0e0e0}雷克. | —— 说 |
AUDIO | ALBUM | 音轨 | 相册 (韩语) | —— 说 | 音轨编号。 如果知道的话 | 相册艺人 |
AUDIO | AUDIOBOOK | 章 次 页 次 | 书本 (韩语) | —— 说 | 章次(如果知道) | 作者 |
AUDIO | PODCAST | 剧集 | 播客 (韩语) | —— 说 | {\fn华文楷体\fs16\1che0e0e0}雷克. | 东道主 |
TRAILER, (中文(简体) ), LIVE | —— 说 | 标题 | —— 说 | —— 说 | —— 说 | —— 说 |
distributor 财务报告和审定财务报表 duration_ms 总是需要; category, (中文(简体) ), genres, (中文(简体) ),
original_language 财务报告和审定财务报表 release_year 到处都是可选的.
插件会先减少给这些字段的任何内容
事件已经构建。 一个流浪汉 episode_title 或丢弃不相关的目录密钥
有警告和遗教 media_type: 'PODCAST' 被映射为 AUDIO 编号 :
PODCAST 以0.1.x为单位的集成继续报告.
若为 media_id 或者说 media 缺少 未报告 (单位:千美元)
clpp.Error(RECOVERABLE, PLUGIN, 7100) 在玩家上被提升,匹配
SDK自己的插件报告配置不良.
请求
乘客可以两相移动游乐头,两相报道:
player.setPosition()定制的UI洗手机怎么叫的? 总是报.video.currentTime = x浏览器的原生<video controls>洗涤器是的,任何UI都建立在媒体元素上. 游戏的USER_SEEKING编号 :USER_SEEKED永远不要为这些而开火, 只有原始的媒体事件.
玩家也为自己移动玩家头——漏洞跳出,活地修正
- 通过同样的媒体活动,测出启动缺口跳出
1.9 s,因此跳跃的大小不能将它们分开. 意向能力:乘客
求求总是遵循用户的手势,玩家的校正从未如此。 如此寻觅
写给 currentTime 仅当手势发生于
userGestureWindowMs。通过 setPosition() 绕过检查,
因为召集API本身就是意向声明.
如果你的UI在程序上移动玩家头 并且你想要报告,请打电话
player.setPosition() 而不是写作 currentTime。 。 。 .
阅读数据时值得了解的两种行为
STATE_CHANGED 锁链. 每个活动 previous_state 是前一个事件的
current_state因此,通过命令可以重建回放的时间线
sequence 内 playback_id这不仅仅是PRESToplay自己的
previousState: 玩家没有 SEEKING 状态 - 请求是 BUFFERING
携带 reason: SEEKING 因此,独立绘制出入口图将发出
PLAYING → SEEKING 接下来是 BUFFERING → PLAYING,不会加入.
语言标记是可读的 至BCP 47外壳: zh-HANT 变成
zh-Hant, (中文(简体) ), pt-br 变成 pt-BR。表态在这里和
玩家将原始值传递过, 所以没有这个, 同一语言会到达
在几个拼写下 任何组合都分开 只有外壳被改变..
一个陌生的标记是经过未触及的 und 省略.
插件自己检测到什么
device_type, (中文(简体) ), os_name, (中文(简体) ), browser_name 财务报告和审定财务报表 ui_language 来源于
浏览器. 他们中任何一个都可以被推翻 config.device二个值
了解:
LAPTOP从未检测到. 浏览器无法区分笔记本电脑和 桌面; 插件报告DESKTOP。如果主机知道得更好,就取消它.ui_language默认为navigator.language。 。 。 . 光谱将它定义为 接口 语言。 如果应用程序的语言设置是 独立于浏览器, 覆盖它.
device_id 从未被检测到——它是船上路由器ID,必须提供
以主妇盟誓.
运行时间 API
import { getVoyagerAnalytics } from '@conetic/prestoplay-analytics'
const analytics = getVoyagerAnalytics(player)!
| 方法 | 目的 |
|---|---|
setSessionContext({flight, session, system, device, serverTime}) | 玩家建成后提供或更新上下文. 会话拖曳通常在玩家构造后完成,所以这是正常的路线. 部分更新合并. |
setNavigationContext(guiPath) | 设定 gui_path 下一个 PLAY,作为替代 load() 配置密钥 . |
reportError({error_id, error_category, error_location, error_description, is_fatal, media_id?}) | 报告应用程序级别错误 。 玩家无法生成 ENTITLEMENT 编号 : APPLICATION 类别或类别 CATALOGUE_FETCH 编号 : SESSION_BOOTSTRAP 编号 : UI_NAVIGATION 他们只经过这里. |
endPlayback(exitReason) | 明确关闭当前播放, 例如 . 'USER_STOP' 当应用程序撕下自己的玩家UI. |
flush() | 发送任何已排队的东西 。 除非分批,否则不准打电话. |
getPendingCount() | 事件已经建立但尚未发送。 除非进行分批,否则零分。 诊断. |
getSequence() | 发布最后序列号. 诊断. |
交付
火灾与遗忘,根据光谱的工作假设(开口问题4):
- 正常事件 :
fetch与keepalive: true。 。 。 . - 卸载路径事件( E)
USER_LEAVING与TAB_CLOSED:navigator.sendBeacon, (中文(简体) ), 倒计时keepalive获取。 从pagehide只有这个 一个页面是 只是隐藏着——屏幕锁、应用开关、前面的另一个标签——确实 没有 结束回放,乘客通常会回来,然后关在那里 以后的每一次事件都会下降,直到下一次load()。 。 。 . - 失败情况记录在案 丢弃。没有排队或重试——在
sequence是光谱的丢失信号 静默的重试会隐藏它 与 分批处理时,一个失败的请求会丢失整批,漏洞也表明这一点.
击打
batchSize: 1 (默认)每次事件都发布。 1以上,活动
队列并一起发布——a STATE_CHANGED 不再收费
自己来的 事件没有变化: event_id, (中文(简体) ), event_time 财务报告和审定财务报表
sequence 事件发生时盖章,而不是发出时盖章.
满了就发了一批 早点 何时持有会冒风险
时间: USER_LEAVING (回放结束了),上 pagehide (这页结束了,
通过 sendBeacon),关于玩家破坏,当传输改变,当应用
电话 flush()之后 batchFlushMs 如果设置。 之间,一个不完整的
批量等待——乘客在两小时的胶片中暂停一次,产生出两个
随行事件 USER_LEAVING。 。 。 .
二事以大小为相. sendBeacon 有效载荷预算约为64KB
上下文缓冲事件大约是 1 KB, 所以一批必须幸存下来的卸货应该
呆在这下面 失去请求会失去整个批次:a batchSize
5-10分之一的请求量多次超过,但没有造成任何损失
大块.
onEvent 每起事件仍会燃烧一次, 由事件本身的躯体
看这批货.
灯塔提醒. sendBeacon 无法设置请求头 。 若为 headers 携带
aPI 键,卸载路径事件将到达没有它。 如果终点需要
认证,要么接受损失 TAB_CLOSED 事件或移动
证书进入 URL — 属于 spec 开放问题 3 的决定 .
线条格式
与 envelope: 'mms' (默认),匹配 POST /api/v1/analytics/events数字 :
{
"type": "PLAY",
"payload": { "event_id": "…", "event_name": "PLAY", "…": "…" },
"occurredAt": "2026-01-08T16:23:06.412Z"
}
与 envelope: 'raw',有效载荷物体单独张贴.
何时 batchSize 捆绑了一些事件, 身体是JSON阵列的以上,
内 sequence 顺序 :
[
{ "type": "PLAY", "payload": { "…": "…" }, "occurredAt": "2026-01-08T16:23:06.412Z" },
{ "type": "STATE_CHANGED", "payload": { "…": "…" }, "occurredAt": "2026-01-08T16:23:06.418Z" }
]
碰巧举行一个活动的批次被作为单一对象发布,从不
单元素阵列——所以只接受单形式保存的端点
工作时间,只要 batchSize 保持为1.
已执行的空格问题
| {\fn方正粗倩简体\fs12\an8\1cHFFFF00\b0} | 问题 | 该插件今天做什么 |
|---|---|---|
| 1个 | 默认 dub/ sub 当 AUDIO_TRACK_CHANGED 从不放火 | 如果没有改变,则不会释放任何东西。 当前选择的种子为 LOADEDMETADATA 这么说 第一个 真实变化报告正确 previous_* 数值。 故意不承认一个合成的默认——它会捏造一个事件. |
| 3个 | 端点规格 | endpoint, (中文(简体) ), headers 财务报告和审定财务报表 envelope 全部可以配置;没有硬码. |
| 页:1 | 重试/ 队列 | 起火而忘相会. A 类 Transport 如果修改,接口是扩展点. |
| 页:1 | device_id 稳定 | 被视为由东道方提供,在飞行中跨会稳定。 该插件从未发明或坚持它 . |
类型脚本
clpp.PlayerConfiguration 是一类别名,没有索引签名,所以不能
通过声明合并扩展,一个自定义密钥是多余的产权错误.
使用导出相交点 :
import type { WithVoyagerAnalytics } from '@conetic/prestoplay-analytics'
const config: WithVoyagerAnalytics<clpp.PlayerConfiguration> = {
source: { url },
voyagerAnalytics: { media_id: '9090929', media },
}
await player.load(config)
杰森·斯克马
2020-12年事件有效载荷船舶计划草案:
@conetic/prestoplay-analytics/schema
插件可以发射的每一个事件都会在测试套件中针对它进行验证.
发展
npm install
npm run build # ESM + CJS + IIFE + .d.ts
npm test # unit suite (vitest, no browser)
npm run test:browser # browser suite (Playwright, real player, real streams)
npm run typecheck
浏览器套房驱动一个真实的PRESToplay播放器对接公共测试流,
装入已建 dist/。它涵盖了假玩家无法做到的事:
SDK真实地发出,按照它发出的顺序,发出它报告的值——
寻找、追踪和错误位置的行为
已经建立。 它需要网络访问并使用当地安装的Chrome
CI 运行 npx playwright install chromium 设置 PW_CHANNEL=。 。 。 .
测试套间包括一个读取安装的警卫
@castlabs/prestoplay/typings.d.ts 并声称每个PRESToplay常数
插件镜像仍然匹配——所以SDK升级后会重新编号玩家状态
而不是悄悄地腐蚀分析师.