xgplayer-cast 投屏插件实战指南:AirPlay 与 Chromecast 的接入、配置与原理剖析
发布时间:2026/9/26 7:39:23来源:尧图网络
音视频前端【免费下载链接】xgplayerA HTML5 video player with a parser that saves traffic项目地址https://gitcode.com/gh_mirrors/xg/xgplayer点击查看免费下载导读xgplayer-cast 是 xgplayer 生态中的投屏Casting插件为 xgplayer 播放器补充了 Apple AirPlay 与 Google Chromecast 两大无线投屏能力。本文将围绕该插件完整讲解从零接入的代码示例、全部配置参数与默认值、编程式投屏 API、事件体系、Chromecast 与 AirPlay 两条投屏链路的时序流程以及投屏媒体 URL 解析的底层原理并结合仓库源码packages/xgplayer-cast/src逐一印证每个配置项和流程的实现细节。读完本文你将掌握如何在现有 xgplayer 项目中快速接入投屏、如何处理 MSE 等本地媒体管线与投屏的冲突、如何为接收端提供可解析的媒体 URL以及如何用远端控制 API 驱动 Chromecast 接收端。插件定位与版本前提xgplayer-cast 是独立的 npm 包以CastPlugin作为 xgplayer 的插件注册使用。从 package.json 可以看到它依赖eventemitter3并以xgplayer3.0.26作为 peerDependencyUMD 全局名为CastPlugin同时带*.scss/*.css副作用标记样式需随包引入。需要特别留意两个版本门槛见 README.md 末尾 NotesAirPlay 从 xgplayer 3.0.25 开始支持Chromecast 从 xgplayer 3.0.26 开始支持当前仓库版本即为 3.0.26。此外两条投屏链路都要求接收端设备Apple TV、Chromecast 电视棒等能独立拉取并解密媒体流因此DRM 加密内容FairPlay、Widevine、clearkeys 等无法投屏——解密许可证与当前浏览器会话绑定接收端无法获得有效密钥播放必然失败。快速接入最小集成示例基础用法在 xgplayer 基础上引入插件与样式然后在plugins中注册CastPlugin并通过cast配置项打开所需协议import Player from xgplayer import CastPlugin from xgplayer-cast import xgplayer/dist/xgplayer.min.css const player new Player({ id, url, autoplay: true, plugins: [CastPlugin], cast: { showIcon: true, airplay: true, chromecast: true } })从源码看插件在afterCreate()阶段完成安装plugin.ts非video媒体类型或disable: true时直接跳过随后分别按isAirPlayAvailable()与normalizeChromecastConfig()shouldInstallChromecast()的结果实例化 Airplay / Chromecast 两个适配器最后根据可用协议更新控制栏投屏图标的显隐。Android / Chromecast 场景最小配置使用内置默认 Sender SDK// Minimal — uses built-in default Sender SDK URL const player new Player({ id, url, plugins: [CastPlugin], cast: { airplay: true, chromecast: true } })这里的默认 Sender SDK URL在源码中有明确定义chromecast-config.tshttps://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework1只要chromecast: true或配置对象未提供sdkUrl/sdkLoader就会回退到该官方地址。自定义 SDK URL内网、代理或自托管// Custom SDK URL (intranet, proxy, or self-hosted) const player new Player({ id, url, plugins: [CastPlugin], cast: { chromecast: { sdkUrl: https://your-cdn.example.com/cast_sender.js, receiverApplicationId: YOUR_APP_ID, autoJoinPolicy: origin_scoped } } })SDK 加载由 chromecast-sdk.ts 统一处理优先使用宿主页面已存在的window.cast.framework/window.chrome.cast否则动态注入script监听__onGCastApiAvailable回调会保留宿主页面原有回调并处理超时、加载失败等异常失败后重置缓存 Promise允许后续重试。SDK 加载完成且destroy()未被调用时才会初始化CastContext。配置参数全解以下为 README.md 中的完整配置表并补充源码中的默认值与实现细节NameTypesDefaultDescriptionshowIconbooleantrue是否在控制栏显示投屏图标airplaybooleantrue可用时是否启用 Apple AirPlaychromecastboolean | objecttrue启用 Chromecast。true使用默认 Sender SDK URL对象形式可覆盖 SDK 加载与会话选项chromecast.sdkUrlstringGoogle Cast Sender SDK URLSender SDK 地址。默认官方 Google Cast Sender SDK可覆盖为内网/CDN/代理部署chromecast.sdkLoaderfunctionnull自定义异步 SDK 加载器。适用于宿主应用自行管理脚本加载的场景不接收参数必须返回一个 Promisechromecast.receiverApplicationIdstringReceiver 应用 ID。空字符串表示使用默认媒体接收器chromecast.autoJoinPolicystringorigin_scoped会话自动加入策略chromecast.loadSdkTimeoutnumber3000Sender SDK 加载超时毫秒autoplayOnCastboolean继承投屏前的播放态投屏开始后接收端是否自动播放。省略时插件保留调用requestCast()那一刻的播放/暂停状态播放中内容在接收端继续播放暂停内容保持暂停显式传true/false可覆盖。AirPlay 可能先发一次本地 play 以建立路由当解析值为false时随即暂停Chromecast 将该值映射为LoadRequest.autoplayshowAirplayMutedTipbooleantrueAirPlay 连接时是否提示用户取消静音源码层面的补充解读默认值出处插件defaultConfig定义在 plugin.ts与表格完全一致position: CONTROLS_RIGHT、index: 7、showIcon: true、autoplayOnCast: undefined、airplay: true、chromecast: true、showAirplayMutedTip: true。chromecast 配置归一化chromecast-config.ts 的normalizeChromecastConfig()会把false/true/null/ 对象统一归一为完整配置对象loadSdkTimeout仅接受正数否则回退3000autoJoinPolicy默认origin_scopedenabled默认true对象中显式enabled: false才会关闭。autoJoinPolicy 映射chromecast.ts 将字符串策略如origin_scoped转成chrome.cast.AutoJoinPolicy枚举找不到时回退ORIGIN_SCOPED。receiverApplicationId 语义空字符串时_initCastContext()会改用chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_IDchromecast.ts即默认媒体接收器业务侧接入自定义 Receiver 时才需要传入自己的 App ID。sdkLoader 契约必须是返回 Promise 的函数chromecast-sdk.tsPromise resolve 后会校验window.cast.framework与window.chrome.cast是否就绪。对外 API编程式投屏与远端控制Method NameDescriptionrequestCast(protocol?)编程式打开系统投屏面板AirPlay 设备列表或 Chromecast 设备选择器。传airplay或chromecast强制指定协议省略时自动选择当前最优可用协议。没有任何可用协议时无效果getCastRemoteState(protocol?)返回所选协议暴露的远端接收端最新状态。目前仅 Chromecast 支持controlCastRemote(action, payload?, protocol?)控制所选协议暴露的远端接收端。目前 Chromecast 支持play、pause、toggle、seek、stop、setVolume、mute、unmuterequestCast 的实现路径plugin.ts 中requestCast()先通过_getPreferredCastProtocol()选协议排序时 Chromecast 优先于 AirPlayplugin.ts随即捕获本地播放/暂停态与当前时间作为 handoff 状态并向对应适配器派发cast_request事件负载含protocol、autoplay、handoffState。控制栏图标的点击处理_doCast同样走requestCast()并会先emitUserAction(e, cast)记录用户行为。controlCastRemote 的远端动作chromecast-remote-controller.ts 中control(action, payload)支持的动作明细play/pause/toggle调用RemotePlayerController.playOrPause()seek取payload.time ?? payload写入remotePlayer.currentTime后调用seek()stop调用controller.stop()setVolume取payload.volume ?? payload夹取到[0, 1]后调用setVolumeLevel()mute/unmute调用muteOrUnmute()mute默认muted: true。同时插件保留了controlCast(action, payload?, protocol?)作为向后兼容别名内部直接转发给controlCastRemoteplugin.ts新集成建议统一使用controlCastRemote。事件体系README 事件表中明确列出两个事件Event NamePayloadDescriptioncast_error{ protocol, code, message, error?, media? }Chromecast 的 setup、session、媒体解析或远端媒体加载失败时触发cast_remote_state_change{ protocol, available, connected, mediaLoaded, playerState, paused, currentTime, duration, volume, muted, title, contentId }Chromecast 远端控制器在 CAF 上报远端播放器状态变化时触发从源码还可以观察到另外两个贯穿全流程的事件README 的时序图与流程描述中大量使用cast_availability_change{ protocol, availability }AirPlay 的webkitplaybacktargetavailabilitychanged、Chromecast 的CAST_STATE_CHANGED都会驱动它更新插件据此决定图标显隐plugin.tscast_target_change{ protocol, isCasting }会话/路由建立与结束时发出业务侧用它切换投屏态 UI。cast_remote_state_change的完整字段来自 chromecast-remote-controller.ts控制器用 CAF 的RemotePlayerRemotePlayerController监听RemotePlayerEventType.ANY_CHANGE把isConnected、isMediaLoaded、isPaused、currentTime、duration、volumeLevel、isMuted、mediaInfo.metadata.title、mediaInfo.contentId等映射成结构化负载。Chromecast 完整流程剖析下图阴影区域为原生 CAF 与接收端边界跨边界的调用/事件均为浏览器/设备原生 API、原生事件、设备选择器交互或接收端媒体行为图出自 README.md关键设计点独立接收端媒体会话Chromecast 在接收端上运行独立的媒体会话不走本地video路由。调用session.loadMedia()之前插件会先暂停本地播放器_pauseLocalForRemoteLoadchromecast.ts避免本地流式插件在接收端接管后仍继续解码播放若接收端加载失败则恢复本地播放_resumeLocalAfterRemoteLoadError。媒体去重与时间续播每次加载前用 URL contentType contentUrl hlsSegmentFormat 等生成媒体身份getMediaIdentityloadstart触发的reloadMedia()只在媒体身份变化时重新加载URL 未变化时复用远端当前时间点避免切回旧位置chromecast.ts。会话结束状态回写SESSION_ENDING时先捕获远端 paused 状态与 currentTimeSESSION_ENDED/SESSION_START_FAILED/SESSION_RESUME_FAILED时把捕获的状态写回本地applyRouteStateToLocal再发出cast_target_change({ isCasting: false })chromecast.ts。使用建议README 原文用cast_target_change把业务 UI 切入投屏态用cast_remote_state_change渲染接收端状态用controlCastRemote()做远端播放/暂停/seek 控制继续驱动本地 video 元素只会控制本地媒体。投屏媒体解析receiver-readable URL 与 contentTypeAirPlay 与 Chromecast 共用同一套媒体解析器。接收端可读的网络 URL 依次从curDefinition.url、当前流式插件的core.config.url、config.url、媒体source元素中解析见 cast-media.ts并在存在后续网络 URL 时跳过blob:、mediastream:、data:、file:等本地 URL。validateUrl对上述非法协议会直接抛出错误cast-media.ts。contentType 解析优先级对于带签名或无扩展名的 URL业务代码应显式提供contentType、mimeType或type。解析器按以下优先级取用preProcessUrl返回对象中的类型当前清晰度项player.curDefinitionurl中的选中 source 项顶层播放器配置URL 扩展名兜底推断短别名归一化hls、m3u8、dash、mpd、mp4等别名会被归一化为接收端 MIME 类型完整映射表见 cast-media.tshls/m3u8→application/x-mpegURLdash/mpd→application/dashxmlmp4/m4v/fmp4→video/mp4另有webm、ogg、ts/mp2t、m4a、aac、mp3、wav、flac等音频视频类型。尽量使用完整 MIME 值HLS 用application/x-mpegURLDASH 用application/dashxmlMP4 用video/mp4。三种推荐写法// Recommended for definition lists const player new Player({ id, definition: { list: [ { definition: 720p, url: https://cdn.example.com/play?id720, contentType: application/x-mpegURL } ] }, plugins: [CastPlugin], cast: { chromecast: true } })// Recommended when the business layer signs or rewrites URLs const player new Player({ id, url: https://cdn.example.com/play?idmain, contentType: application/x-mpegURL, preProcessUrl(url, ext) { if (ext?.scene cast ext?.protocol chromecast) { return { url: signForReceiver(url), contentType: application/x-mpegURL } } return { url } }, plugins: [CastPlugin], cast: { chromecast: true } })// Source-array form is also supported const player new Player({ id, url: [ { src: https://cdn.example.com/play?idmain, type: application/x-mpegURL } ], plugins: [CastPlugin], cast: { chromecast: true } })preProcessUrl的第二个参数ext由解析器构造cast-media.ts包含{ scene: cast, protocol, contentType }业务侧可据此区分 AirPlay/Chromecast 场景分别签名。解析器还会把contentUrl、streamType、duration、metadata、customData、hlsSegmentFormat、hlsVideoSegmentFormat等可选MediaInfo字段原样转发给接收端cast-media.ts。AirPlay 与 MSE原生路由的边界AirPlay 在 Safari 原生video直接播放接收端可读的 HLS/MP4 URL 时效果最佳。MSE 与 ManagedMediaSource 会构建发送端本地媒体管线通常表现为blob:源或srcObjectAirPlay 设备无法从发送页拉取该本地源可能出现本地媒体继续播放或接收端只有声音的问题。下图阴影区域为原生 Safari/WebKit 与接收端边界图出自 README.md实现要点对应源码可用性检测isAirPlayAvailable()要求媒体元素同时具备webkitShowPlaybackTargetPicker函数与WebKitPlaybackTargetAvailabilityEvent事件类型airplay.ts。按请求启用路由而非安装时启用插件在cast_request时设置x-webkit-airplayallow并移除disableRemotePlayback_allowRemotePlayback这样不会干扰那些临时设置disableRemotePlayback的 Safari ManagedMediaSource 初始化airplay.ts。不因打开选择器就动本地管线当前源是 MSE/MMS/srcObject/blob:时插件先用与 Chromecast 相同的源优先级解析出原始网络 URL添加带data-xgplayer-cast-airplaytrue标记的source回退HLS 类型会转成application/vnd.apple.mpegurlairplay.ts但不会因此挂起流式插件或替换媒体源。WebKit 确认无线目标后再切换webkitcurrentplaybacktargetiswirelesschanged(true)之后才清除本地 MSE 源、挂起流式插件_suspendMSEPluginplugin.ts、把网络 URL 赋给媒体元素并在loadedmetadata后 seek 到最新本地currentTime。路由回落防抖webkitcurrentplaybacktargetiswirelesschanged(false)会经 1000ms 防抖确认AIRPLAY_ROUTE_SETTLE_DELAY_MS避免 AirPlay 交接期间的瞬时抖动误报断开airplay.ts。静音提示WebKit 对静音媒体元素会认为无需音频输出设备而拒绝路由对应 WebKit bug 146366因此静音时插件不会打开选择器而是显示CAST_UNMUTE_TIP提示文案3 秒后自动消失是否显示由showAirplayMutedTip控制airplay.ts。流式插件恢复投屏结束恢复时_resumeMSEPlugin会重新注册原流式插件并把startTime临时设置为续播时间点plugin.ts。面向业务集成的推荐模式README 原文在必须使用 AirPlay 的 Safari/iOS 上尽量使用原生 HLS——这是最可靠的路径因为原生选择器打开时媒体元素已持有接收端可读 URL在url、definition.list[].url或preProcessUrl中提供可直接播放的 HLS 或 MP4 URL避免为 AirPlay 媒体使用 DRM、加密的仅会话 URL、blob:、data:与 localhost URL提供 AirPlay 兼容性广的 HLS 变体例如面向目标接收端使用保守 profile/level 的 H.264/AAC若字幕需要出现在 AirPlay 接收端上请将字幕保留在 HLS manifest 中。Cast Handoff媒体所有权交接插件把投屏视为本地 xgplayer 与接收端之间的媒体所有权切换requestCast()调用瞬间捕获本地播放/暂停状态captureLocalStateForCast见 cast-handoff-state.tsautoplayOnCast可覆盖该状态Chromecast 在接收端加载前刷新本地currentTime_resolveInitialCurrentTimechromecast.ts使设备选择耗时不会让接收端倒退到较早的时间点接收端媒体必须是 receiver-readable URL从接收端返回时插件先恢复本地currentTime与播放/暂停状态再发出cast_target_change({ isCasting: false })——业务代码可借此事件在本地状态恢复完成后刷新 UI状态恢复逻辑applyRouteStateToLocal见 cast-handoff-state.ts。iOS Safari 的已知限制从 AirPlay 返回时无法保证有声媒体自动本地播放。插件会恢复时间点并在路由处于播放态时尝试一次play()但 Safari 可能因自动播放策略拒绝业务 UI 应处理暂停态并展示常规播放按钮。术语表TermScopeMeaningNotesCast requestCross-platform用户或业务代码发起、请求浏览器/设备选择器开始投屏的动作由投屏图标或requestCast(protocol?)触发。请求只启动协议选择不保证远端目标已连接CAFChromecastCast Application Framework即cast.framework暴露的高层 Google Cast SDK APIWeb Sender 集成使用CastContext、RemotePlayer、RemotePlayerController等 CAF API 管理会话、接收端状态与远端控制底层媒体消息仍使用chrome.cast.media.*如MediaInfo、LoadRequestHandoffCross-platform媒体从本地 xgplayer 实例移交到远端接收端的过渡跨协议媒体状态层。请求时捕获 receiver-readable 媒体 URL 与播放/暂停意图接收端接管时使用最新可用本地时间HandshakeProtocol-specific建立路由或会话所需的协议特定激活步骤属于实现细节而非媒体状态契约。AirPlay 可能需要路由激活后的本地play()随后若 handoff 状态为暂停则再次暂停Chromecast 改用requestSession()与loadMedia()Local mediaCross-platform由发送页本地video元素与本地流式插件控制的媒体Chromecast 在接收端加载前暂停本地播放器加载失败则恢复AirPlay 场景 Safari/WebKit 可能将同一媒体元素继续路由到接收端Remote mediaCross-platform接收端设备拥有的媒体Chromecast 通过 CAFRemotePlayer暴露独立远端媒体会话AirPlay 无等价接收端控制 API经 WebKit 媒体元素路由驱动Receiver-readable URLBusiness integration接收端设备可直接拉取的媒体 URLblob:、data:、file:、mediastream:、localhost、DRM/会话绑定或仅发送端可见的 URL 均不是合法接收端媒体 URL。业务代码可通过preProcessUrl或contentType元数据提供接收端兼容 URL版本与限制小结AirPlay 需要 xgplayer3.0.25Chromecast 需要 xgplayer3.0.26当前仓库的 xgplayer-cast/package.json 版本为 3.0.26peerDependency 为xgplayer: 3.0.26加密视频不支持投屏AirPlay / Chromecast 要求接收端设备Apple TV、Chromecast 电视棒独立拉取并解密媒体流DRM 保护内容FairPlay、Widevine、clearkeys 等的许可证与当前浏览器会话绑定接收端无法获得有效密钥播放会失败Chromecast 远端控制基于 CAFRemotePlayer/RemotePlayerControllerAirPlay 不暴露同等的独立接收端控制 API因此 AirPlay 继续走 Safari/WebKit 的原生媒体元素路由建议在实际项目中先用浏览器内置的投屏设备或在 Safari/iOS 上验证 AirPlay 路由做端到端验证再决定是否接入preProcessUrl签名、自定义 Receiver App 等进阶能力。赞分享音视频前端【免费下载链接】xgplayerA HTML5 video player with a parser that saves traffic项目地址https://gitcode.com/gh_mirrors/xg/xgplayer点击查看免费下载相关推荐Immich Chromecast 投屏支持Google Cast 协议接入原理、启用方式与源码解析Immich Chromecast 投屏支持Google Cast 协议接入原理、启用方式与源码解析 本文以 Immich 的 Chromecast 投屏文档后端前端移动开发音视频计算机视觉Pinpoint WebSphere 插件接入指南配置详解与源码级原理剖析Pinpoint WebSphere 插件接入指南配置详解与源码级原理剖析 导读 本文以 Pinpoint 仓库中 agent module/plugins/后端可观测性APM链路追踪微服务Pinpoint Informix JDBC 插件接入指南配置详解与源码级原理剖析Pinpoint Informix JDBC 插件接入指南配置详解与源码级原理剖析 本文基于 Pinpoint 仓库中的 informix jdbc 插件官方后端可观测性APM链路追踪微服务创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网