{"_id":"@codeages/cloud-video-player-web","_rev":"6-5a9414e091a086610c9c1232685dc90d","name":"@codeages/cloud-video-player-web","dist-tags":{"latest":"0.0.6"},"versions":{"0.0.1":{"name":"@codeages/cloud-video-player-web","version":"0.0.1","_id":"@codeages/cloud-video-player-web@0.0.1","maintainers":[{"name":"zhangjie011117","email":"1836204942@qq.com"},{"name":"codeages-admin","email":"codeages@foxmail.com"},{"name":"lileiseven","email":"lileiseven@foxmail.com"},{"name":"zhugexiaobo","email":"zhugexiaobo@gmail.com"}],"dist":{"shasum":"f8d9b3f7c88a7d5ccca092b4b2a328f89c7c04b4","tarball":"https://registry.npmjs.org/@codeages/cloud-video-player-web/-/cloud-video-player-web-0.0.1.tgz","fileCount":5,"integrity":"sha512-racprzepwv7IjDxJQSMtlM+Gyca5c9ghvFkNJwamd5UkJUHdWqz6yBdPOmmLB1F4jtG5PAVPkGoZL/iYfAT5AQ==","signatures":[{"sig":"MEUCICUIAl6RZuloxsdUbCoQBSDbL2wq1Ce5RXrtMRUE7hTcAiEA0KTD+9592C0Zc14BfrRUeWNl/VGqUUk8lJZMFmUUvUk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1188881},"main":"./dist/lib.js","type":"module","types":"./dist/lib.d.ts","exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js"},"./style.css":"./dist/cloud-video-player-web.css"},"gitHead":"1ecad822cb19b4010bfaa679e8378f41118caf41","scripts":{"dev":"vite","test":"vitest run","build":"tsc && vite build","preview":"vite preview"},"_npmUser":{"name":"zhangjie011117","email":"1836204942@qq.com"},"_npmVersion":"11.12.1","description":"基于 TypeScript、xgplayer 和 hls.js 的 Web 视频播放器库，支持 HLS 播放、自定义主题色、播放控制、事件订阅和云端 V4～V10 Key 解密。","directories":{},"_nodeVersion":"24.15.0","dependencies":{"hls.js":"^1.7.1","ts-log":"^3.0.3","xgplayer":"^3.0.26"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.2.2","lucide":"^1.42.0","vitest":"^5.0.0","typescript":"~6.0.2","@types/node":"^26.4.0","unplugin-dts":"^1.0.3","@microsoft/api-extractor":"^7.59.0"},"_npmOperationalInternal":{"tmp":"tmp/cloud-video-player-web_0.0.1_1788935393044_0.7517012635816642","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@codeages/cloud-video-player-web","version":"0.0.2","_id":"@codeages/cloud-video-player-web@0.0.2","maintainers":[{"name":"zhangjie011117","email":"1836204942@qq.com"},{"name":"codeages-admin","email":"codeages@foxmail.com"},{"name":"lileiseven","email":"lileiseven@foxmail.com"},{"name":"zhugexiaobo","email":"zhugexiaobo@gmail.com"}],"dist":{"shasum":"65ee71db4a3b97325aeda0a8ca433b757022b2fe","tarball":"https://registry.npmjs.org/@codeages/cloud-video-player-web/-/cloud-video-player-web-0.0.2.tgz","fileCount":5,"integrity":"sha512-kngmEzQGjgf122037qGJwUJNWi2eJNnSsWmoc+Eyceax0ieLmHavCaD/ma7WrKlbD/QrQW2ILFw5244zWv6gng==","signatures":[{"sig":"MEQCIDJrjZJSF/7qEKj4Hxw9ww2Pc10GUuY8xcGqc6cbRJOPAiBU8bELvYKBSpN88TAFqNPh1xnUdHpvQypfp7i8p/UatQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQC2u0dZMlbe4WRD4ba+21MSENYSfxpTDl10EgLpSmPqjgIgVdiAiBfaIq2aPvZZcHYN1M8YCuUB0kddsly1O4v+30M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1191198},"main":"./dist/lib.js","type":"module","types":"./dist/lib.d.ts","exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js"},"./style.css":"./dist/cloud-video-player-web.css"},"gitHead":"04aef64316108406bfa54031a5ca695bf0bdc4c5","scripts":{"dev":"vite","test":"vitest run","build":"tsc && vite build","preview":"vite preview"},"_npmUser":{"name":"zhangjie011117","email":"1836204942@qq.com"},"_npmVersion":"11.12.1","description":"基于 TypeScript、xgplayer 和 hls.js 的 Web 视频播放器库，支持 HLS 播放、自定义主题色、播放控制、事件订阅和云端 V4～V10 Key 解密。","directories":{},"_nodeVersion":"24.15.0","dependencies":{"hls.js":"^1.7.1","ts-log":"^3.0.3","xgplayer":"^3.0.26"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.2.2","lucide":"^1.42.0","vitest":"^5.0.0","typescript":"~6.0.2","@types/node":"^26.4.0","unplugin-dts":"^1.0.3","@microsoft/api-extractor":"^7.59.0"},"_npmOperationalInternal":{"tmp":"tmp/cloud-video-player-web_0.0.2_1788936307996_0.42096697041562936","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"@codeages/cloud-video-player-web","version":"0.0.3","_id":"@codeages/cloud-video-player-web@0.0.3","maintainers":[{"name":"zhangjie011117","email":"1836204942@qq.com"},{"name":"codeages-admin","email":"codeages@foxmail.com"},{"name":"lileiseven","email":"lileiseven@foxmail.com"},{"name":"zhugexiaobo","email":"zhugexiaobo@gmail.com"}],"dist":{"shasum":"84757f51244778970d0e69c0abe92fd1a7315568","tarball":"https://registry.npmjs.org/@codeages/cloud-video-player-web/-/cloud-video-player-web-0.0.3.tgz","fileCount":5,"integrity":"sha512-wHIJzbe9/wJ1WDEHRQ6XuLcOYr9kh9ycZd6Wn9NW+r5L54O1jWYl8PJ7qwMCJWtgwWf/shrwrDr8fQQ0ti7Crw==","signatures":[{"sig":"MEUCIQDDskY6yrNhvNLDkaMlDOWdNYosGnKisnMsFp4cZq1n7wIgcfBaPaT0w3Q/VueDDLiJtgTsDiWaPcdqHgUeGTbuvdI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQC/X14UGUTPWavRRJG0Sob0sIZgtatKDTx7L8wULGboeQIgfx5B1EWg+lc7box7XIkH+5LyyVFeB8BV/EDpeMTTt+Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1193049},"main":"./dist/lib.js","type":"module","types":"./dist/lib.d.ts","exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js"},"./style.css":"./dist/cloud-video-player-web.css"},"gitHead":"ea55636e9ad62f22e1f69724b13ccf8a7a4aae91","scripts":{"dev":"vite","test":"vitest run","build":"tsc && vite build","preview":"vite preview"},"_npmUser":{"name":"zhangjie011117","email":"1836204942@qq.com"},"_npmVersion":"11.12.1","description":"基于 TypeScript、xgplayer 和 hls.js 的 Web 视频播放器库，支持 HLS 播放、自定义主题色、播放控制、事件订阅和云端 V4～V10 Key 解密。","directories":{},"_nodeVersion":"24.15.0","dependencies":{"hls.js":"^1.7.1","ts-log":"^3.0.3","xgplayer":"^3.0.26"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.2.2","lucide":"^1.42.0","vitest":"^5.0.0","typescript":"~6.0.2","@types/node":"^26.4.0","unplugin-dts":"^1.0.3","@microsoft/api-extractor":"^7.59.0"},"_npmOperationalInternal":{"tmp":"tmp/cloud-video-player-web_0.0.3_1788937800901_0.03327915209178545","host":"s3://npm-registry-packages-npm-production"}},"0.0.4":{"name":"@codeages/cloud-video-player-web","version":"0.0.4","_id":"@codeages/cloud-video-player-web@0.0.4","maintainers":[{"name":"zhangjie011117","email":"1836204942@qq.com"},{"name":"codeages-admin","email":"codeages@foxmail.com"},{"name":"lileiseven","email":"lileiseven@foxmail.com"},{"name":"zhugexiaobo","email":"zhugexiaobo@gmail.com"}],"dist":{"shasum":"32b07bdad8cc38f33b91dbac80dbd7e749d9d088","tarball":"https://registry.npmjs.org/@codeages/cloud-video-player-web/-/cloud-video-player-web-0.0.4.tgz","fileCount":5,"integrity":"sha512-mknEs2Ght8B8zYbcnl5xiBSpdp6Egv02srCN5VyJ36pGm9DMo7f0T+py1525gp0PVvzuFA0sw4ZVQUYx2XdEuw==","signatures":[{"sig":"MEUCIDOiSNlTKQJANeIXLqByjK4+sN/3vTu3ikD8i4nvdKYzAiEAiQyP9a391u9iOsP7QiVFMG3jnvb+zJRmRCo0stJKNu4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIAeddclF9yBA0vpFfhdQH3Hh7xBgsQmmUWn6BYt3wBm7AiEAwoVAAHVopifzOm29jdmCFvdrA6tmCl5its7veDPo13I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1209522},"main":"./dist/lib.js","type":"module","types":"./dist/lib.d.ts","exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js"},"./style.css":"./dist/cloud-video-player-web.css"},"gitHead":"ea55636e9ad62f22e1f69724b13ccf8a7a4aae91","scripts":{"dev":"vite","test":"vitest run","build":"tsc && vite build","preview":"vite preview","test:cloud":"node tests/browser/cloud.mjs","test:browser":"node tests/browser/run.mjs"},"_npmUser":{"name":"zhangjie011117","email":"1836204942@qq.com"},"_npmVersion":"11.12.1","description":"基于 TypeScript、xgplayer 和 hls.js 的 Web 视频播放器库，支持 HLS 播放、自定义主题色、播放控制、事件订阅和云端 V4～V10 Key 解密。","directories":{},"_nodeVersion":"24.15.0","dependencies":{"hls.js":"^1.7.1","ts-log":"^3.0.3","xgplayer":"^3.0.26"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.2.2","lucide":"^1.42.0","vitest":"^5.0.0","playwright":"^1.63.0","typescript":"~6.0.2","@types/node":"^26.4.0","unplugin-dts":"^1.0.3","@microsoft/api-extractor":"^7.59.0"},"_npmOperationalInternal":{"tmp":"tmp/cloud-video-player-web_0.0.4_1788946521816_0.08552040096694902","host":"s3://npm-registry-packages-npm-production"}},"0.0.5":{"name":"@codeages/cloud-video-player-web","version":"0.0.5","_id":"@codeages/cloud-video-player-web@0.0.5","maintainers":[{"name":"zhangjie011117","email":"1836204942@qq.com"},{"name":"codeages-admin","email":"codeages@foxmail.com"},{"name":"lileiseven","email":"lileiseven@foxmail.com"},{"name":"zhugexiaobo","email":"zhugexiaobo@gmail.com"}],"dist":{"shasum":"f6e58bf99840c77639ffa180ac1595742511e334","tarball":"https://registry.npmjs.org/@codeages/cloud-video-player-web/-/cloud-video-player-web-0.0.5.tgz","fileCount":5,"integrity":"sha512-tbWD4U2P4hETnVUmDk/BuNT3lYqKhMTo3ZFSI76QaIypGog32Xo13HkBomYydXV6OZ9T86i6ngd1eSB8TL9xng==","signatures":[{"sig":"MEYCIQDoBEf7DE5bCe0DzT6YyXCry5FEf7ok7AuMDAlSAI4+wgIhAKDC0ecY/7OrDlAwcEprigTaOZANFGNAyc+E0WF2Dh52","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIDgz8AUrG40xFYiRGxtafUzNJIhxs9LoL7U4nEEpRj7dAiAl+cVRJd/6TJ4jmcpRV6SsbI8OvHKxOK13igLs5Yr87Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1218253},"main":"./dist/lib.js","type":"module","_from":"file:codeages-cloud-video-player-web-0.0.5.tgz","types":"./dist/lib.d.ts","exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js"},"./style.css":"./dist/cloud-video-player-web.css"},"scripts":{"dev":"vite","lint":"eslint src tests vite.config.ts vitest.config.ts","test":"vitest run","build":"tsc && vite build","preview":"vite preview","test:cloud":"node tests/browser/cloud.mjs","test:browser":"node tests/browser/run.mjs"},"_npmUser":{"name":"zhangjie011117","email":"1836204942@qq.com"},"_resolved":"/private/var/folders/f7/8dmqtfjj3dx2k8wc4657cwkh0000gn/T/9f9758bbbc6b70d1abe0c07a734caf46/codeages-cloud-video-player-web-0.0.5.tgz","_integrity":"sha512-tbWD4U2P4hETnVUmDk/BuNT3lYqKhMTo3ZFSI76QaIypGog32Xo13HkBomYydXV6OZ9T86i6ngd1eSB8TL9xng==","_npmVersion":"11.6.1","description":"基于 TypeScript、xgplayer 和 hls.js 的 Web 视频播放器库，支持 HLS 播放、自定义主题色、播放控制、事件订阅和云端 V4～V10 Key 解密。","directories":{},"_nodeVersion":"24.10.0","dependencies":{"hls.js":"^1.7.1","ts-log":"^3.0.3","xgplayer":"^3.0.26"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.2.2","eslint":"^10.10.0","lucide":"^1.42.0","vitest":"^5.0.0","globals":"^17.12.0","@eslint/js":"^10.0.1","playwright":"^1.63.0","typescript":"~6.0.2","@types/node":"^26.4.0","unplugin-dts":"^1.0.3","typescript-eslint":"^8.70.0","@microsoft/api-extractor":"^7.59.0"},"_npmOperationalInternal":{"tmp":"tmp/cloud-video-player-web_0.0.5_1789217783467_0.8457313826453403","host":"s3://npm-registry-packages-npm-production"}},"0.0.6":{"_id":"@codeages/cloud-video-player-web@0.0.6","dist":{"shasum":"87ae6efdbc1091230df92ece7af69496825f221f","tarball":"https://registry.npmjs.org/@codeages/cloud-video-player-web/-/cloud-video-player-web-0.0.6.tgz","fileCount":5,"integrity":"sha512-IYJZuiftoANI6dTRU7B4ycDy/zYgMP9rdkrVia/kR75nYy5Z+dDUGxwOzVtliedF4P/qfXXk+6jIi9X/yvj9JA==","signatures":[{"sig":"MEYCIQDjuYTCVD2Lbrqy9TKxrhN52rUwrUAUj17HjdDmz7e9AAIhAJzoyMONBl4Tu2ruTRThnC5/EDyLCi2nTinEKn1Hxq85","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEAtwBmz5mG+eBtqBiixrJjm7TuBRCcgrARJxDwK6p69AiEAvkqX5XS4ETrPgl+aTNlfZ30DJ7qdrFO3+07Zuy2ImzE="}],"unpackedSize":1208966},"main":"./dist/lib.js","name":"@codeages/cloud-video-player-web","type":"module","_from":"file:codeages-cloud-video-player-web-0.0.6.tgz","types":"./dist/lib.d.ts","exports":{".":{"types":"./dist/lib.d.ts","import":"./dist/lib.js"},"./style.css":"./dist/cloud-video-player-web.css"},"scripts":{"dev":"vite","lint":"eslint src tests vite.config.ts vitest.config.ts","test":"vitest run","build":"tsc && vite build","preview":"vite preview","test:cloud":"node tests/browser/cloud.mjs","test:browser":"node tests/browser/run.mjs"},"version":"0.0.6","_npmUser":{"name":"zhangjie011117","email":"1836204942@qq.com"},"_resolved":"/private/var/folders/f7/8dmqtfjj3dx2k8wc4657cwkh0000gn/T/db6eadd74a7c9616ea63fb87c4db147f/codeages-cloud-video-player-web-0.0.6.tgz","_integrity":"sha512-IYJZuiftoANI6dTRU7B4ycDy/zYgMP9rdkrVia/kR75nYy5Z+dDUGxwOzVtliedF4P/qfXXk+6jIi9X/yvj9JA==","_npmVersion":"11.6.1","description":"基于 TypeScript、xgplayer 和 hls.js 的 Web 视频播放器库，支持 HLS 播放、自定义主题色、播放控制、事件订阅和云端 V4～V10 Key 解密。","directories":{},"maintainers":[{"name":"zhangjie011117","email":"1836204942@qq.com"},{"name":"codeages-admin","email":"codeages@foxmail.com"},{"name":"lileiseven","email":"lileiseven@foxmail.com"},{"name":"zhugexiaobo","email":"zhugexiaobo@gmail.com"}],"_nodeVersion":"24.10.0","dependencies":{"hls.js":"^1.7.1","ts-log":"^3.0.3","xgplayer":"^3.0.26"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.2.2","eslint":"^10.10.0","lucide":"^1.42.0","vitest":"^5.0.0","globals":"^17.12.0","@eslint/js":"^10.0.1","playwright":"^1.63.0","typescript":"~6.0.2","@types/node":"^26.4.0","unplugin-dts":"^1.0.3","typescript-eslint":"^8.70.0","@microsoft/api-extractor":"^7.59.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cloud-video-player-web_0.0.6_1789226792946_0.6899830839149921"}}},"time":{"created":"2026-09-09T06:29:52.881Z","modified":"2026-09-12T15:26:33.231Z","0.0.1":"2026-09-09T06:29:53.190Z","0.0.2":"2026-09-09T06:45:08.128Z","0.0.3":"2026-09-09T07:10:01.091Z","0.0.4":"2026-09-09T09:35:21.955Z","0.0.5":"2026-09-12T12:56:23.567Z","0.0.6":"2026-09-12T15:26:33.024Z"},"description":"基于 TypeScript、xgplayer 和 hls.js 的 Web 视频播放器库，支持 HLS 播放、自定义主题色、播放控制、事件订阅和云端 V4～V10 Key 解密。","maintainers":[{"name":"zhangjie011117","email":"1836204942@qq.com"},{"name":"codeages-admin","email":"codeages@foxmail.com"},{"name":"lileiseven","email":"lileiseven@foxmail.com"},{"name":"zhugexiaobo","email":"zhugexiaobo@gmail.com"}],"readme":"# 视频播放器 Web 版\n\n基于 TypeScript、xgplayer 和 hls.js 的 Web 视频播放器库，支持 HLS 播放、自定义主题色、播放控制、事件订阅和云端 V4～V10 Key 解密。\n\n## 安装\n\n```bash\npnpm install\n```\n\n库入口为 `src/main.ts`，构建产物输出到 `dist/`。\n\n## 快速开始\n\n```ts\nimport { VideoPlayer } from '@codeages/cloud-video-player-web'\nimport '@codeages/cloud-video-player-web/style.css'\n\nconst player = new VideoPlayer({\n  id: 'video-player',\n  themeColor: '#2563eb',\n})\n\nplayer.on('error', error => {\n  console.error(error.code, error.message)\n})\n\nawait player.play(playUrl, { autoplay: false })\n```\n\n`playUrl` 是业务接口返回的云播放信息地址。SDK 自动获取播放列表、Key 版本和清晰度，不接受直接媒体地址，也不需要调用方解析云接口。\n\n挂载元素必须在创建播放器前存在：\n\n```html\n<div style=\"height: 405px\">\n  <div id=\"video-player\"></div>\n</div>\n```\n\n## 配置\n\n### `VideoPlayerConfig`\n\n| 参数 | 类型 | 说明 |\n| --- | --- | --- |\n| `id` | `string` | 播放器挂载元素 ID。 |\n| `width` | `number \\| string` | 默认 `'100%'`；数字表示像素，字符串支持 CSS 尺寸（包括百分比）。 |\n| `height` | `number \\| string` | 默认 `'100%'`；数字表示像素，使用百分比时父容器必须有明确高度。 |\n| `fullscreen` | `boolean` | 默认 `true`；设为 `false` 关闭普通全屏按钮和双击画面全屏。 |\n| `cssFullscreen` | `boolean` | 默认 `true`；独立控制网页全屏。 |\n| `themeColor` | `string` | 可选主题色，支持浏览器可识别的具体 CSS 颜色。 |\n| `playbackRates` | `number[]` | 默认 `[2, 1.5, 1.25, 1, 0.5]`，初始倍速为 `1`。必须非空、包含 `1`，各项为不重复的正有限数，否则抛出 `TypeError`。 |\n\n非法颜色、空字符串、`var()`、`currentColor` 和依赖外部上下文的颜色会抛出 `TypeError`。\n\n以上配置仅在创建实例时设置，切换播放资源时保留，不提供运行时修改接口。\n默认尺寸由原先的 `600 × 337.5` 改为填满父容器；旧页面需要为父容器提供明确高度，\n或显式传入 `width: 600, height: 337.5` 保持原尺寸。\n\n后台嵌入示例（父容器需有明确高度）：\n\n```ts\nconst player = new VideoPlayer({\n  id: 'video-player',\n  width: '100%',\n  height: '100%',\n  fullscreen: false,\n  cssFullscreen: false,\n})\n```\n\n### `PlayOptions`\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `autoplay` | `boolean` | `true` | 加载新资源后是否自动播放。 |\n\n### 清晰度与倍速\n\nSDK 通过 JSONP 请求 `playUrl`，再请求播放列表的 `json=1` 接口获取清晰度。\n清晰度保持云接口返回顺序，第一项作为默认清晰度。列表不足两项时 xgplayer 隐藏菜单，合法空列表使用原播放列表；请求失败或非法数据会明确报错。\n\n清晰度和倍速使用 xgplayer 原生菜单，不提供 `selectQuality()` 或底层播放器对象。清晰度选择、URL 切换、菜单状态以及切换期间的位置和播放状态处理遵循 xgplayer 原生行为。\n加载新资源重置位置、清晰度列表和 Key 版本，同一实例保留用户的倍速、音量及静音选择。\n\n### 控制栏与纯音频\n\n视频播放时约 3 秒无操作隐藏控制栏，鼠标移动、暂停和结束时显示，菜单展开期间保持显示。\n每次加载通过 `controlsvisibilitychange` 通知初始可见状态，之后仅在实际显隐改变时通知。\nHLS 轨道信息明确表示只有音频时，保持控制栏显示；无法可靠识别时沿用默认行为。无需传入 `mediaType`。\n纯音频沿用相同播放链路和默认控件；清晰度菜单取决于云接口返回的列表。\n学习上报、完成规则、断点存储和业务弹窗由调用方负责。\n\n## 播放控制\n\n| 方法 | 说明 |\n| --- | --- |\n| `play(playUrl?, options?)` | 传入云播放信息地址时从零加载新资源；省略或空字符串时继续播放。 |\n| `pause()` | 暂停并保留当前进度。 |\n| `stop()` | 暂停并归零，取消待完成操作；云请求被取消后，`play()` 从零重新加载当前资源。 |\n| `seek(seconds)` | 跳转到非负秒数；无资源或参数越界时抛出错误。 |\n| `destroy()` | 同步销毁实例并释放资源；重复调用安全返回，销毁后不可复用。 |\n| `on(event, handler)` | 持续订阅事件，返回取消订阅函数。 |\n| `once(event, handler)` | 订阅一次事件，返回取消订阅函数。 |\n| `off(event, handler)` | 取消指定订阅。 |\n\n浏览器可能因自动播放策略拒绝 `play()`，调用方应处理 Promise 拒绝：\n\n```ts\ntry {\n  await player.play()\n} catch (error) {\n  // 提示用户手动播放或重试\n}\n```\n\n`play(playUrl)` 在两阶段云请求、播放保护通过并发起媒体加载后完成，实际就绪由 `canplay` 通知。\n云请求每次超时为 10 秒；失败时 Promise 拒绝并发出 fatal `CLOUD_LOAD_ERROR`（`source: 'cloud'`）。\n加载期间的 `pause()` 和 `seek()` 保留最新意图；停止、切换资源或销毁以 `AbortError` 取消旧请求。\n\n## 事件\n\n状态事件包括：`play`、`playing`、`pause`、`stop`、`ended`、`loadedmetadata`、`canplay`、`waiting`、`timeupdate`、`durationchange`、`seeking` 和 `seeked`。\n\n这些事件返回：\n\n```ts\ninterface VideoPlayerState {\n  currentTime: number\n  duration: number | null\n  paused: boolean\n  ended: boolean\n}\n```\n\n`error` 事件返回 `VideoPlayerError`，通过 `source`、`code`、`message` 和 `fatal` 区分云接口、媒体、HLS 或播放保护错误。\n\n| 事件 | 载荷 |\n| --- | --- |\n| `ratechange` | `{ playbackRate: number }`，实际媒体倍速变化。 |\n| `controlsvisibilitychange` | `{ visible: boolean }`，控制栏实际显隐。 |\n\n`destroy` 事件无数据，每个实例仅通知一次，随后自动清理所有订阅：\n\n```ts\nplayer.on('destroy', () => {\n  // 实例已不可用\n})\nplayer.destroy()\n```\n\n公开 `destroy()` 在底层销毁调用结束后、返回前通知。底层主动销毁或销毁抛错时也会通知，\n但不保证通知时 DOM 已全部清理；底层销毁异常原样抛出。销毁监听器异常被隔离。\n销毁会取消待执行定位和播放检测，检测中的 `play()` 以 `AbortError` 拒绝。\n销毁后 `play()` 拒绝、`seek()` 抛错，`pause()`、`stop()` 和新增订阅为空操作。\n\n## 播放限制\n\n- 支持 hls.js 时优先使用 hls.js，否则回退到浏览器原生 HLS。\n- 构建目标为 Chrome 69+ 和 Safari 13+。\n- 加载新资源前会检测已知下载扩展和 `SourceBuffer` 覆盖；命中时拒绝播放。\n- 云播放接口必须支持 JSONP；SDK 自动取得 Key 版本，仅支持原生 HLS 的浏览器无法解密自定义 21 字节 Key。\n- 这是不兼容的接口重构：旧的直接媒体地址及手工清晰度、Key 参数已移除，调用方改传业务接口返回的 `playUrl`。\n\n## 开发\n\n本地演示需要在 `.env.local` 配置 `PLAY_INFO_AUTHORIZATION`，不要提交真实令牌。\n\n```bash\npnpm dev      # 启动演示页\npnpm test     # 运行单元测试\npnpm test:browser # 本地视频、音频和加密 HLS 的真实浏览器回归\npnpm build    # 类型检查并构建库与声明文件\npnpm preview  # 预览构建结果\n```\n\n演示页只从业务接口取得 `playUrl`，然后调用 `player.play(playUrl, { autoplay: false })`，与 LMS 接入方式一致。\n可用 `/?playUrl=...` 指定其他云播放信息地址。视频和纯音频使用相同入口。\n地址含查询参数时需 URL 编码；不要在文档、截图或提交内容中保存授权地址。\n\n浏览器回归需要 Node.js 22.18+、FFmpeg 和 Chrome，或运行 `pnpm exec playwright install chromium` 安装测试浏览器。\n可用 `CHROME_PATH` 指定 Chrome 路径。测试会生成并清理临时媒体，截图输出到被 Git 忽略的 `.browser-results/`。\n运行 `pnpm exec playwright install webkit` 后，可用 `BROWSER=webkit pnpm test:browser` 回归 WebKit；这不替代真实 Safari 的版本验收。\n真实云端演示回归使用 `CLOUD_DEMO_URL=http://127.0.0.1:5173 pnpm test:cloud`，要求该地址已启动开发服务器且授权有效。\n\n源码按职责组织：`player/` 提供公开门面，`playback/` 统一协调播放操作，`cloud/` 解析资源，\n`adapters/xgplayer/` 隔离底层实例，`plugins/hls/` 管理流与解密，`protection/` 和 `ui/` 分别处理检测与交互。\n公开入口和调用方式不变；内部模块不作为包导出。\n","readmeFilename":"README.md"}