kplayer-ts 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +466 -138
  3. package/dist/kplayer-ts.cjs.js +397 -0
  4. package/dist/kplayer-ts.cjs.js.map +1 -0
  5. package/dist/kplayer-ts.d.ts +6 -0
  6. package/dist/{kplayer.es.js → kplayer-ts.es.js} +281 -268
  7. package/dist/kplayer-ts.es.js.map +1 -0
  8. package/dist/kplayer-ts.umd.js +397 -0
  9. package/dist/kplayer-ts.umd.js.map +1 -0
  10. package/dist/main.d.ts +1 -0
  11. package/dist/template/player.d.ts +21 -0
  12. package/dist/template/video.d.ts +12 -0
  13. package/dist/ts/ad.d.ts +39 -0
  14. package/dist/ts/bar.d.ts +10 -0
  15. package/dist/ts/bezel.d.ts +6 -0
  16. package/dist/ts/contextmenu.d.ts +12 -0
  17. package/dist/ts/controller.d.ts +38 -0
  18. package/dist/ts/events.d.ts +11 -0
  19. package/dist/ts/fullscreen.d.ts +15 -0
  20. package/dist/ts/hotkey.d.ts +11 -0
  21. package/dist/ts/i18n.d.ts +6 -0
  22. package/dist/ts/icons.d.ts +22 -0
  23. package/dist/ts/index.d.ts +3 -0
  24. package/dist/ts/info-panel.d.ts +16 -0
  25. package/dist/ts/options.d.ts +5 -0
  26. package/dist/ts/player.d.ts +107 -0
  27. package/dist/ts/setting.d.ts +14 -0
  28. package/dist/ts/subtitle.d.ts +22 -0
  29. package/dist/ts/subtitles.d.ts +19 -0
  30. package/dist/ts/template.d.ts +94 -0
  31. package/dist/ts/thumbnails.d.ts +18 -0
  32. package/dist/ts/timer.d.ts +22 -0
  33. package/dist/ts/types.d.ts +146 -0
  34. package/dist/ts/user.d.ts +21 -0
  35. package/dist/ts/utils.d.ts +21 -0
  36. package/package.json +10 -6
  37. package/dist/kplayer.cjs.js +0 -410
  38. package/dist/kplayer.cjs.js.map +0 -1
  39. package/dist/kplayer.css +0 -1
  40. package/dist/kplayer.es.js.map +0 -1
  41. package/dist/kplayer.umd.js +0 -410
  42. package/dist/kplayer.umd.js.map +0 -1
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 GeekyAnts India Pvt Ltd
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,149 +1,477 @@
1
- ## Usage
2
-
3
- ```ts
4
- import KPlayer from 'kplayer';
5
- import type { KPlayerOptions } from 'kplayer';
6
- import 'kplayer/dist/kplayer.css';
7
- import Hls from 'hls.js';
8
-
9
- (window as Window & { Hls?: typeof Hls }).Hls = Hls;
10
-
11
- const container = document.getElementById('kplayer') as HTMLElement;
12
-
13
- const options: KPlayerOptions = {
14
- container,
15
- autoplay: false,
16
- airplay: true,
17
- chromecast: true,
18
- theme: '#FF0000',
19
- loop: true,
20
- lang: 'mn',
21
- screenshot: true,
22
- hotkey: true,
23
- preload: 'auto',
24
- logo: 'https://cdn.cdn3.co/storage/image/setting/583dfa2d-a6c7-4772-89aa-147a31c16ace.png',
25
- volume: 0.7,
26
- mutex: true,
27
- live: false,
28
- playbackSpeed: [0.5, 1, 1.25, 1.5, 2],
29
- preventClickToggle: false,
30
-
31
- title: {
32
- title: 'Noble Reincarnation: Born Blessed, So Ill Obtain Ultimate Power',
33
- description: 'Өв залгах эрх хасалт. | 11-р анги',
34
- back: true,
1
+ # KPlayer
2
+
3
+ A powerful, customizable HTML5 video player built with TypeScript.
4
+
5
+ ---
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install kplayer-ts
11
+ ```
12
+
13
+ Or load via CDN:
14
+
15
+ ```html
16
+ <div id="kplayer"></div>
17
+ <script src="kplayer.min.js"></script>
18
+ ```
19
+
20
+ ---
21
+
22
+ ## Quick Start
23
+
24
+ ```html
25
+ <div id="kplayer"></div>
26
+ ```
27
+
28
+ ```typescript
29
+ import KPlayer from "kplayer-ts";
30
+ import type { KPlayerOptions } from "kplayer-ts";
31
+
32
+ const dp = new KPlayer({
33
+ container: document.getElementById("kplayer"),
34
+ video: {
35
+ url: "demo.mp4",
36
+ pic: "demo.jpg",
37
+ thumbnails: "thumbnails.jpg",
38
+ },
39
+ });
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Options
45
+
46
+ | Name | Default | Description |
47
+ |---|---|---|
48
+ | `container` | `document.querySelector('.kplayer')` | Player container element |
49
+ | `live` | `false` | Enable live mode |
50
+ | `autoplay` | `false` | Auto play video on load |
51
+ | `theme` | `'#b7daff'` | Main accent color |
52
+ | `loop` | `false` | Loop video playback |
53
+ | `lang` | `navigator.language` | UI language: `'en'`, `'mn'`, `'zh-cn'`, `'zh-tw'`, `'ko-kr'`, `'de'`, `'ja'`, `'ru'` |
54
+ | `screenshot` | `false` | Enable screenshot button (requires CORS) |
55
+ | `airplay` | `false` | Enable AirPlay (Safari only) |
56
+ | `chromecast` | `false` | Enable Chromecast |
57
+ | `hotkey` | `true` | Enable keyboard shortcuts |
58
+ | `preload` | `'auto'` | Values: `'none'`, `'metadata'`, `'auto'` |
59
+ | `volume` | `0.7` | Default volume (0–1). Player remembers user setting |
60
+ | `playbackSpeed` | `[0.5, 0.75, 1, 1.25, 1.5, 2]` | Playback speed options |
61
+ | `logo` | — | Logo URL shown in top-left corner |
62
+ | `mutex` | `true` | Pause other players when this one starts |
63
+ | `preventClickToggle` | `false` | Prevent play/pause toggle on player click |
64
+ | `video` | — | Video configuration object (see below) |
65
+ | `subtitle` | — | Subtitle configuration object (see below) |
66
+ | `highlight` | `[]` | Time markers on the progress bar |
67
+ | `contextmenu` | `[]` | Custom right-click menu items |
68
+ | `title` | — | Title bar configuration |
69
+ | `vastAD` | `false` | Enable VAST/VMAP ad support |
70
+ | `vastADURL` | — | VAST or VMAP ad tag URL |
71
+ | `ad` | — | Custom ad configuration |
72
+ | `pluginOptions` | — | Options passed to MSE plugins (hls, flv, dash, webtorrent) |
73
+
74
+ ### `video` options
75
+
76
+ | Name | Default | Description |
77
+ |---|---|---|
78
+ | `video.url` | — | Video URL |
79
+ | `video.pic` | — | Video poster/thumbnail image |
80
+ | `video.thumbnails` | — | Preview thumbnails image strip |
81
+ | `video.type` | `'auto'` | `'auto'`, `'hls'`, `'flv'`, `'dash'`, `'webtorrent'`, `'normal'`, or custom type |
82
+ | `video.customType` | — | Custom type handler functions (see MSE section) |
83
+ | `video.quality` | — | Array of quality levels (see Quality Switching) |
84
+ | `video.defaultQuality` | `0` | Default quality index |
85
+
86
+ ### `subtitle` options
87
+
88
+ | Name | Default | Description |
89
+ |---|---|---|
90
+ | `subtitle.url` | required | Subtitle URL (string) or array of subtitle objects |
91
+ | `subtitle.type` | `'webvtt'` | Subtitle format (`'webvtt'` supported) |
92
+ | `subtitle.fontSize` | `'20px'` | Subtitle font size |
93
+ | `subtitle.bottom` | `'40px'` | Distance from player bottom (e.g. `'10px'`, `'10%'`) |
94
+ | `subtitle.color` | `'#fff'` | Subtitle text color |
95
+ | `subtitle.defaultSubtitle` | — | Default subtitle lang or name |
96
+ | `subtitle.encrypt` | `false` | Enable AES-CBC encrypted subtitles |
97
+ | `subtitle.key` | — | AES key (hex string, 32 chars) |
98
+ | `subtitle.iv` | — | AES IV (hex string, 32 chars) |
99
+
100
+ ### `title` options
101
+
102
+ | Name | Default | Description |
103
+ |---|---|---|
104
+ | `title.title` | — | Title text |
105
+ | `title.description` | — | Description / episode info |
106
+ | `title.back` | `false` | Show back button |
107
+ | `title.onBack` | — | Callback when back button is clicked |
108
+
109
+ ---
110
+
111
+ ## Full Example
112
+
113
+ ```typescript
114
+ import KPlayer from "kplayer-ts";
115
+ import type { KPlayerOptions } from "kplayer-ts";
116
+
117
+ const dp = new KPlayer({
118
+ container: document.getElementById("kplayer"),
119
+ autoplay: false,
120
+ theme: "#FF0000",
121
+ loop: true,
122
+ lang: "mn",
123
+ screenshot: true,
124
+ hotkey: true,
125
+ preload: "auto",
126
+ logo: "logo.png",
127
+ volume: 0.7,
128
+ mutex: true,
129
+ title: {
130
+ title: "Video Title",
131
+ description: "Episode 1",
132
+ back: true,
133
+ },
134
+ video: {
135
+ url: "demo.m3u8",
136
+ pic: "poster.jpg",
137
+ thumbnails: "thumbnails.jpg",
138
+ type: "hls",
139
+ },
140
+ pluginOptions: {
141
+ hls: {
142
+ debug: false,
143
+ maxBufferLength: 30,
144
+ },
145
+ },
146
+ subtitle: {
147
+ url: [
148
+ { name: "English", url: "en.vtt", lang: "en" },
149
+ { name: "Монгол", url: "mn.vtt", lang: "mn" },
150
+ ],
151
+ defaultSubtitle: "mn",
152
+ fontSize: "25px",
153
+ bottom: "10%",
154
+ color: "#ffffff",
155
+ },
156
+ highlight: [
157
+ { text: "OP Start", time: 20 },
158
+ { text: "OP End", time: 120 },
159
+ { text: "END Start", time: 520 },
160
+ { text: "END End", time: 550 },
161
+ ],
162
+ contextmenu: [
163
+ { text: "GitHub", link: "https://github.com/kenji-07" },
164
+ {
165
+ text: "Log player",
166
+ click: (player) => console.log(player),
167
+ },
168
+ ],
169
+ });
170
+ ```
171
+
172
+ ---
173
+
174
+ ## API
175
+
176
+ ```typescript
177
+ dp.play() // Play video
178
+ dp.pause() // Pause video
179
+ dp.toggle() // Toggle play/pause
180
+ dp.seek(time: number) // Seek to time in seconds
181
+ dp.speed(rate: number) // Set playback rate
182
+ dp.volume(percentage, nostorage?, nonotice?) // Set volume (0–1)
183
+ dp.notice(text, time?, opacity?) // Show notification
184
+ dp.switchQuality(index: number) // Switch quality (manual list)
185
+ dp.destroy() // Destroy player instance
186
+ ```
187
+
188
+ ### Properties
189
+
190
+ ```typescript
191
+ dp.video // Native HTMLVideoElement
192
+ dp.video.currentTime // Current playback position (seconds)
193
+ dp.video.duration // Total duration (seconds)
194
+ dp.video.paused // Whether video is paused
195
+ dp.plugins.hls // hls.js instance (when type: 'hls')
196
+ dp.plugins.flvjs // flv.js instance (when type: 'flv')
197
+ dp.plugins.dash // dash.js instance (when type: 'dash')
198
+ ```
199
+
200
+ ### Fullscreen
201
+
202
+ ```typescript
203
+ dp.fullScreen.request('browser') // Browser fullscreen
204
+ dp.fullScreen.request('web') // Web (page-level) fullscreen
205
+ dp.fullScreen.cancel('browser')
206
+ dp.fullScreen.cancel('web')
207
+ dp.fullScreen.toggle('browser')
208
+ dp.fullScreen.toggle('web')
209
+ ```
210
+
211
+ ---
212
+
213
+ ## Events
214
+
215
+ ```typescript
216
+ dp.on('play', () => console.log('playing'));
217
+ dp.on('ended', () => console.log('ended'));
218
+ ```
219
+
220
+ ### Video Events
221
+
222
+ `abort` · `canplay` · `canplaythrough` · `durationchange` · `emptied` · `ended` · `error` · `loadeddata` · `loadedmetadata` · `loadstart` · `pause` · `play` · `playing` · `progress` · `ratechange` · `seeked` · `seeking` · `stalled` · `suspend` · `timeupdate` · `volumechange` · `waiting`
223
+
224
+ ### Player Events
225
+
226
+ `screenshot` · `thumbnails_show` · `thumbnails_hide` · `contextmenu_show` · `contextmenu_hide` · `notice_show` · `notice_hide` · `quality_start` · `quality_end` · `destroy` · `resize` · `fullscreen` · `fullscreen_cancel` · `webfullscreen` · `webfullscreen_cancel` · `subtitle_show` · `subtitle_hide` · `subtitle_change` · `title_back`
227
+
228
+ ---
229
+
230
+ ## Quality Switching
231
+
232
+ ### Manual quality list
233
+
234
+ Provide a `quality` array with names and URLs. The player renders a quality menu automatically.
235
+
236
+ ```typescript
237
+ const dp = new KPlayer({
238
+ container: document.getElementById("kplayer"),
239
+ video: {
240
+ quality: [
241
+ { name: "HD", url: "demo.m3u8", type: "hls" },
242
+ { name: "SD", url: "demo.mp4", type: "normal" },
243
+ ],
244
+ defaultQuality: 0,
245
+ pic: "poster.jpg",
246
+ thumbnails: "thumbnails.jpg",
247
+ },
248
+ });
249
+ ```
250
+
251
+ ### HLS adaptive quality (auto)
252
+
253
+ When `type: 'hls'` is used, KPlayer automatically builds a quality menu from the HLS manifest levels, including an **Auto** option. Switching triggers `switching-quality` and `switched-quality` notices.
254
+
255
+ ---
256
+
257
+ ## MSE Support
258
+
259
+ ### HLS
260
+
261
+ Requires [hls.js](https://github.com/video-dev/hls.js).
262
+
263
+ ```typescript
264
+ import Hls from "hls.js";
265
+ (window as any).Hls = Hls;
266
+
267
+ const dp = new KPlayer({
268
+ container: document.getElementById("kplayer"),
269
+ video: {
270
+ url: "demo.m3u8",
271
+ type: "hls",
272
+ },
273
+ pluginOptions: {
274
+ hls: {
275
+ debug: false,
276
+ maxBufferLength: 30,
277
+ startLevel: -1, // -1 = auto
278
+ abrBandWidthFactor: 0.95,
279
+ fragLoadingMaxRetry: 6,
280
+ enableWorker: true,
281
+ // Request headers
282
+ xhrSetup: (xhr, url) => {
283
+ xhr.setRequestHeader("Authorization", "Bearer your-token");
284
+ },
35
285
  },
286
+ },
287
+ });
288
+
289
+ console.log(dp.plugins.hls); // hls.js instance
290
+ ```
291
+
292
+ Using `customType`:
36
293
 
37
- vastAD: false,
38
- vastADURL: 'https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpremidpost&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&cmsid=496&vid=short_onecue&correlator=',
39
-
40
- // ── Single HLS video ────────────────────────────────────────────────
41
- // video: {
42
- // url: 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_ts/master.m3u8',
43
- // pic: 'https://image.tmdb.org/t/p/original/nAxGnGHOsfzufThz20zgmRwKur3.jpg',
44
- // thumbnails: 'https://image.tmdb.org/t/p/original/nAxGnGHOsfzufThz20zgmRwKur3.jpg',
45
- // type: 'hls',
46
- // },
47
-
48
- // ── Ad examples ─────────────────────────────────────────────────────
49
- ad: {
50
- url: [
51
- {
52
- name: 'Image ad',
53
- type: 'image',
54
- backroundColor: '',
55
- url: 'https://cdn.cdn3.co/storage/image/setting/583dfa2d-a6c7-4772-89aa-147a31c16ace.png',
56
- deeplink: '',
57
- startTime: 0,
58
- skipTime: 10,
59
- },
60
- {
61
- name: 'Text ad',
62
- type: 'text',
63
- backroundColor: 'FF0000',
64
- url: 'Hello users ads watching',
65
- deeplink: '',
66
- startTime: 120,
67
- skipTime: 10,
68
- },
69
- {
70
- name: 'Video ad',
71
- type: 'video',
72
- backroundColor: '',
73
- url: 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
74
- deeplink: '',
75
- startTime: 130,
76
- skipTime: 10,
77
- },
78
- ],
294
+ ```typescript
295
+ const dp = new KPlayer({
296
+ container: document.getElementById("kplayer"),
297
+ video: {
298
+ url: "demo.m3u8",
299
+ type: "customHls",
300
+ customType: {
301
+ customHls: (video, player) => {
302
+ const hls = new Hls({ debug: false });
303
+ hls.loadSource(video.src);
304
+ hls.attachMedia(video);
305
+ },
79
306
  },
307
+ },
308
+ });
309
+ ```
80
310
 
81
- // ── Multi quality ────────────────────────────────────────────────────
82
- video: {
83
- quality: [
84
- {
85
- name: 'HD',
86
- url: 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_ts/master.m3u8',
87
- type: 'normal',
88
- },
89
- {
90
- name: 'SD',
91
- url: 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
92
- type: 'normal',
93
- },
94
- ],
95
- defaultQuality: 0,
96
- pic: 'https://image.tmdb.org/t/p/original/nAxGnGHOsfzufThz20zgmRwKur3.jpg',
97
- thumbnails: 'https://image.tmdb.org/t/p/original/nAxGnGHOsfzufThz20zgmRwKur3.jpg',
311
+ ### MPEG-DASH
312
+
313
+ Requires [dash.js](https://github.com/Dash-Industry-Forum/dash.js).
314
+
315
+ ```typescript
316
+ const dp = new KPlayer({
317
+ container: document.getElementById("kplayer"),
318
+ video: {
319
+ url: "demo.mpd",
320
+ type: "dash",
321
+ },
322
+ pluginOptions: {
323
+ dash: {
324
+ // dash.js config
98
325
  },
326
+ },
327
+ });
328
+
329
+ console.log(dp.plugins.dash); // dash.js instance
330
+ ```
99
331
 
100
- subtitle: {
101
- url: [
102
- {
103
- name: 'English',
104
- url: 'http://cdn.cdn3.co/storage/subtitle/e67dbcf0-96b2-4265-b787-680124cb9077.vtt',
105
- lang: 'en',
106
- },
107
- {
108
- name: 'Монгол',
109
- url: 'http://cdn.cdn3.co/storage/subtitle/e67dbcf0-96b2-4265-b787-680124cb9077.vtt',
110
- lang: 'mn',
111
- },
112
- {
113
- name: '日本語',
114
- url: 'https://raw.githubusercontent.com/videojs/video.js/main/docs/examples/shared/example-captions.vtt',
115
- lang: 'ja',
116
- },
117
- ],
118
- defaultSubtitle: 'mn',
119
- type: 'webvtt',
120
- fontSize: '25px',
121
- bottom: '10%',
122
- color: '#ffffff',
123
- encrypt: false,
124
- iv: '',
125
- key: '',
332
+ ### FLV
333
+
334
+ Requires [flv.js](https://github.com/bilibili/flv.js).
335
+
336
+ ```typescript
337
+ const dp = new KPlayer({
338
+ container: document.getElementById("kplayer"),
339
+ video: {
340
+ url: "demo.flv",
341
+ type: "flv",
342
+ },
343
+ pluginOptions: {
344
+ flv: {
345
+ mediaDataSource: {},
346
+ config: {},
126
347
  },
348
+ },
349
+ });
127
350
 
