ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Shaka Player 广告变现集成指南:MediaTailor、Interstitial 与 IMA SDK 实战

Shaka Player 广告变现集成指南:MediaTailor、Interstitial 与 IMA SDK 实战 Shaka Player 广告变现集成指南MediaTailor、Interstitial 与 IMA SDK 实战【免费下载链接】shaka-playerJavaScript player library / DASH HLS client / MSE-EME player项目地址: https://gitcode.com/GitHub_Trending/sh/shaka-playerShaka Player 通过统一的shaka.extern.IAdManager接口为应用提供了完整的广告投放 API覆盖 Interactive Media Ads 为主干结合仓库中 lib/ads/ 的源码实现系统讲解如何在你的播放器应用中接入这几种主流广告方案、如何监听广告事件以及如何定制广告管理器。读完本文你将能独立完成广告容器初始化、各类广告流的请求与播放、SCTE-35 场景下的自定义插播以及 IMA 深度集成的配置。1. 广告能力总览与核心 API 入口Shaka Player 的广告能力全部收敛在 Player 实例的 Ad Manager 对象上接口定义见 externs/shaka/ads.js 中的shaka.extern.IAdManager。该接口暴露的能力包括IMA Client SiderequestClientSideAds()、initClientSide()、updateClientSideAdsRenderingSettings()IMA DAI Server SiderequestServerSideStream()、replaceServerSideAdTagParameters()MediaTailorrequestMediaTailorStream()、addMediaTailorTrackingUrl()InterstitialsaddCustomInterstitial()、addAdUrlInterstitial()后者支持 VAST/VMAP通用能力setContainers()、getCuePoints()、getStats()、getCurrentAd()、setLocale()等。其中 MediaTailor 与 IMA 的 Server Side 请求方法都返回一个Promisestring即已插入广告的流清单 URI拿到后直接交给player.load(uri)即可播放这一模式在 lib/ads/media_tailor_ad_manager.js 的streamRequest()中通过内部streamPromise_实现。无论使用哪套广告技术接入的第一步都是获取 Ad Manager 并设置广告容器const adManager player.getAdManager(); // If youre using a non-UI build, this is the div youll need to create // for your layout. const csContainer controls.getClientSideAdContainer(); const ssContainer controls.getServerSideAdContainer(); // Note: If you are using Shaka UI this call is not necessary. adManager.setContainers(csContainer, ssContainer);说明如果你没有使用 Shaka 的 UI 库需要自己在video元素之上创建一个div作为广告容器若使用 Shaka UI控件会提供现成的客户端/服务端广告容器上述setContainers调用可省略。2. AWS Elemental MediaTailor 集成Shaka Player 提供了与 AWS Elemental MediaTailor 的深度集成支持Client Side、Server Side以及overlays浮层三种广告插入方式全部通过adManager.requestMediaTailorStream()一个入口完成。先初始化服务端逻辑与第 1 节的容器设置代码一致此处不再重复const video document.getElementById(video); const ui video[ui]; const controls video.ui.getControls(); const player controls.getPlayer(); const adManager player.getAdManager(); // If youre using a non-UI build, this is the div youll need to create // for your layout. const csContainer controls.getClientSideAdContainer(); const ssContainer controls.getServerSideAdContainer(); // Note: If you are using Shaka UI this call is not necessary. adManager.setContainers(csContainer, ssContainer);2.1 请求 Client Side 流Client Side 模式下MediaTailor 会返回一个包含广告决策信息的清单通常是 DASH MPD广告插入发生在客户端。requestMediaTailorStream()的第二个参数adsParams可携带自定义的广告参数例如这里的assetid与poddurationconst mediaTailorUrl https://d305rncpy6ne2q.cloudfront.net/v1/session/94063eadf7d8c56e9e2edd84fdf897826a70d0df/SFP-MediaTailor-VOD-HLS-DASH/out/v1/b94f3611978f419985a18335bac9d9cb/ddb73bf548a44551a0059c346226445a/eaa5485198bf497284559efb8172425e/index.mpd; const mediaTailorAdsParams { adsParams: { assetid: test2, podduration: 15, }, }; const uri await adManager.requestMediaTailorStream(mediaTailorUrl, mediaTailorAdsParams); player.load(uri);2.2 请求 Server Side 流Server Side 模式下广告在服务端被拼接进流中客户端拿到的就是一个干净的 HLS 主清单。此时adsParams可以不传const mediaTailorUrl https://ad391cc0d55b44c6a86d232548adc225.mediatailor.us-east-1.amazonaws.com/v1/session/d02fedbbc5a68596164208dd24e9b48aa60dadc7/singssai/master.m3u8; const uri await adManager.requestMediaTailorStream(mediaTailorUrl); player.load(uri);注意MediaTailor 的overlays浮层广告插入方式与 Server Side 完全一致即同样通过requestMediaTailorStream()请求并加载返回的流。从源码结构看MediaTailor 的会话信息请求、广告断点AdBreak解析、追踪 URL 上报等逻辑都封装在 lib/ads/media_tailor_ad_manager.js 的shaka.ads.MediaTailorAdManager中并通过 lib/ads/media_tailor_ad.js 与 lib/ads/svta_ad.js 等适配层把第三方广告对象统一映射为 Shaka 自己的shaka.extern.IAd接口。3. Interstitial插播集成Shaka Player 原生支持多种类型的 Interstitial覆盖了从标准到自定义的完整场景HLS InterstitialsRFC 8216bis 中的EXT-X-DATERANGE插播机制DASH Media Presentation InsertionInsertPresentation/ReplacePresentation即 MPD 级插播Custom Interstitials应用自定义的插播条目VAST / VMAP通过 URL 动态解析3.1 HLS Interstitials零配置原生支持HLS Interstitials 完全不需要应用介入Shaka Player 在解析播放清单时自动识别并调度。有以下几个值得了解的细节对应实现均可在 lib/ads/interstitial_ad_manager.js 中找到惰性资产列表解析Lazy asset list resolution。当插播引用了一个资产列表X-ASSET-LIST时Shaka 不会在清单解析时立即拉取而是等到播放即将到达该插播点时再解析。这避免了集中爆发式的广告决策请求也让广告决策更贴近真实播放时刻。提前多久解析由ads.interstitialPreloadAheadTime配置控制默认 10 秒见 lib/util/player_configuration.js也可以通过下述的逐插播偏移机制单独覆盖。源码中resolutionAheadTime_()与shouldResolveAssetListNow_()正是这套前瞻窗口 延迟解析逻辑的落地实现。Preload Date RangeRFC 8216bis Appendix F。一个CLASScom.apple.hls.preload的EXT-X-DATERANGE通过X-TARGET-ID指向另一个 Date Range用来告诉播放器该插播的资源可以提前多久解析。Shaka 通过addPreloadMetadata()将其换算成逐插播的解析偏移resolutionTimeOffset具体计算为Math.max(0, 目标startTime - 预加载Date Range的startTime)。Date Range 更新合并。后续出现的、共享同一个ID的EXT-X-DATERANGE标签会被合并处理后出现的标签可以补充之前没有的属性最典型的是X-PLAYOUT-LIMIT——在直播SGAIServer-Guided Ad Insertion流中常用它来提前截断插播、提前回到主内容。按照规范要求已经赋过值的属性不会被更改。Seek 进入直播广告插播。当开启ads.allowStartInMiddleOfInterstitial默认值为true见 lib/util/player_configuration.js时如果用户 seek 回到一个已经解析过的直播插播区间Shaka 会以反映新播放头位置的_HLS_start_offset重新请求其资产列表保证接续播出的正确性。3.2 DASH Media Presentation Insertion同样零配置DASH 的 MPD 级插播InsertPresentation/ReplacePresentation即 MPD alternate同样开箱即用无需任何应用干预。实现会遵循earliestResolutionTimeOffset属性它规定了可以在插播展示时间之前多少秒提前解析备选 MPD。当该属性缺失时回退使用ads.interstitialPreloadAheadTime配置值。3.3 Custom Interstitials完全可控的插播编排自定义插播对象是shaka.extern.AdInterstitial完整字段定义见 externs/shaka/ads.js。它接受一个可选的resolutionTimeOffset属性单位秒表示在startTime之前多久可以开始解析并预加载该插播的资源——它正好对应 DASH 的earliestResolutionTimeOffset属性与 HLS 的 preload Date Range 机制。当该属性为undefined或0时使用ads.interstitialPreloadAheadTime配置值。下面示例为了简洁都省略了该字段。基础示例——注册一个从第 10 秒开始、可跳过、带全套追踪事件的自定义插播const video document.getElementById(video); const ui video[ui]; const controls video.ui.getControls(); const player controls.getPlayer(); const adManager player.getAdManager(); // If youre using a non-UI build, this is the div youll need to create // for your layout. const csContainer controls.getClientSideAdContainer(); const ssContainer controls.getServerSideAdContainer(); // Note: If you are using Shaka UI this call is not necessary. adManager.setContainers(csContainer, ssContainer); adManager.addCustomInterstitial({ id: null, groupId: null, startTime: 10, endTime: null, uri: YOUR_URL, mimeType: null, isSkippable: true, skipOffset: 10, skipFor: null, canJump: false, resumeOffset: null, playoutLimit: null, once: true, pre: false, post: false, timelineRange: false, loop: false, overlay: null, displayOnBackground: false, currentVideo: null, background: null, clickThroughUrl: null, tracking: { impression: [YOUR_TRACKING_URL], clickTracking: [YOUR_TRACKING_URL], start: [YOUR_TRACKING_URL], firstQuartile: [YOUR_TRACKING_URL], midpoint: [YOUR_TRACKING_URL], thirdQuartile: [YOUR_TRACKING_URL], complete: [YOUR_TRACKING_URL], skip: [YOUR_TRACKING_URL], error: [YOUR_TRACKING_URL], resume: [YOUR_TRACKING_URL], pause: [YOUR_TRACKING_URL], mute: [YOUR_TRACKING_URL], unmute: [YOUR_TRACKING_URL], }, });关键字段语义与shaka.extern.AdInterstitial定义一致字段含义startTime/endTime插播在主时间轴上的起止时间秒endTime为null表示不确定uri插播内容地址可以是 Shaka 支持的任何类型MSE 或 src 均可mimeType已知时的 MIME 类型isSkippable/skipOffset/skipFor是否可跳过、跳过按钮何时出现、跳过按钮显示多久canJump是否允许跨过该插播jumpableresumeOffset插播结束后主内容恢复播放的位置表示相对插播计划展示时间的偏移直播广告替换场景必须为nullplayoutLimit整个插播的最长播出时长限制once/pre/post是否只播一次、是否在片头/片尾触发timelineRange在时间轴 UI 上显示为单点还是区间overlay/displayOnBackground/currentVideo/background浮层插播的几何布局与背景样式见 3.4 节clickThroughUrl点击广告时的跳转地址tracking各类追踪事件的 URL 列表类型见shaka.extern.AdTrackingEvent与 SCTE-35 结合可以监听timelineregionadded事件把清单中的 SCTE-35 时间线区间直接转成自定义插播。此时timelineRange在直播场景应设为true广告在时间轴上表现为一个区间canJump设为trueonce设为false同一标记在直播中可能循环触发const video document.getElementById(video); const ui video[ui]; const controls video.ui.getControls(); const player controls.getPlayer(); const adManager player.getAdManager(); // If youre using a non-UI build, this is the div youll need to create // for your layout. const csContainer controls.getClientSideAdContainer(); const ssContainer controls.getServerSideAdContainer(); // Note: If you are using Shaka UI this call is not necessary. adManager.setContainers(csContainer, ssContainer); player.addEventListener(timelineregionadded, (e) { const event e.detail; if (event.schemeIdUri ! urn:scte:scte35:2014:xmlbin) { return; } adManager.addCustomInterstitial({ id: event.id, groupId: null, startTime: event.startTime, endTime: event.endTime, uri: YOUR_URL, mimeType: null, isSkippable: false, skipOffset: null, skipFor: null, canJump: true, resumeOffset: player.isLive() ? null : 0, playoutLimit: null, once: false, pre: false, post: false, timelineRange: player.isLive(), // If true, the ad will appear as a range on the timeline. loop: false, overlay: null, displayOnBackground: false, currentVideo: null, background: null, clickThroughUrl: null, tracking: null, }); });3.4 Custom Overlay Interstitials浮层与多视频元素布局自定义浮层插播支持图片、视频渐进式或清单流以及网页浮层。浮层几何通过overlay/currentVideo两个shaka.extern.AdPositionInfo描述viewport、topLeft、size均为像素并由displayOnBackground决定是否把主视频缩小到背景。这类能力仅在启用多视频元素播放插播时可用。右上象限浮层示例主视频不动广告出现在右上 1/4 区域const video document.getElementById(video); const ui video[ui]; const controls video.ui.getControls(); const player controls.getPlayer(); const adManager player.getAdManager(); // If youre using a non-UI build, this is the div youll need to create // for your layout. const csContainer controls.getClientSideAdContainer(); const ssContainer controls.getServerSideAdContainer(); // Note: If you are using Shaka UI this call is not necessary. adManager.setContainers(csContainer, ssContainer); adManager.addCustomInterstitial({ id: null, groupId: null, startTime: 10, endTime: null, uri: YOUR_URL, mimeType: null, isSkippable: true, skipOffset: 10, skipFor: null, canJump: false, resumeOffset: null, playoutLimit: null, once: true, pre: false, post: false, timelineRange: false, loop: false, overlay: { // Show interstitial in upper right quadrant viewport: { x: 1920, // Pixels y: 1080, // Pixels }, topLeft: { x: 960, // Pixels y: 0, // Pixels }, size: { x: 960, // Pixels y: 540, // Pixels }, }, displayOnBackground: false, currentVideo: null, background: null, clickThroughUrl: null, tracking: null, });L-Shape 布局示例广告占满全屏背景主视频缩小到左上 1/4const video document.getElementById(video); const ui video[ui]; const controls video.ui.getControls(); const player controls.getPlayer(); const adManager player.getAdManager(); // If youre using a non-UI build, this is the div youll need to create // for your layout. const csContainer controls.getClientSideAdContainer(); const ssContainer controls.getServerSideAdContainer(); // Note: If you are using Shaka UI this call is not necessary. adManager.setContainers(csContainer, ssContainer); adManager.addCustomInterstitial({ id: null, groupId: null, startTime: 10, endTime: null, uri: YOUR_URL, mimeType: null, isSkippable: true, skipOffset: 10, skipFor: null, canJump: false, resumeOffset: null, playoutLimit: null, once: true, pre: false, post: false, timelineRange: false, loop: false, overlay: { viewport: { x: 1920, y: 1080, }, topLeft: { x: 0, y: 0, }, size: { x: 1920, y: 1080, }, }, displayOnBackground: true, currentVideo: { viewport: { x: 1920, y: 1080, }, topLeft: { x: 0, y: 0, }, size: { x: 960, y: 540, }, }, background: null, clickThroughUrl: null, tracking: null, });双框double box布局示例主视频缩小居中偏下广告占据右上方可自定义背景 CSSconst video document.getElementById(video); const ui video[ui]; const controls video.ui.getControls(); const player controls.getPlayer(); const adManager player.getAdManager(); // If youre using a non-UI build, this is the div youll need to create // for your layout. const csContainer controls.getClientSideAdContainer(); const ssContainer controls.getServerSideAdContainer(); // Note: If you are using Shaka UI this call is not necessary. adManager.setContainers(csContainer, ssContainer); adManager.addCustomInterstitial({ id: null, groupId: null, startTime: 10, endTime: null, uri: YOUR_URL, mimeType: null, isSkippable: true, skipOffset: 10, skipFor: null, canJump: false, resumeOffset: null, playoutLimit: null, once: true, pre: false, post: false, timelineRange: false, loop: false, overlay: { viewport: { x: 1920, // Pixels y: 1080, // Pixels }, topLeft: { x: 960, // Pixels y: 270, // Pixels }, size: { x: 960, // Pixels y: 540, // Pixels }, }, displayOnBackground: true, currentVideo: { viewport: { x: 1920, // Pixels y: 1080, // Pixels }, topLeft: { x: 160, // Pixels y: 360, // Pixels }, size: { x: 640, // Pixels y: 360, // Pixels }, }, background: content-box radial-gradient(crimson, skyblue), clickThroughUrl: null, tracking: null, });background字段接受任意合法的 CSSbackground属性值loop字段表示浮层插播是否循环播放仅对浮层有效且仅在启用多视频元素播放插播时受支持。3.5 VAST / VMAP通过 URL 动态解析插播addAdUrlInterstitial(url)会请求给定的 VAST/VMAP 地址解析响应并把其中的广告转换为插播条目后排队播放。从 lib/ads/interstitial_ad_manager.js 的addAdUrlInterstitial()实现看它使用shaka.net.NetworkingEngine.AdvancedRequestType.INTERSTITIAL_AD_URL发起请求并用shaka.util.TXml.parseXml(response.data, VAST,vmap:VMAP)解析 XML若解析失败会抛出shaka.util.Error.Code.VAST_INVALID_XML。const video document.getElementById(video); const ui video[ui]; const controls video.ui.getControls(); const player controls.getPlayer(); const adManager player.getAdManager(); // If youre using a non-UI build, this is the div youll need to create // for your layout. const csContainer controls.getClientSideAdContainer(); const ssContainer controls.getServerSideAdContainer(); // Note: If you are using Shaka UI this call is not necessary. adManager.setContainers(csContainer, ssContainer); const url https://pubads.g.doubleclick.net/gampad/ads?sz640x480iu/124319096/external/single_ad_samplesciu_szs300x250implsgdfp_req1envvpoutputvastunviewed_position_start1cust_paramsdeployment%3Ddevsite%26sample_ct%3Dlinearcorrelator; adManager.addAdUrlInterstitial(url);4. IMA SDK 集成客户端与服务端Shaka Player 与 Google Interactive Media AdsIMASDK 深度集成同时支持 Client Side 与 Server SideDAI广告插入两者都通过shaka.extern.IAdManager暴露。4.1 引入 SDK 脚本首先需要在页面中引入 Shaka UI 编译产物与 IMA 相关 SDKClient Side 用ima3.jsServer Side 用ima3_dai.js!DOCTYPE html html head !-- Shaka Player ui compiled library: -- script srcdist/shaka-player.ui.js/script !-- Shaka Player ui compiled library default CSS: -- link relstylesheet typetext/css hrefdist/controls.css !-- IMA HTML5 SDK (for serving Client Side ads): -- script typetext/javascript srchttps://imasdk.googleapis.com/js/sdkloader/ima3.js/script !-- IMA DAI SDK (for serving Server Side ads): -- script typetext/javascript srchttps://imasdk.googleapis.com/js/sdkloader/ima3_dai.js/script !-- Your application source: -- script srcmyapp.js/script /head /html获取 Ad Managerconst adManager player.getAdManager();4.2 客户端广告插入Client Side Ads客户端模式要求你先有广告标签ad tagURI。同样先初始化客户端逻辑并设置容器代码同第 1 节。初始化完成后可以在播放过程中的任意时刻请求广告const adsRequest new google.ima.AdsRequest(); // Your ad tag url should go here. We are using a sample ad tag from the // IMA HTML5 SDK implementation guide for this tutorial. adsRequest.adTagUrl https://pubads.g.doubleclick.net/gampad/ads?sz640x480iu/124319096/external/single_ad_samplesciu_szs300x250implsgdfp_req1envvpoutputvastunviewed_position_start1cust_paramsdeployment%3Ddevsite%26sample_ct%3Dlinearcorrelator; adManager.requestClientSideAds(adsRequest, /** adsRenderingSettings */ null);adsRequest的类型是google.ima.AdsRequest其完整字段可查阅 IMA HTML5 SDK 的 AdsRequest 参考文档。控制广告渲染initClientSide(container, video, adsRenderingSettings)可用自定义渲染设置初始化客户端广告之后可用updateClientSideAdsRenderingSettings()动态更新渲染设置const adsRenderingSettings new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete true; adManager.initClientSide(container, video, adsRenderingSettings); // Updates the ads rendering settings. adManager.updateClientSideAdsRenderingSettings(adsRenderingSettings);google.ima.AdsRenderingSettings的字段含义见 IMA 官方 AdsRenderingSettings 参考文档。4.3 服务端广告插入Server Side Ads / DAI服务端模式需要 Google Ad Manager 账号并将流托管在 Google Ad Manager 的服务器上官方入口见 https://admanager.google.com/。初始化逻辑同样与第 1 节一致。VOD 流requestServerSideStream()接收google.ima.dai.api.VODStreamRequest返回一个 Promiseresolve 出带广告的清单 URI可直接交给player.load()const streamRequest new google.ima.dai.api.VODStreamRequest(); // Your stream information will go here. We are using IMAs sample stream info // in this tutorial. streamRequest.contentSourceId 2528370; streamRequest.videoId tears-of-steel; const uri await adManager.requestServerSideStream(streamRequest); player.load(uri);shaka.extern.IAdManager.requestServerSideStream()的返回类型、参数结构见 externs/shaka/ads.js 以及 IMA DAI 的 VODStreamRequest 参考文档。LIVE 流使用LiveStreamRequest核心字段是assetKeyconst streamRequest new google.ima.dai.api.LiveStreamRequest(); // Your stream information will go here. We are using IMAs sample stream info // in this tutorial. streamRequest.assetKey sN_IYUG8STe1ZzhIIE_ksA; const uri await adManager.requestServerSideStream(streamRequest); player.load(uri);LiveStreamRequest的完整字段见 IMA DAI 的 LiveStreamRequest 参考文档。如果使用 Shaka 的 UI 库广告 UI跳过按钮、倒计时等会自动接入无需额外编码。5. 监听广告事件Shaka 会把 IMA 的 Client Side 与 Server Side 事件统一转换成自己的广告事件与对象便于应用用同一套代码处理所有广告类型。完整事件列表可查阅shaka.ads.AdManager的AdBreakReadyEvent等事件文档。注册一个最简单的监听器广告开始时在控制台打日志adManager.addEventListener(shaka.ads.Utils.AD_STARTED, () { console.log(An ad has started); });事件名常量定义在 lib/ads/ad_utils.js 的shaka.ads.Utils中常用事件包括ADS_LOADEDads-loaded一组广告已加载AD_STARTEDad-started广告即将开始AD_PLAYINGad-playing广告真正进入播放状态与AD_STARTED表示意图开始不同该事件保证广告媒体元素已进入playing状态、播放头真实推进AD_FIRST_QUARTILE/AD_MIDPOINT/AD_THIRD_QUARTILE播放进度 25% / 50% / 75%AD_COMPLETEad-complete、AD_STOPPED、AD_SKIPPED、AD_ERRORAD_VOLUME_CHANGED、AD_MUTED、AD_PAUSED、AD_RESUMEDAD_CLICKED、AD_PROGRESSCUEPOINTS_CHANGEDad-cue-points-changed插播点集合变化AD_BREAK_READYad-break-ready、AD_BREAK_STARTED、AD_BREAK_ENDED广告插播ad break生命周期IMA_AD_MANAGER_LOADEDima-ad-manager-loaded、IMA_STREAM_MANAGER_LOADEDima-stream-manager-loaded底层 IMA 对象就绪见第 6 节每个 Shaka 广告事件都附带原始 SDK 事件与广告对象如果可用。大多数应用用不到但需要时可以通过事件对象取到// Note that unlike in the previous example, we are capturing the AD_STARTED // event object here (the e parameter of the lambda function) so we can access // its properties. adManager.addEventListener(shaka.ads.Utils.AD_STARTED, (e) { const sdkAdObject e[sdkAdObject]; const originalEvent e[originalEvent]; });6. 面向 IMA 高级用户的底层对象访问如果你已有一套 IMA 集成要接入 Shaka或者需要使用 Shaka API 未暴露的更细粒度 SDK 能力可以监听底层 IMA 对象加载完成的事件直接拿到 IMA 的google.ima.AdsManagerClient Side或google.ima.dai.api.StreamManagerServer SideadManager.addEventListener(shaka.ads.Utils.IMA_AD_MANAGER_LOADED, (e) { const imaAdManager e[imaAdManager]; }); adManager.addEventListener(shaka.ads.Utils.IMA_STREAM_MANAGER_LOADED, (e) { const imaStreamManager e[imaStreamManager]; });拿到对象后的用法可参考 IMA 官方的 AdsManager 参考文档 与 StreamManager 参考文档。7. 无 Cookie 环境下的受限广告投放Limited Ads服务端 IMA SDK 允许在用户未同意或拒绝 Cookie 授权时投放受限广告limited ads。做法是按照 IMA 的 limited ads 指南通过StreamRequest.adTagParameters设置ltd参数同时为了让清单与分片请求不带 Cookie配置合适的requestFilter。需要注意request.withCredentials默认为false因此只有在你代码的其他部分显式开启过它时才需要做如下覆盖player.getNetworkingEngine().registerRequestFilter(function(type, request, context) { if (type shaka.net.NetworkingEngine.RequestType.MANIFEST || type shaka.net.NetworkingEngine.RequestType.SEGMENT) { request.withCredentials false; } });requestFilter是 ShakaNetworkingEngine的标准扩展点见 lib/net/networking_engine.js应用可按RequestType对清单、分片等请求做任意改写。8. 自定义 Ad Manager 实现Shaka 的广告架构支持完全自定义的 Ad Manager。所有广告管理器都要实现shaka.extern.IAdManager接口定义见 externs/shaka/ads.js。要让 Player 使用自定义实现需要在实例化 Player之前注册工厂函数// myapp.CustomAdManager is a placeholder name for your ad manager implementation. shaka.Player.setAdManagerFactory(() new myapp.CustomAdManager());在 lib/player.js 中可以看到shaka.Player.setAdManagerFactory(factory)是静态入口而默认实现shaka.ads.AdManager的注册同样通过该工厂机制完成见 lib/ads/ad_manager.jsPlayer 内部通过getAdManager()lib/player.js按需实例化。这意味着你可以在不修改 Player 核心逻辑的前提下将广告决策、插播调度甚至第三方广告 SDK 封装成自己的实现无缝接入。9. 常见问题与最佳实践小结容器初始化非 UI 构建必须自建div广告容器并调用adManager.setContainers(csContainer, ssContainer)UI 构建下该调用可省略。Server Side 流程一致性无论 MediaTailor 还是 IMA DAIrequestServerSideStream()/requestMediaTailorStream()都返回已插入广告的清单 URI之后统一走player.load(uri)。解析时机控制HLS / DASH 插播默认在播放接近插播点时ads.interstitialPreloadAheadTime默认 10 秒才解析资源既避免请求突增也保证决策贴近播放可用逐插播的resolutionTimeOffset自定义插播、earliestResolutionTimeOffsetDASH或 preload Date RangeHLS单独微调。SCTE-35 联动监听timelineregionadded并筛选urn:scte:scte35:2014:xmlbin的区间可把信令插播无缝接入统一的自定义插播队列。事件统一化监听 Shaka 自有事件如shaka.ads.Utils.AD_STARTED即可同时覆盖 Client Side 与 Server Side需要底层 SDK 对象时再用IMA_AD_MANAGER_LOADED/IMA_STREAM_MANAGER_LOADED获取。扩展性通过shaka.Player.setAdManagerFactory()可在播放器创建前注入自定义 Ad Manager 实现满足深度定制需求。围绕广告模块的更多实现细节可继续研读仓库中的 lib/ads/各类 AdManager 与适配器、externs/shaka/ads.js全部广告相关类型定义以及 test/ads/ 下的单元与集成测试如interstitial_ad_manager_unit.js、vast_interstitial_parser_unit.js这些测试用例对理解各广告技术的边界行为很有帮助。【免费下载链接】shaka-playerJavaScript player library / DASH HLS client / MSE-EME player项目地址: https://gitcode.com/GitHub_Trending/sh/shaka-player创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表