@conetic/prestoplay-analytics

中文文档
0.2.1发布于 2026/10/02SEE LICENSE IN LICENSETypeScriptESM + CJS零依赖近 30 天下载 3772

PRESToplay 插件, 将 Voyager IFE 分析事件报告到分析端点

中文使用文档
文档目录18 节
  1. 安装
  2. 快开始
  3. 没有捆绑
  4. 三件事会咬人
  5. 配置
  6. 静态- 构造器配置
  7. 反弹.. load() 配置
  8. 请求
  9. 阅读数据时值得了解的两种行为
  10. 插件自己检测到什么
  11. 运行时间 API
  12. 交付
  13. 击打
  14. 线条格式
  15. 已执行的空格问题
  16. 类型脚本
  17. 杰森·斯克马
  18. 发展

@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 在玩家配置中.

静态- 构造器配置

密钥类型默认说明
endpointstring—— 说分析端点 URL. 绝对或同源.
headersRecord<string,string>{}额外的请求头,例如:. {'x-api-key': '…'}。见下文信标提示.
keepalivebooleantrue发送每次事件 fetch(..., {keepalive: true}) 因此,一个在飞行中 撕裂的要求仍然完成。 设定 false 只有在终点是同一来源的服务工人时: Firefox 路线在工人周围持续请求。 卸载路径总是使用保存后 sendBeacon。 。 。 .
envelope'mms' | 'raw''mms'mms 员额 {type, payload, occurredAt}· ; raw 张贴赤裸事件对象.
batchSizenumber1每个请求的事件. 1 每起事件都是自己发的 1以上, 活动队列, 并作为 JSON 阵列一起出去 —— 见 击打。 。 。 .
batchFlushMsnumber0不完全的批次可能要等很久才发出. 0 =无时间限制。 忽略当 batchSize 为 1.
disabledEventsEventName[][]事件名称从未发布. 事发前检查过了 所以 sequence 没有洞.
transport'http' | 'mock' | Transport | () => Transporthttp 何时 endpoint 已经设定, 否则 mock交付机制.
serverTimeRFC 3339 字符串—— 说服务器在会话开始时的时间, 为时钟校正 。 大力推荐.
flightFlightContext—— 说斯谱 4.2. 顺利通过.
sessionSessionContext—— 说标本4.3: session_id 财务报告和审定财务报表 device_id。 。 。 .
systemSystemContext—— 说谱 4.5: oem 财务报告和审定财务报表 app_version。 。 。 .
devicePartial<DeviceContext>检测超过检测值 .
onEvent(event, body) => void—— 说无论运输方式如何, 对检查人员和调试人员来说——不是交付保证.
enabledbooleantruefalse 加载插件但禁用所有报告.
trackChangeCoalesceMsnumber50将同步音频+字幕更改合并到一个事件的窗口 .
trackDiscoveryMsnumber1500多长时间 LOADEDMETADATA 等待轨道列表, 当它看起来还是空的 。 文本音轨在内容负载后注册; 立即报告生成空 available_subtitle_languages 有的跑来跑去,有的跑来跑去. 0 关闭等待。 不影响 time_to_metadata_ms。 。 。 .
seekSettleMsnumber250玩家头在报告搜索前必须安顿多久,所以擦拭器拖曳是一个事件,而不是每个中间位置一个(6.6.
minSeekDeltaMsnumber1000最小的跳跃报告为乘客寻找.
userGestureWindowMsnumber2000用户的手势是多久才写到 video.currentTime 算作客运动作 见 请求 见下文.
debugbooleanfalse日志插件诊断.

反弹.. load() 配置

密钥类型雷克语说明
media_idstring对目录标识符,在插曲/音轨级别.
mediaMediaMetadata对Spec 4.6目录元数据,以下修改. 发送到 PLAY 只有这个.
gui_pathstring对为到达资产而走的导航路径 .

start_position_ms 从玩家自己读取 startTime - 别重复它.

这个 media 块

media_title 电影 电影 插曲 赛道 章节 没有 episode_title。家长进入 series_title,其位置在 episode_number数字 :

media_typemedia_subtypemedia_titleseries_titleseason_numberepisode_numberauthor_or_artist
MOVIE—— 说电影—— 说—— 说—— 说—— 说
SERIES_EPISODE譬如说. SITCOM剧集显示 (韩语){\fn华文楷体\fs16\1che0e0e0}雷克.{\fn华文楷体\fs16\1che0e0e0}雷克.—— 说
AUDIOALBUM音轨相册 (韩语)—— 说音轨编号。 如果知道的话相册艺人
AUDIOAUDIOBOOK章 次 页 次书本 (韩语)—— 说章次(如果知道)作者
AUDIOPODCAST剧集播客 (韩语)—— 说{\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 如果修改,接口是扩展点.
页:1device_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升级后会重新编号玩家状态 而不是悄悄地腐蚀分析师.

版本与发布记录

@conetic/prestoplay-analytics 共发布 1 个版本,首次发布于 2026/10/02;过去 12 个月发布了 1 个版本。

版本发布日期距今
0.2.1latest2026/10/021 个月前

关于 @conetic/prestoplay-analytics 的常见问题

@conetic/prestoplay-analytics 是什么?

PRESToplay 插件, 将 Voyager IFE 分析事件报告到分析端点

如何安装 @conetic/prestoplay-analytics?

在项目目录运行 npm install @conetic/prestoplay-analytics,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@castlabs/prestoplay(^6.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@conetic/prestoplay-analytics 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@conetic/prestoplay-analytics 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@conetic/prestoplay-analytics 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@conetic/prestoplay-analytics 可以商用吗?

@conetic/prestoplay-analytics 使用 SEE LICENSE IN LICENSE 许可。许可条款写在包内的独立文件中,请阅读该文件确认可否商用。以上为概括,不构成法律意见,请以许可原文为准。

@conetic/prestoplay-analytics 的下载量有多少?

根据 npm 官方下载统计,@conetic/prestoplay-analytics 在 2026/10/11 – 2026/11/09 这 30 天内被下载 3,772 次,日均约 126 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@conetic/prestoplay-analytics 还在维护吗?

最新版本 0.2.1 发布于 2026/10/02(1 个月前);至今共发布 1 个版本,其中过去 12 个月发布了 1 个;首次发布于 2026/10/02。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。