128
- contextmenu: [
129
- {
130
- text: 'custom1',
131
- link: 'https://github.com/DIYgod/DPlayer',
132
- },
133
- {
134
- text: 'custom2',
135
- click: (player) => {
136
- console.log(player);
137
- },
138
- },
139
- ],
351
+ console.log(dp.plugins.flvjs); // flv.js instance
352
+ ```
353
+
354
+ ### WebTorrent
355
+
356
+ Requires [WebTorrent](https://github.com/webtorrent/webtorrent).
140
357
 
141
- highlight: [
142
- { text: 'OP Start', time: 20 },
143
- { text: 'OP End', time: 120 },
144
- { text: 'END Start', time: 520 },
145
- { text: 'END End', time: 550 },
358
+ ```typescript
359
+ const dp = new KPlayer({
360
+ container: document.getElementById("kplayer"),
361
+ video: {
362
+ url: "magnet:?xt=...",
363
+ type: "webtorrent",
364
+ },
365
+ pluginOptions: {
366
+ webtorrent: {
367
+ // WebTorrent config
368
+ },
369
+ },
370
+ });
371
+
372
+ console.log(dp.plugins.webtorrent); // WebTorrent instance
373
+ ```
374
+
375
+ ### Custom MSE library
376
+
377
+ ```typescript
378
+ const dp = new KPlayer({
379
+ container: document.getElementById("kplayer"),
380
+ video: {
381
+ url: "demo.m3u8",
382
+ type: "customHls",
383
+ customType: {
384
+ customHls: (video, player) => {
385
+ const hls = new Hls({
386
+ p2pConfig: { live: false },
387
+ });
388
+ hls.loadSource(video.src);
389
+ hls.attachMedia(video);
390
+ },
391
+ },
392
+ },
393
+ });
394
+ ```
395
+
396
+ ---
397
+
398
+ ## Ads
399
+
400
+ ### Custom ads (image / text / video)
401
+
402
+ ```typescript
403
+ const dp = new KPlayer({
404
+ container: document.getElementById("kplayer"),
405
+ video: { url: "demo.mp4" },
406
+ ad: {
407
+ url: [
408
+ {
409
+ name: "Intro image ad",
410
+ type: "image",
411
+ url: "ad-banner.png",
412
+ deeplink: "https://example.com",
413
+ startTime: 0,
414
+ skipTime: 5,
415
+ },
416
+ {
417
+ name: "Mid-roll video ad",
418
+ type: "video",
419
+ url: "ad-video.mp4",
420
+ startTime: 120,
421
+ skipTime: 10,
422
+ },
423
+ {
424
+ name: "Text ad",
425
+ type: "text",
426
+ url: "Special offer – click to learn more",
427
+ backroundColor: "FF0000",
428
+ deeplink: "https://example.com",
429
+ startTime: 300,
430
+ skipTime: 5,
431
+ },
146
432
  ],
147
- };
433
+ },
434
+ });
435
+ ```
436
+
437
+ ### VAST / VMAP
438
+
439
+ ```typescript
440
+ const dp = new KPlayer({
441
+ container: document.getElementById("kplayer"),
442
+ video: { url: "demo.mp4" },
443
+ vastAD: true,
444
+ vastADURL: "https://your-ad-server.com/vmap.xml",
445
+ });
446
+ ```
447
+
448
+ ---
449
+
450
+ ## Keyboard Shortcuts
451
+
452
+ | Key | Action |
453
+ |---|---|
454
+ | `Space` | Play / Pause |
455
+ | `←` | Seek back 10s |
456
+ | `→` | Seek forward 10s |
457
+ | `↑` | Volume up |
458
+ | `↓` | Volume down |
459
+ | `Esc` | Exit web fullscreen |
460
+
461
+ ---
462
+
463
+ ## License
464
+
465
+ MIT
466
+
467
+ ---
468
+
469
+ ## Donation
470
+
471
+ If KPlayer has been useful to you, consider supporting its development. Your contribution helps keep the project maintained and growing.
472
+
473
+ | Platform | Link |
474
+ |---|---|
475
+ | 💖 GitHub Sponsors | [github.com/sponsors/kenji-07](https://github.com/sponsors/kenji-07) |
148
476
 
149
- const player = new KPlayer(options);
477
+ Thank you to all contributors and supporters! 🙏