diff --git a/packages/artplayer-plugin-vast/README.md b/packages/artplayer-plugin-vast/README.md index 785687886..9dc39247d 100644 --- a/packages/artplayer-plugin-vast/README.md +++ b/packages/artplayer-plugin-vast/README.md @@ -1,6 +1,6 @@ # artplayer-plugin-vast -vast plugin for ArtPlayer +VAST plugin for ArtPlayer ## Demo diff --git a/packages/artplayer-plugin-vast/package.json b/packages/artplayer-plugin-vast/package.json index f1a76306a..94efc95db 100644 --- a/packages/artplayer-plugin-vast/package.json +++ b/packages/artplayer-plugin-vast/package.json @@ -1,8 +1,8 @@ { "license": "MIT", - "version": "1.0.0", + "version": "1.0.1", "name": "artplayer-plugin-vast", - "description": "vast plugin for ArtPlayer", + "description": "VAST plugin for ArtPlayer", "main": "dist/artplayer-plugin-vast.js", "legacy": "dist/artplayer-plugin-vast.legacy.js", "module": "dist/artplayer-plugin-vast.esm.js", diff --git a/packages/artplayer-plugin-vast/src/index.js b/packages/artplayer-plugin-vast/src/index.js index 612e7e284..50dade9da 100644 --- a/packages/artplayer-plugin-vast/src/index.js +++ b/packages/artplayer-plugin-vast/src/index.js @@ -3,7 +3,7 @@ import { Player, PlayerOptions, loadImaSdk } from '@glomex/vast-ima-player'; export default function artplayerPluginVast(callback) { return async (art) => { const { template, constructor } = art; - const { createElement, setStyles, append } = constructor.utils; + const { createElement, setStyles } = constructor.utils; const { $video, $player } = template; await loadImaSdk(); @@ -11,45 +11,101 @@ export default function artplayerPluginVast(callback) { const ima = google.ima; const adsRenderingSettings = new ima.AdsRenderingSettings(); + adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; + adsRenderingSettings.enablePreloading = true; + const playerOptions = new PlayerOptions(); + let isAdPlaying = false; + let imaPlayer = null; + let $container = null; - const id = `art-${Date.now()}`; - const $container = createElement('div'); - append($player, $container); - $container.id = id; - setStyles($container, { - position: 'absolute', - inset: '0', - width: '100%', - height: '100%', - zIndex: '150', - display: 'none', - }); + function createContainer() { + const container = createElement('div'); + const id = `art-vast-${Date.now()}`; + container.id = id; + setStyles(container, { + position: 'absolute', + inset: '0', + width: '100%', + height: '100%', + zIndex: '150', + backgroundColor: 'black', + display: 'none', + pointerEvents: 'auto', + }); + return container; + } - const imaPlayer = new Player(ima, $video, $container, adsRenderingSettings, playerOptions); + function initPlayer() { + $container = createContainer(); + $player.appendChild($container); + imaPlayer = new Player(ima, $video, $container, adsRenderingSettings, playerOptions); + + // ✅ 事件绑定 + imaPlayer.onAdStarted = () => { + isAdPlaying = true; + $container.style.display = 'block'; + art.pause(); + }; + + imaPlayer.onAdEnd = () => { + isAdPlaying = false; + $container.style.display = 'none'; + art.play(); + }; + + imaPlayer.onAdError = (error) => { + console.error('VAST Ad Error:', error); + isAdPlaying = false; + $container.style.display = 'none'; + art.play(); + }; + } + + function destroyPlayer() { + if ($container && $container.parentNode) { + $container.parentNode.removeChild($container); + } + $container = null; + imaPlayer = null; + } function playUrl(url) { - const playAdsRequest = new ima.AdsRequest(); - playAdsRequest.adTagUrl = url; - imaPlayer.playAds(playAdsRequest); + if (isAdPlaying) return; + if (!imaPlayer) initPlayer(); + const request = new ima.AdsRequest(); + request.adTagUrl = url; + imaPlayer.playAds(request); } function playRes(res) { - const playAdsRequest = new ima.AdsRequest(); - playAdsRequest.adsResponse = res; - imaPlayer.playAds(playAdsRequest); + if (isAdPlaying) return; + if (!imaPlayer) initPlayer(); + const request = new ima.AdsRequest(); + request.adsResponse = res; + imaPlayer.playAds(request); } if (typeof callback === 'function') { - await callback({ art, id, ima, imaPlayer, $container, playUrl, playRes }); + await callback({ + art, + playUrl, + playRes, + ima, + imaPlayer, + get container() { + return $container; + }, + }); } return { name: 'artplayerPluginVast', + destroy: destroyPlayer, }; }; } if (typeof window !== 'undefined') { - window['artplayerPluginVast'] = artplayerPluginVast; + window.artplayerPluginVast = artplayerPluginVast; } diff --git a/packages/artplayer-plugin-vast/types/artplayer-plugin-vast.d.ts b/packages/artplayer-plugin-vast/types/artplayer-plugin-vast.d.ts index 82c2445a8..f2b27c916 100644 --- a/packages/artplayer-plugin-vast/types/artplayer-plugin-vast.d.ts +++ b/packages/artplayer-plugin-vast/types/artplayer-plugin-vast.d.ts @@ -1,20 +1,34 @@ import type Artplayer from 'artplayer'; +import { Player } from '@glomex/vast-ima-player'; export = artplayerPluginVast; export as namespace artplayerPluginVast; -type Option = (params: { +declare global { + interface Window { + artplayerPluginVast?: typeof artplayerPluginVast; + } +} + +type PlayUrlFn = (url: string) => void; +type PlayResFn = (res: string) => void; + +interface VastPluginContext { art: Artplayer; - id: string; - ima: any; - imaPlayer: any; - $container: HTMLDivElement; - playUrl: (url: string) => void; - playRes: (res: string) => void; -}) => void; + ima: typeof google.ima; + imaPlayer: Player; + playUrl: PlayUrlFn; + playRes: PlayResFn; + container: HTMLDivElement | null; +} -type Result = { +export type ArtplayerPluginVastOption = (params: VastPluginContext) => void | Promise; + +export interface ArtplayerPluginVastInstance { name: 'artplayerPluginVast'; -}; + destroy?: () => void; +} -declare const artplayerPluginVast: (option: Option) => (art: Artplayer) => Result; +declare function artplayerPluginVast( + option: ArtplayerPluginVastOption, +): (art: Artplayer) => ArtplayerPluginVastInstance;