mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-25 16:11:20 -08:00
docs(site): [SITE-04] document Ads and VAST compatibility in both languages
This commit is contained in:
1 parent
2305f9d7c7
commit
558e946ae5
97 files changed
+4434
-1974
No files matched your search
@@ -21,6 +21,8 @@ not a VitePress page. Keep both URL surfaces compatible.
|
||||
| `docs/plugin/asr.md`, `docs/en/plugin/asr.md` | PCM/WAV callbacks, subtitle rendering, audio routing, lifecycle and runtime types | `/document/plugin/asr.html`, `/document/en/plugin/asr.html` |
|
||||
| `docs/plugin/auto-thumbnail.md`, `docs/en/plugin/auto-thumbnail.md` | Progressive JPEG extraction, limits, decoder ownership and asynchronous runtime types | `/document/plugin/auto-thumbnail.html`, `/document/en/plugin/auto-thumbnail.html` |
|
||||
| `docs/plugin/multiple-subtitles.md`, `docs/en/plugin/multiple-subtitles.md` | Track loading, selection, shared subtitle configuration and compatible type views | `/document/plugin/multiple-subtitles.html`, `/document/en/plugin/multiple-subtitles.html` |
|
||||
| `docs/plugin/ads.md`, `docs/en/plugin/ads.md` | Preroll options, countdown-only controls, events and approved type-inference migration | `/document/plugin/ads.html`, `/document/en/plugin/ads.html` |
|
||||
| `docs/plugin/vast.md`, `docs/en/plugin/vast.md` | Published/workspace initialization, request contexts, SDK ownership and accurate runtime types | `/document/plugin/vast.html`, `/document/en/plugin/vast.html` |
|
||||
| `docs/.vitepress/config.js` | Navigation, base URL, output path, page head | Repository `docs/document/` |
|
||||
| `docs/vite.config.ts` | Search plugin configuration | VitePress/Vite integration; real search acceptance remains pending |
|
||||
| `docs/public/main.js` | Run Code links and first-visit language redirect | Copied into the built site |
|
||||
@@ -34,11 +36,18 @@ and run `node refactor/scripts/demos.mjs --check`. Preserve the frozen BASE-04
|
||||
inventory. Also refresh and check the current site inventory; the two inventories
|
||||
serve different purposes. Neither path check replaces browser navigation tests.
|
||||
|
||||
The generated site lives in `docs/document/`. The current inventory contains 48 Markdown pages: 24 Chinese
|
||||
and 24 English. Danmuku, HLS, DASH, Audio Track, VTT Thumbnail, Chapter, Ambilight, Document PiP, ASR, Auto Thumbnail and Multiple Subtitles have dedicated guides and navigation in both languages. Other plugins currently
|
||||
The generated site lives in `docs/document/`. The current inventory contains 52 Markdown pages: 26 Chinese
|
||||
and 26 English. Danmuku, HLS, DASH, Audio Track, VTT Thumbnail, Chapter, Ambilight, Document PiP, ASR, Auto Thumbnail, Multiple Subtitles, Ads and VAST have dedicated guides and navigation in both languages. Other plugins currently
|
||||
use their package README, architecture notes and linked editor examples;
|
||||
navigation links alone are not complete API documentation.
|
||||
|
||||
Ads and VAST keep their original demos and approved compatibility decisions.
|
||||
Ads play/pause affect its countdown, and its programmatic skip does not enforce
|
||||
the close button's delay. VAST distinguishes default pre-callback allocation from
|
||||
explicit workspace lazy allocation and separates session release from terminal
|
||||
core destruction. Its external IMA example must not be reported as a local or
|
||||
offline playback fixture. Guide navigation tests do not exercise SDK playback.
|
||||
|
||||
Auto Thumbnail and Multiple Subtitles preserve their original runnable examples.
|
||||
Both registrars are asynchronous, but their Promises cover different work: Auto
|
||||
Thumbnail installs subscriptions before extraction, while Multiple Subtitles
|
||||
|
||||
@@ -68,7 +68,7 @@ const config = {
|
||||
items: [
|
||||
{ text: '🎉 弹幕库', link: '/plugin/danmuku' },
|
||||
{ text: '弹幕遮罩', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-danmuku/index.js%0A./uncompiled/artplayer-plugin-danmuku-mask/index.js&example=danmuku.mask' },
|
||||
{ text: '视频广告', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-ads/index.js&example=ads' },
|
||||
{ text: '视频广告', link: '/plugin/ads' },
|
||||
{ text: 'Iframe 控制', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-tool-iframe/index.js&example=iframe' },
|
||||
{ text: 'HLS 控制', link: '/plugin/hls-control' },
|
||||
{ text: 'DASH 控制', link: '/plugin/dash-control' },
|
||||
@@ -77,7 +77,7 @@ const config = {
|
||||
{ text: '多重字幕', link: '/plugin/multiple-subtitles' },
|
||||
{ text: 'ASS 字幕 - JASSUB', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-jassub/index.js&example=jassub' },
|
||||
{ text: 'Chromecast', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-chromecast/index.js&example=chromecast' },
|
||||
{ text: 'VAST 广告', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-vast/index.js&example=vast' },
|
||||
{ text: 'VAST 广告', link: '/plugin/vast' },
|
||||
{ text: '视频章节', link: '/plugin/chapter' },
|
||||
{ text: '视频背光', link: '/plugin/ambilight' },
|
||||
{ text: '文档画中画', link: '/plugin/document-pip' },
|
||||
@@ -142,7 +142,7 @@ const config = {
|
||||
collapsible: true,
|
||||
items: [
|
||||
{ text: 'Danmuku', link: '/en/plugin/danmuku' },
|
||||
{ text: 'Advertise', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-ads/index.js&example=ads' },
|
||||
{ text: 'Advertise', link: '/en/plugin/ads' },
|
||||
{ text: 'Iframe Control', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-tool-iframe/index.js&example=iframe' },
|
||||
{ text: 'HLS Control', link: '/en/plugin/hls-control' },
|
||||
{ text: 'DASH Control', link: '/en/plugin/dash-control' },
|
||||
@@ -151,7 +151,7 @@ const config = {
|
||||
{ text: 'Multiple Subtitles', link: '/en/plugin/multiple-subtitles' },
|
||||
{ text: 'ASS Subtitle - JASSUB', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-jassub/index.js&example=jassub' },
|
||||
{ text: 'Chromecast', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-chromecast/index.js&example=chromecast' },
|
||||
{ text: 'VAST', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-vast/index.js&example=vast' },
|
||||
{ text: 'VAST', link: '/en/plugin/vast' },
|
||||
{ text: 'Video Chapters', link: '/en/plugin/chapter' },
|
||||
{ text: 'Video Ambilight', link: '/en/plugin/ambilight' },
|
||||
{ text: 'Document PIP', link: '/en/plugin/document-pip' },
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
# Video and HTML Ads
|
||||
|
||||
[简体中文](../../plugin/ads.md)
|
||||
|
||||
Show one preroll when content first plays, using a separate video or HTML. The plugin supplies countdown, close, details, mute and fullscreen controls without IMA. Ad-tag requests belong to the separate [VAST plugin](./vast.md). This page describes the unreleased refactor branch; online examples and unpinned packages are not the current candidate.
|
||||
|
||||
## Installation and example
|
||||
|
||||
```sh
|
||||
yarn add artplayer artplayer-plugin-ads
|
||||
```
|
||||
|
||||
```js
|
||||
import Artplayer from 'artplayer';
|
||||
import artplayerPluginAds from 'artplayer-plugin-ads';
|
||||
```
|
||||
|
||||
For script usage, load ArtPlayer before `dist/artplayer-plugin-ads.js`; the global is `artplayerPluginAds`. The [original online example](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-ads/index.js&example=ads) below supplies both video and HTML, so the video takes precedence.
|
||||
|
||||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-ads/index.js">▶ Run Code</div>
|
||||
|
||||
```js
|
||||
// npm i artplayer-plugin-ads
|
||||
// import artplayerPluginAds from 'artplayer-plugin-ads';
|
||||
|
||||
const art = new Artplayer({
|
||||
container: '.artplayer-app',
|
||||
url: '/assets/sample/video.mp4',
|
||||
autoSize: true,
|
||||
fullscreen: true,
|
||||
fullscreenWeb: true,
|
||||
plugins: [
|
||||
artplayerPluginAds({
|
||||
// html广告,假如是视频广告则忽略该值
|
||||
html: '<img src="/assets/sample/poster.jpg">',
|
||||
|
||||
// 视频广告的地址
|
||||
video: '/assets/sample/test1.mp4',
|
||||
|
||||
// 广告跳转网址,为空则不跳转
|
||||
url: 'http://artplayer.org',
|
||||
|
||||
// 必须观看的时长,期间不能被跳过,单位为秒
|
||||
// 当该值大于或等于totalDuration时,不能提前关闭广告
|
||||
// 当该值等于或小于0时,则随时都可以关闭广告
|
||||
playDuration: 5,
|
||||
|
||||
// 广告总时长,单位为秒
|
||||
totalDuration: 10,
|
||||
|
||||
// 多语言支持
|
||||
i18n: {
|
||||
close: '关闭广告',
|
||||
countdown: '%s秒',
|
||||
detail: '查看详情',
|
||||
canBeClosed: '%s秒后可关闭广告',
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
// 广告被点击
|
||||
art.on('artplayerPluginAds:click', (ads) => {
|
||||
console.info('广告被点击', ads)
|
||||
})
|
||||
|
||||
// 广告被跳过
|
||||
art.on('artplayerPluginAds:skip', (ads) => {
|
||||
console.info('广告被跳过', ads)
|
||||
})
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
Options may be omitted or supplied as `{}` to use defaults.
|
||||
|
||||
| Field | Type | Default | Meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| `html` | `string` | `''` | Ad HTML, including images; not sanitized automatically, so supply trusted content |
|
||||
| `video` | `string` | `''` | Ad video URL; a nonempty value overrides html |
|
||||
| `url` | `string` | `''` | Destination opened from ad content or details; empty disables navigation and hides details |
|
||||
| `playDuration` | `number` | `5` | Countdown seconds before the close button is enabled; does not restrict programmatic skip |
|
||||
| `totalDuration` | `number` | `10` | Total countdown seconds, independent of the video duration |
|
||||
| `muted` | `boolean` | `false` | Initial ad-video mute state |
|
||||
| `i18n` | `Translations` | Below | Replaces the entire translations object; all four fields are required |
|
||||
|
||||
| Translation | Default |
|
||||
| --- | --- |
|
||||
| `close` | `'关闭广告'` |
|
||||
| `countdown` | `'%s秒'` |
|
||||
| `detail` | `'查看详情'` |
|
||||
| `canBeClosed` | `'%s秒后可关闭广告'` |
|
||||
|
||||
`%s` is replaced with the time value. Options are shallowly merged; partial i18n objects are not supported. Use numeric seconds: string durations are rejected without coercion. Historical workspace source/type fields are not runtime aliases for video/html; supply images through an img in html.
|
||||
|
||||
Positive integer durations are recommended. With `playDuration <= 0`, the button allows immediate closure; with `playDuration >= totalDuration`, it is hidden. Counting advances once per timer execution and pauses while the document is hidden. It is not an exact measure of video currentTime or real elapsed time. The ad video loops; countdown completion or skip ends the ad.
|
||||
|
||||
## Methods and events
|
||||
|
||||
Registration is synchronous. The result is `art.plugins.artplayerPluginAds`, with the fixed name `artplayerPluginAds`.
|
||||
|
||||
| Method | Runtime behavior |
|
||||
| --- | --- |
|
||||
| `pause()` | Pause only the countdown, leaving ad video playback unchanged |
|
||||
| `play()` | Resume only the countdown without adding duplicate timer chains |
|
||||
| `skip()` | Finish once, regardless of the button's playDuration restriction |
|
||||
|
||||
All return `undefined` synchronously. Before initialization, play/pause do not start an ad. Early skip cancels the pending preroll and emits once without creating DOM or starting content. Repeated skip after completion is inert.
|
||||
|
||||
| Player event | Payload and timing |
|
||||
| --- | --- |
|
||||
| `artplayerPluginAds:click` | The normalized options when ad content or available details are clicked; a nonempty url is opened first |
|
||||
| `artplayerPluginAds:skip` | The same normalized options on completion, including countdown expiry, programmatic skip or media failure; not solely a user-click signal |
|
||||
|
||||
Event options remain live, not readonly snapshots. Listener mutations affect later reads, such as totalDuration. Opening the details destination remains subject to browser window policies.
|
||||
|
||||
## Lifecycle and media
|
||||
|
||||
Install through construction options. After ready, the first play or video:playing signal creates the overlay and pauses content. Late installation does not replay an earlier ready event. Video ads wait for their own metadata before counting and requesting playback; HTML ads start counting immediately.
|
||||
|
||||
Ad media loading or playback failure completes the ad, and rejected internal play requests warn. Normal completion requests content playback, pauses the ad, hides the overlay and synchronously emits skip. A playback request does not guarantee the browser has started playing; direct application `art.play()` rejection behavior remains unchanged.
|
||||
|
||||
The hidden overlay stays until player destruction. Destroy releases the ad source, listeners, timer and overlay, removing its own `art.template.$ads` even if player HTML is retained. There is no separate public destroy, reset or replay-ad API. Existing `artplayer-plugin-ads*` classes remain; the fullscreen control uses core fullscreen.
|
||||
|
||||
The separate ad video must be loadable and decodable by the browser. Main-player SDKs and proxies do not automatically handle it. Native fullscreen, mobile playback policies and media behavior require target-environment validation; page navigation is not that evidence.
|
||||
|
||||
## TypeScript compatibility
|
||||
|
||||
The root and `/legacy` retain acceptance of the old erroneous `totalDuration: string` declaration, but runtime still rejects strings. The approved inference correction makes `Parameters<typeof ads>[0].totalDuration` read as `number | string | undefined`; historical source/type also become optional. Narrow those values or migrate to the accurate Option type.
|
||||
|
||||
New code can select `/runtime`, which uses the same implementation:
|
||||
|
||||
```ts
|
||||
import ads from 'artplayer-plugin-ads/runtime';
|
||||
import type { Option, Result } from 'artplayer-plugin-ads';
|
||||
|
||||
const options: Option = { video: '/advertisement.mp4', totalDuration: 10 };
|
||||
const installAds = ads(options);
|
||||
|
||||
function pauseCountdown(plugin: Result): void {
|
||||
plugin.pause();
|
||||
}
|
||||
```
|
||||
|
||||
Public types include Translations, Option, LegacyOption, WorkspaceOption, CompatOption, Result, Callable, Factory, RuntimeCallable and RuntimeFactory. Historical option types do not add runtime aliases. CommonJS supports the function and `.default(...)`; ESM uses the default export. The precise entry is not a second plugin implementation.
|
||||
@@ -0,0 +1,116 @@
|
||||
# VAST Ads
|
||||
|
||||
[简体中文](../../plugin/vast.md)
|
||||
|
||||
Request and display ads through Glomex VAST IMA Player and Google IMA. Unlike the separate [Ads plugin](./ads.md), this accepts ad-tag URLs or VAST responses rather than managing a local countdown ad. SDK and ad resources must be reachable; network, VPN or blocking rules can prevent loading. This page describes the unreleased refactor branch, not proof that the online example validates the current candidate.
|
||||
|
||||
## Installation and example
|
||||
|
||||
```sh
|
||||
yarn add artplayer artplayer-plugin-vast
|
||||
```
|
||||
|
||||
```js
|
||||
import Artplayer from 'artplayer';
|
||||
import artplayerPluginVast from 'artplayer-plugin-vast';
|
||||
```
|
||||
|
||||
For script usage, load ArtPlayer before `dist/artplayer-plugin-vast.js`; the global is `artplayerPluginVast`. Its Glomex dependency loads IMA, so no separate custom loader is needed. This preserves the [original online example](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-vast/index.js&example=vast); its external ad URL is not a local test fixture.
|
||||
|
||||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-vast/index.js">▶ Run Code</div>
|
||||
|
||||
```js
|
||||
// Depends on:
|
||||
// https://glomex.github.io/vast-ima-player/
|
||||
// https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side
|
||||
|
||||
// Google's IMA SDK are blocked by your Ad blocker.
|
||||
// Please Turn Off Your Ad Blocker.
|
||||
|
||||
// npm i artplayer-plugin-vast
|
||||
// import artplayerPluginVast from 'artplayer-plugin-vast';
|
||||
|
||||
var art = new Artplayer({
|
||||
container: '.artplayer-app',
|
||||
url: '/assets/sample/video.mp4',
|
||||
fullscreen: true,
|
||||
fullscreenWeb: true,
|
||||
plugins: [
|
||||
artplayerPluginVast(({ playUrl, imaPlayer, ima }) => {
|
||||
// Play the ad when the video is played
|
||||
art.once('play', () => {
|
||||
playUrl('https://artplayer.org/assets/vast/linear-ad.xml')
|
||||
})
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
## Initialization compatibility
|
||||
|
||||
`artplayerPluginVast(callback?, options?)` returns an asynchronous registrar. It loads the SDK, creates the appropriate context and awaits the callback before resolving. A callback can return a Promise. Registration does not imply an ad was requested or played.
|
||||
|
||||
| Behavior | Default npm mode | `{ compatibility: 'workspace-1.2' }` |
|
||||
| --- | --- | --- |
|
||||
| Callback entry | SDK player and container already allocated | Allocation waits for init/playUrl/playRes |
|
||||
| IMA settings | SDK defaults preserved | Preloading and restoration of custom playback state default to true |
|
||||
| Resource fields | Writable imaPlayer/id/$container data fields | Live readonly getters, null before allocation and after release |
|
||||
| Requests | Wrapper forwards every explicit request | New requests are suppressed during an active ad |
|
||||
| Container | SDK manages visibility with default styles | Black overlay, four ad events manage visibility and active state |
|
||||
|
||||
This implements the approved decision: published npm1.0.0 calls retain their default behavior. Code relying on unpublished workspace1.2 lazy initialization must select it explicitly. The mode is captured once at factory creation; unknown values immediately throw TypeError before SDK loading.
|
||||
|
||||
## Callback context
|
||||
|
||||
| Field | Runtime purpose |
|
||||
| --- | --- |
|
||||
| `art` | Current ArtPlayer instance |
|
||||
| `ima` | Loaded IMA SDK |
|
||||
| `adsRenderingSettings` | IMA AdsRenderingSettings passed to a newly allocated SDK player |
|
||||
| `playerOptions` | Glomex PlayerOptions passed to a newly allocated SDK player |
|
||||
| `imaPlayer` | SDK player; already created in default mode, nullable in workspace mode |
|
||||
| `id` / `$container` | Container ID/element, with the mode-specific snapshot/null rules above |
|
||||
| `container` | Live readonly container getter in both modes, null before allocation or after release |
|
||||
| `init()` | Return or create the current SDK player; null after terminal disposal |
|
||||
| `playUrl(url, config?)` | Create an AdsRequest, set adTagUrl and request ads; returns void synchronously |
|
||||
| `playRes(response, config?)` | Create an AdsRequest, set adsResponse and request ads; returns void synchronously |
|
||||
|
||||
The extra config fields retain historical for-in copying, including enumerable inherited fields. Copying follows the primary assignment, so config can override adTagUrl/adsResponse. Use application-controlled configuration. Request construction or SDK synchronous errors can throw; void does not signal success or provide an ad-completion Promise.
|
||||
|
||||
To configure before SDK player allocation, select workspace mode and mutate the original settings/options objects before init or request methods. The default mode's first player already exists on callback entry; do not assume later option changes retroactively alter construction.
|
||||
|
||||
Default imaPlayer/id/$container fields retain the last allocation after release, even though that SDK is destroyed and its container removed. They are not active resources. Explicit recreation updates them, and assigning these fields does not transfer internal ownership. In workspace mode, keep the context and read getters when needed rather than destructuring their initial null values.
|
||||
|
||||
## Events and destruction
|
||||
|
||||
Subscribe to SDK events on imaPlayer; they are not same-named ArtPlayer events. Workspace mode listens to `AdContentPauseRequested`, `AdContentResumeRequested`, `AdStarted` and `AdError` to update its overlay and active state, logging AdError details. Default mode does not add those workspace listeners. The SDK handles content pause/resume; the wrapper does not duplicate it.
|
||||
|
||||
The result is named `artplayerPluginVast` and registered at `art.plugins.artplayerPluginVast`. Its synchronous `destroy()` releases the current session. While the core remains alive, retained context init/playUrl/playRes methods can create a new session. A recreated SDK player is a different object; reinstall your own SDK subscriptions on it.
|
||||
|
||||
Core destruction makes this attachment terminal: late SDK completion cannot invoke the callback or allocate a container, init returns null and request methods become inert. It does not cancel a shared SDK script load for other instances. SDK loading or callback failure cleans up the attachment and preserves the original rejection value. Cleanup errors can be observable while remaining resources are still released. Plugin destroy and core destroy therefore have different restart semantics.
|
||||
|
||||
Real ad playback depends on an available response, IMA, browser policies and devices. When SDK loading is blocked, mocks, guide navigation or continued main-content playback cannot count as successful ads. Validate those separately on the target network and device.
|
||||
|
||||
## TypeScript entries
|
||||
|
||||
The root and `/legacy` preserve npm1.0.0's required callback, any SDK fields and inaccurate synchronous name-only result. Plain historical replacement factories do not need a `.default` property. Registration has always been asynchronous. Use `/runtime` for accurate types, optional callback, the second parameter and destroy, with the same implementation:
|
||||
|
||||
```ts
|
||||
import vast from 'artplayer-plugin-vast/runtime';
|
||||
import type { RuntimeResult } from 'artplayer-plugin-vast/runtime';
|
||||
|
||||
const installPublished = vast(({ imaPlayer }) => {
|
||||
imaPlayer.addEventListener('AdStarted', () => console.log('Ad started'));
|
||||
});
|
||||
|
||||
const installWorkspace = vast((context) => {
|
||||
context.playerOptions.autoResize = false;
|
||||
context.init()?.addEventListener('AdStarted', () => console.log('Ad started'));
|
||||
}, { compatibility: 'workspace-1.2' });
|
||||
|
||||
function releaseAd(result: RuntimeResult): void {
|
||||
result.destroy();
|
||||
}
|
||||
```
|
||||
|
||||
Runtime exports RequestConfig, CompatibilityOptions, Context, PublishedContext, WorkspaceContext, RuntimeContext, RuntimeCallback, RuntimeResult, Registration and RuntimeFactory, plus the historical workspace aliases ArtplayerPluginVastOption and ArtplayerPluginVastInstance. Those aliases describe the workspace callback and awaited result, respectively. CommonJS without interop can use runtime `import = require`, supporting both direct and `.default` calls. These types do not modify the old root declaration.
|
||||
@@ -0,0 +1,145 @@
|
||||
# 视频与 HTML 广告
|
||||
|
||||
[English](../en/plugin/ads.md)
|
||||
|
||||
在内容首次播放时展示一次前贴片广告,可以使用独立视频或 HTML。插件自带倒计时、关闭、详情、静音和全屏控件,不需要 IMA SDK;VAST 广告请求由另一个 [VAST 插件](./vast.md)处理。本页描述未发布的重构分支,在线示例与未固定版本的包不等于当前候选。
|
||||
|
||||
## 安装和示例
|
||||
|
||||
```sh
|
||||
yarn add artplayer artplayer-plugin-ads
|
||||
```
|
||||
|
||||
```js
|
||||
import Artplayer from 'artplayer';
|
||||
import artplayerPluginAds from 'artplayer-plugin-ads';
|
||||
```
|
||||
|
||||
使用 script 时先加载 ArtPlayer,再加载 `dist/artplayer-plugin-ads.js`,全局名为 `artplayerPluginAds`。下面保留[原在线示例](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-ads/index.js&example=ads),其中同时配置 video/html 时使用视频。
|
||||
|
||||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-ads/index.js">▶ Run Code</div>
|
||||
|
||||
```js
|
||||
// npm i artplayer-plugin-ads
|
||||
// import artplayerPluginAds from 'artplayer-plugin-ads';
|
||||
|
||||
const art = new Artplayer({
|
||||
container: '.artplayer-app',
|
||||
url: '/assets/sample/video.mp4',
|
||||
autoSize: true,
|
||||
fullscreen: true,
|
||||
fullscreenWeb: true,
|
||||
plugins: [
|
||||
artplayerPluginAds({
|
||||
// html广告,假如是视频广告则忽略该值
|
||||
html: '<img src="/assets/sample/poster.jpg">',
|
||||
|
||||
// 视频广告的地址
|
||||
video: '/assets/sample/test1.mp4',
|
||||
|
||||
// 广告跳转网址,为空则不跳转
|
||||
url: 'http://artplayer.org',
|
||||
|
||||
// 必须观看的时长,期间不能被跳过,单位为秒
|
||||
// 当该值大于或等于totalDuration时,不能提前关闭广告
|
||||
// 当该值等于或小于0时,则随时都可以关闭广告
|
||||
playDuration: 5,
|
||||
|
||||
// 广告总时长,单位为秒
|
||||
totalDuration: 10,
|
||||
|
||||
// 多语言支持
|
||||
i18n: {
|
||||
close: '关闭广告',
|
||||
countdown: '%s秒',
|
||||
detail: '查看详情',
|
||||
canBeClosed: '%s秒后可关闭广告',
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
// 广告被点击
|
||||
art.on('artplayerPluginAds:click', (ads) => {
|
||||
console.info('广告被点击', ads)
|
||||
})
|
||||
|
||||
// 广告被跳过
|
||||
art.on('artplayerPluginAds:skip', (ads) => {
|
||||
console.info('广告被跳过', ads)
|
||||
})
|
||||
```
|
||||
|
||||
## 配置
|
||||
|
||||
配置可省略,也可传入 `{}` 使用默认值。
|
||||
|
||||
| 字段 | 类型 | 默认值 | 含义 |
|
||||
| --- | --- | --- | --- |
|
||||
| `html` | `string` | `''` | 广告 HTML,可包含图片;不会自动清理 HTML,仅使用可信内容 |
|
||||
| `video` | `string` | `''` | 广告视频地址,非空时优先于 html |
|
||||
| `url` | `string` | `''` | 点击广告或详情时打开的地址;为空不跳转并隐藏详情按钮 |
|
||||
| `playDuration` | `number` | `5` | 关闭按钮开放前的倒计时秒数,不限制应用直接调用 skip |
|
||||
| `totalDuration` | `number` | `10` | 广告倒计时总秒数,不取广告视频的实际时长 |
|
||||
| `muted` | `boolean` | `false` | 广告视频初始静音状态 |
|
||||
| `i18n` | `Translations` | 下表 | 整体替换默认翻译对象,四个字段必须一起提供 |
|
||||
|
||||
| 翻译字段 | 默认值 |
|
||||
| --- | --- |
|
||||
| `close` | `'关闭广告'` |
|
||||
| `countdown` | `'%s秒'` |
|
||||
| `detail` | `'查看详情'` |
|
||||
| `canBeClosed` | `'%s秒后可关闭广告'` |
|
||||
|
||||
`%s` 用于时间替换。配置按浅合并处理,不支持只传一项 i18n。时长应使用数字秒,字符串不进行转换,而是被运行时校验拒绝。`source/type` 只是旧工作区声明遗留字段,不会被当作 video/html 的别名;图片通过 html 的 img 提供。
|
||||
|
||||
建议使用正整数时长。`playDuration <= 0` 时可立即用按钮关闭;`playDuration >= totalDuration` 时隐藏提前关闭按钮。倒计时按每次定时器执行累计一秒,页面隐藏时暂停;不是对视频 currentTime 或现实经过时间的精确计费。视频循环播放,广告结束由倒计时或 skip 决定。
|
||||
|
||||
## 方法和事件
|
||||
|
||||
插件同步注册,结果在 `art.plugins.artplayerPluginAds`,name 固定为 `artplayerPluginAds`。
|
||||
|
||||
| 方法 | 实际行为 |
|
||||
| --- | --- |
|
||||
| `pause()` | 暂停倒计时,不暂停广告视频 |
|
||||
| `play()` | 恢复倒计时,不播放广告视频,也不创建重复计时链 |
|
||||
| `skip()` | 结束广告一次;不受关闭按钮的 playDuration 限制 |
|
||||
|
||||
三个方法都同步返回 `undefined`。未初始化时 play/pause 不启动广告,skip 取消尚未显示的前贴片并发出一次 skip 事件,不创建 DOM 或主动开始内容播放。广告结束后重复 skip 无额外效果。
|
||||
|
||||
| 播放器事件 | 参数与时机 |
|
||||
| --- | --- |
|
||||
| `artplayerPluginAds:click` | 广告内容或可用详情按钮被点击,传入该次归一化配置;有 url 时先请求打开新窗口 |
|
||||
| `artplayerPluginAds:skip` | 广告完成时传入同一个归一化配置;倒计时结束、手动跳过或媒体失败均可能触发,并非只表示用户点击 |
|
||||
|
||||
事件参数不是只读快照,监听器修改其中字段会影响后续读取,例如 totalDuration。实际打开广告详情还受浏览器窗口策略约束。
|
||||
|
||||
## 生命周期和媒体
|
||||
|
||||
在构造选项中安装插件。插件等到 ready 后的第一次 play 或 video:playing 信号才创建覆盖层并暂停正文;晚于 ready 安装不会补发已经过去的 ready。视频广告等到自己的 metadata 后启动倒计时并请求播放,HTML 广告直接开始计时。
|
||||
|
||||
广告视频加载或播放失败会结束广告;内部请求播放的 Promise 拒绝会记录警告。正常结束先请求恢复正文播放,再暂停广告、隐藏覆盖层并同步发出 skip。恢复请求不保证浏览器已经开始播放,应用直接调用 `art.play()` 的拒绝行为也没有改变。
|
||||
|
||||
结束后隐藏的广告层保留到播放器销毁。销毁释放广告视频来源、监听器、定时器和覆盖层,并清理自己创建的 `art.template.$ads`;即使保留播放器 HTML 也会清理。插件没有独立公开的 destroy、reset 或再次投放接口。样式沿用 `artplayer-plugin-ads*` 类名;全屏按钮调用核心 fullscreen。
|
||||
|
||||
独立广告视频需要浏览器能够加载与解码;主播放器的自定义 SDK/代理不会自动接管它。原生全屏、移动端播放策略及实际媒体效果需要目标环境验收,页面导航通过不代表这些能力已验证。
|
||||
|
||||
## TypeScript 兼容
|
||||
|
||||
根入口和 `/legacy` 接受旧声明中的 `totalDuration: string`,但运行时仍拒绝字符串。已批准的类型修正使 `Parameters<typeof ads>[0].totalDuration` 读取为 `number | string | undefined`,旧工作区 source/type 也变为可选;依赖过去推导的代码需要缩窄或迁到精确 Option。
|
||||
|
||||
新代码可选择相同实现的 `/runtime`:
|
||||
|
||||
```ts
|
||||
import ads from 'artplayer-plugin-ads/runtime';
|
||||
import type { Option, Result } from 'artplayer-plugin-ads';
|
||||
|
||||
const options: Option = { video: '/advertisement.mp4', totalDuration: 10 };
|
||||
const installAds = ads(options);
|
||||
|
||||
function pauseCountdown(plugin: Result): void {
|
||||
plugin.pause();
|
||||
}
|
||||
```
|
||||
|
||||
公开类型包括 Translations、Option、LegacyOption、WorkspaceOption、CompatOption、Result、Callable、Factory、RuntimeCallable、RuntimeFactory。LegacyOption/WorkspaceOption 用于明确表示历史声明,不新增运行时别名。CommonJS 支持函数本身和 `.default(...)`,ESM 使用默认导出;精确入口不是第二套插件实现。
|
||||
@@ -0,0 +1,116 @@
|
||||
# VAST 广告
|
||||
|
||||
[English](../en/plugin/vast.md)
|
||||
|
||||
通过 Glomex VAST IMA Player 和 Google IMA SDK 请求并展示广告。与 [Ads 插件](./ads.md)的本地倒计时广告不同,这里使用广告标签地址或 VAST 响应。SDK 脚本和广告资源需要可访问,网络、VPN 或广告拦截规则可能阻止加载。本页描述未发布重构分支,线上示例不是当前候选的验收证据。
|
||||
|
||||
## 安装和示例
|
||||
|
||||
```sh
|
||||
yarn add artplayer artplayer-plugin-vast
|
||||
```
|
||||
|
||||
```js
|
||||
import Artplayer from 'artplayer';
|
||||
import artplayerPluginVast from 'artplayer-plugin-vast';
|
||||
```
|
||||
|
||||
使用 script 时先加载 ArtPlayer,再加载 `dist/artplayer-plugin-vast.js`,全局名为 `artplayerPluginVast`。插件通过其 Glomex 依赖加载 IMA,无需另造加载器。以下保留[原在线示例](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-vast/index.js&example=vast);其中的外部广告地址并非本地测试夹具。
|
||||
|
||||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-vast/index.js">▶ Run Code</div>
|
||||
|
||||
```js
|
||||
// Depends on:
|
||||
// https://glomex.github.io/vast-ima-player/
|
||||
// https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side
|
||||
|
||||
// Google's IMA SDK are blocked by your Ad blocker.
|
||||
// Please Turn Off Your Ad Blocker.
|
||||
|
||||
// npm i artplayer-plugin-vast
|
||||
// import artplayerPluginVast from 'artplayer-plugin-vast';
|
||||
|
||||
var art = new Artplayer({
|
||||
container: '.artplayer-app',
|
||||
url: '/assets/sample/video.mp4',
|
||||
fullscreen: true,
|
||||
fullscreenWeb: true,
|
||||
plugins: [
|
||||
artplayerPluginVast(({ playUrl, imaPlayer, ima }) => {
|
||||
// Play the ad when the video is played
|
||||
art.once('play', () => {
|
||||
playUrl('https://artplayer.org/assets/vast/linear-ad.xml')
|
||||
})
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
## 初始化兼容模式
|
||||
|
||||
工厂形状为 `artplayerPluginVast(callback?, options?)`,返回异步注册函数。加载 SDK、创建相应上下文并 await 用户回调后,注册才完成。回调可返回 Promise,但注册完成不等于广告已请求或播放。
|
||||
|
||||
| 行为 | 默认 npm 模式 | `{ compatibility: 'workspace-1.2' }` |
|
||||
| --- | --- | --- |
|
||||
| 回调开始时 | 已创建 IMA player 和容器 | 尚未创建,等 init/playUrl/playRes |
|
||||
| IMA 设置 | 保留 SDK 自身默认值 | 预加载和广告结束后恢复自定义播放状态默认为 true |
|
||||
| 资源字段 | imaPlayer/id/$container 是可写数据字段 | 三者是实时只读 getter,初始化前或释放后为 null |
|
||||
| 请求 | 包装层转发每次显式请求 | 活动广告期间抑制新的请求 |
|
||||
| 容器 | 由 SDK 管理广告显隐,保留默认样式 | 黑色覆盖层,四个广告事件控制显隐和活动状态 |
|
||||
|
||||
这是已批准的兼容选择:已发布 npm 1.0.0 用户保留默认行为,依赖未发布工作区 1.2 惰性初始化的代码必须显式选择工作区模式。模式在工厂调用时读取一次;未知值立即抛出 TypeError,不会启动 SDK 加载。
|
||||
|
||||
## 回调上下文
|
||||
|
||||
| 字段 | 实际用途 |
|
||||
| --- | --- |
|
||||
| `art` | 当前播放器实例 |
|
||||
| `ima` | 已加载的 IMA SDK |
|
||||
| `adsRenderingSettings` | 传给新 SDK player 的 IMA AdsRenderingSettings 对象 |
|
||||
| `playerOptions` | 传给新 SDK player 的 Glomex PlayerOptions 对象 |
|
||||
| `imaPlayer` | SDK player,默认模式已创建;工作区模式可为 null |
|
||||
| `id` / `$container` | 该模式的容器 ID/元素,空值和快照规则见上表 |
|
||||
| `container` | 两种模式均为当前容器的只读 getter;未创建或释放后为 null |
|
||||
| `init()` | 取得或创建当前 SDK player,终止后返回 null |
|
||||
| `playUrl(url, config?)` | 创建 AdsRequest,设置 adTagUrl 并请求广告;同步返回 void |
|
||||
| `playRes(response, config?)` | 创建 AdsRequest,设置 adsResponse 并请求广告;同步返回 void |
|
||||
|
||||
config 是附加请求字段;沿用历史 for-in 复制行为,包括可枚举的继承字段,且复制发生在主字段之后,因此可以覆盖 adTagUrl/adsResponse。请传入应用明确控制的配置。请求构造或 SDK 同步错误可直接抛出,void 返回不表示广告成功,也不是播放完成 Promise。
|
||||
|
||||
要在 SDK player 创建前配置选项,使用工作区模式并先修改原 settings/options 对象,再调用 init 或请求方法。默认模式的首个 player 在回调之前已经创建;不要假设回调内修改选项能追溯改变构造行为。
|
||||
|
||||
默认模式释放后,imaPlayer/id/$container 仍保留上次分配的快照,但 SDK 已销毁、容器已移除;不能继续把快照当作活跃资源。显式重建会更新它们。写入这些字段不会转移插件内部资源所有权。工作区模式应保留 context 并实时读取 getter,避免解构保存初始化前的 null。
|
||||
|
||||
## 广告事件与销毁
|
||||
|
||||
SDK 事件通过 imaPlayer 订阅,不是同名的 ArtPlayer 事件。工作区包装层监听 `AdContentPauseRequested`、`AdContentResumeRequested`、`AdStarted`、`AdError`,改变覆盖层和活动状态;AdError 同时记录错误。默认模式不增加这些工作区监听器。正文暂停/恢复由 SDK 负责,包装层不重复实现。
|
||||
|
||||
结果名为 `artplayerPluginVast`,通过 `art.plugins.artplayerPluginVast` 取得,公开 `destroy()` 同步释放当前会话。播放器仍存活时,可再次调用回调中保留的 init/playUrl/playRes 创建新会话。重建后的 SDK 是新对象,需要重新安装应用自己的 SDK 监听器。
|
||||
|
||||
核心销毁使这次插件安装永久终止:SDK 加载的迟到完成不再调用回调或创建容器,init 返回 null,请求方法为空操作。它不会取消其他实例共用的 SDK 脚本加载。SDK 加载或用户回调失败会清理附件并保留原拒绝值;清理失败可能可观察,但其余资源仍会尝试释放。不要将插件 destroy 与核心 destroy 的终止语义混同。
|
||||
|
||||
真实广告播放还涉及可用广告响应、IMA、浏览器策略和设备。SDK 加载受阻时不能把 mock、页面导航或正文继续播放当作广告播放通过;使用目标网络和设备单独验收。
|
||||
|
||||
## TypeScript 入口
|
||||
|
||||
根入口和 `/legacy` 保留 npm 1.0.0 的必填回调、any SDK 字段和错误的同步 name-only 返回声明,不要求旧替换函数增加 `.default`。实际注册一直是异步的。需要准确类型、可省略回调、第二参数或 destroy 时使用同一实现的 `/runtime`:
|
||||
|
||||
```ts
|
||||
import vast from 'artplayer-plugin-vast/runtime';
|
||||
import type { RuntimeResult } from 'artplayer-plugin-vast/runtime';
|
||||
|
||||
const installPublished = vast(({ imaPlayer }) => {
|
||||
imaPlayer.addEventListener('AdStarted', () => console.log('Ad started'));
|
||||
});
|
||||
|
||||
const installWorkspace = vast((context) => {
|
||||
context.playerOptions.autoResize = false;
|
||||
context.init()?.addEventListener('AdStarted', () => console.log('Ad started'));
|
||||
}, { compatibility: 'workspace-1.2' });
|
||||
|
||||
function releaseAd(result: RuntimeResult): void {
|
||||
result.destroy();
|
||||
}
|
||||
```
|
||||
|
||||
runtime 导出 RequestConfig、CompatibilityOptions、Context、PublishedContext、WorkspaceContext、RuntimeContext、RuntimeCallback、RuntimeResult、Registration、RuntimeFactory,及旧工作区别名 ArtplayerPluginVastOption/ArtplayerPluginVastInstance。前者是工作区回调类型,后者是 await 后的结果类型。CommonJS 无 interop 时可用 runtime 的 `import = require`,支持函数和 `.default`;这些类型不会更改旧根声明。
|
||||
@@ -50,5 +50,5 @@
|
||||
}
|
||||
|
||||
// <stdin>
|
||||
installNavigation(window, ["advanced/built-in.html", "advanced/built-in", "advanced/class.html", "advanced/class", "advanced/event.html", "advanced/event", "advanced/global.html", "advanced/global", "advanced/plugin.html", "advanced/plugin", "advanced/property.html", "advanced/property", "component/contextmenu.html", "component/contextmenu", "component/controls.html", "component/controls", "component/layers.html", "component/layers", "component/setting.html", "component/setting", "", "index.html", "plugin/ambilight.html", "plugin/ambilight", "plugin/asr.html", "plugin/asr", "plugin/audio-track.html", "plugin/audio-track", "plugin/auto-thumbnail.html", "plugin/auto-thumbnail", "plugin/chapter.html", "plugin/chapter", "plugin/danmuku.html", "plugin/danmuku", "plugin/dash-control.html", "plugin/dash-control", "plugin/document-pip.html", "plugin/document-pip", "plugin/hls-control.html", "plugin/hls-control", "plugin/multiple-subtitles.html", "plugin/multiple-subtitles", "plugin/vtt-thumbnail.html", "plugin/vtt-thumbnail", "start/i18n.html", "start/i18n", "start/option.html", "start/option"]);
|
||||
installNavigation(window, ["advanced/built-in.html", "advanced/built-in", "advanced/class.html", "advanced/class", "advanced/event.html", "advanced/event", "advanced/global.html", "advanced/global", "advanced/plugin.html", "advanced/plugin", "advanced/property.html", "advanced/property", "component/contextmenu.html", "component/contextmenu", "component/controls.html", "component/controls", "component/layers.html", "component/layers", "component/setting.html", "component/setting", "", "index.html", "plugin/ads.html", "plugin/ads", "plugin/ambilight.html", "plugin/ambilight", "plugin/asr.html", "plugin/asr", "plugin/audio-track.html", "plugin/audio-track", "plugin/auto-thumbnail.html", "plugin/auto-thumbnail", "plugin/chapter.html", "plugin/chapter", "plugin/danmuku.html", "plugin/danmuku", "plugin/dash-control.html", "plugin/dash-control", "plugin/document-pip.html", "plugin/document-pip", "plugin/hls-control.html", "plugin/hls-control", "plugin/multiple-subtitles.html", "plugin/multiple-subtitles", "plugin/vast.html", "plugin/vast", "plugin/vtt-thumbnail.html", "plugin/vtt-thumbnail", "start/i18n.html", "start/i18n", "start/option.html", "start/option"]);
|
||||
})();
|
||||
Reference in new issue
Block a user