kplayer-ts 1.0.3 → 1.0.4
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.
- package/README.md +146 -0
- package/dist/kplayer-ts.cjs +402 -0
- package/dist/kplayer-ts.cjs.map +1 -0
- package/dist/kplayer-ts.d.ts +3 -3
- package/dist/kplayer-ts.es.js +2166 -2522
- package/dist/kplayer-ts.es.js.map +1 -1
- package/dist/kplayer-ts.umd.js +139 -134
- package/dist/kplayer-ts.umd.js.map +1 -1
- package/dist/react/index.cjs +2 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.ts +31 -0
- package/dist/react/index.es.js +27 -0
- package/dist/react/index.es.js.map +1 -0
- package/dist/ts/controller.d.ts +7 -0
- package/dist/ts/player.d.ts +3 -0
- package/dist/ts/setting.d.ts +1 -0
- package/dist/ts/types.d.ts +17 -0
- package/package.json +41 -11
- package/dist/kplayer-ts.cjs.js +0 -397
- package/dist/kplayer-ts.cjs.js.map +0 -1
package/README.md
CHANGED
|
@@ -41,6 +41,99 @@ const dp = new KPlayer({
|
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
+
## React / Next.js
|
|
45
|
+
|
|
46
|
+
KPlayer is **SSR-safe** — importing the package never touches `window` / `document`
|
|
47
|
+
at module load, so it works in Next.js (App Router or Pages Router) and during the
|
|
48
|
+
server build without crashing.
|
|
49
|
+
|
|
50
|
+
The player ships with a built-in `16 / 9` aspect ratio, so it stays visible even when
|
|
51
|
+
the container has no explicit height. Give the container a `height` to override it.
|
|
52
|
+
|
|
53
|
+
### Use the bundled component (recommended)
|
|
54
|
+
|
|
55
|
+
A ready-made wrapper is published at `kplayer-ts/react`. It creates the player in
|
|
56
|
+
`useEffect` and destroys it on unmount for you. `react` is an optional peer dependency.
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { KPlayer } from "kplayer-ts/react";
|
|
60
|
+
|
|
61
|
+
export function VideoPlayer({ url }: { url: string }) {
|
|
62
|
+
return (
|
|
63
|
+
<KPlayer
|
|
64
|
+
options={{ video: { url, type: "hls" } }}
|
|
65
|
+
style={{ width: "100%" }}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
In **Next.js (App Router)**, add `"use client"` at the top of the file. To access the
|
|
72
|
+
underlying instance, pass a `ref` or use `onReady`:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
"use client";
|
|
76
|
+
import { useRef } from "react";
|
|
77
|
+
import { KPlayer, type KPlayerInstance } from "kplayer-ts/react";
|
|
78
|
+
|
|
79
|
+
export default function VideoPlayer({ url }: { url: string }) {
|
|
80
|
+
const ref = useRef<KPlayerInstance>(null);
|
|
81
|
+
return (
|
|
82
|
+
<KPlayer
|
|
83
|
+
ref={ref}
|
|
84
|
+
options={{ video: { url, type: "hls" } }}
|
|
85
|
+
onReady={(player) => console.log("ready", player.version)}
|
|
86
|
+
style={{ width: "100%" }}
|
|
87
|
+
/>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
| Prop | Type | Description |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| `options` | `Omit<KPlayerOptions, "container">` | Player options (no `container` — the component owns the `<div>`). Read once on mount; change `key` to reload. |
|
|
95
|
+
| `onReady` | `(player) => void` | Called once with the instance right after creation |
|
|
96
|
+
| `ref` | `Ref<KPlayerInstance>` | Receives the player instance (`null` after unmount) |
|
|
97
|
+
| …rest | `HTMLAttributes<HTMLDivElement>` | `style`, `className`, etc. are forwarded to the container `<div>` |
|
|
98
|
+
|
|
99
|
+
### Or wire it up manually
|
|
100
|
+
|
|
101
|
+
If you prefer not to use the wrapper, create the instance yourself inside `useEffect`
|
|
102
|
+
(browser only) and call `destroy()` on unmount:
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
"use client";
|
|
106
|
+
import { useEffect, useRef } from "react";
|
|
107
|
+
import KPlayer from "kplayer-ts";
|
|
108
|
+
|
|
109
|
+
export default function VideoPlayer({ url }: { url: string }) {
|
|
110
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
if (!ref.current) return;
|
|
113
|
+
const dp = new KPlayer({ container: ref.current, video: { url, type: "hls" } });
|
|
114
|
+
return () => dp.destroy();
|
|
115
|
+
}, [url]);
|
|
116
|
+
return <div ref={ref} style={{ width: "100%" }} />;
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Loading `hls.js`
|
|
121
|
+
|
|
122
|
+
`hls.js` is an external peer of the bundle — the player reads it from `window.Hls`.
|
|
123
|
+
Import it and expose it before creating the player:
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
import Hls from "hls.js";
|
|
127
|
+
if (typeof window !== "undefined") {
|
|
128
|
+
(window as unknown as { Hls: typeof Hls }).Hls = Hls;
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Alternatively, pass your own instance via [`video.customType`](#mse-support) — that
|
|
133
|
+
path does not need `window.Hls`.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
44
137
|
## Options
|
|
45
138
|
|
|
46
139
|
| Name | Default | Description |
|
|
@@ -96,6 +189,31 @@ const dp = new KPlayer({
|
|
|
96
189
|
| `subtitle.encrypt` | `false` | Enable AES-CBC encrypted subtitles |
|
|
97
190
|
| `subtitle.key` | — | AES key (hex string, 32 chars) |
|
|
98
191
|
| `subtitle.iv` | — | AES IV (hex string, 32 chars) |
|
|
192
|
+
| `subtitle.keyProvider` | — | `() => { key, iv } \| Promise<{ key, iv }>` — fetch the key/iv at runtime instead of hard-coding them |
|
|
193
|
+
|
|
194
|
+
> ⚠️ **Security note on encrypted subtitles.** Decryption happens **in the browser**,
|
|
195
|
+
> so the `key` and `iv` can never be fully hidden from a determined user — they are
|
|
196
|
+
> always recoverable from DevTools / the Network tab / the JS bundle. Subtitle
|
|
197
|
+
> "encryption" here only deters *casual* scraping; it is **not** real content
|
|
198
|
+
> protection. Two practical steps:
|
|
199
|
+
>
|
|
200
|
+
> 1. **Don't hard-code the key in your page/bundle.** Use `keyProvider` to fetch it
|
|
201
|
+
> at runtime from an authenticated backend endpoint, so the key isn't published
|
|
202
|
+
> in static source and the server can apply auth / rate-limiting / per-session keys.
|
|
203
|
+
> 2. For genuine protection of the *video* itself, use DRM (EME — Widevine / PlayReady
|
|
204
|
+
> / FairPlay), not client-side AES.
|
|
205
|
+
>
|
|
206
|
+
> ```ts
|
|
207
|
+
> subtitle: {
|
|
208
|
+
> url: [{ name: "Монгол", url: "mn.vtt", lang: "mn" }],
|
|
209
|
+
> encrypt: true,
|
|
210
|
+
> // key/iv-г bundle-д бичихгүйгээр backend-ээс татаж авна
|
|
211
|
+
> keyProvider: async () => {
|
|
212
|
+
> const res = await fetch("/api/subtitle-key", { credentials: "include" });
|
|
213
|
+
> return res.json(); // → { key: "…hex…", iv: "…hex…" }
|
|
214
|
+
> },
|
|
215
|
+
> }
|
|
216
|
+
> ```
|
|
99
217
|
|
|
100
218
|
### `title` options
|
|
101
219
|
|
|
@@ -458,6 +576,34 @@ const dp = new KPlayer({
|
|
|
458
576
|
| `↓` | Volume down |
|
|
459
577
|
| `Esc` | Exit web fullscreen |
|
|
460
578
|
|
|
579
|
+
### Touch gestures (mobile)
|
|
580
|
+
|
|
581
|
+
| Gesture | Action |
|
|
582
|
+
|---|---|
|
|
583
|
+
| Single tap | Show / hide controls |
|
|
584
|
+
| Double-tap left half | Seek back 10s (repeat to stack: 20s, 30s…) |
|
|
585
|
+
| Double-tap right half | Seek forward 10s (repeat to stack) |
|
|
586
|
+
|
|
587
|
+
A YouTube-style ripple shows the seek direction and accumulated amount.
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
|
|
591
|
+
## Accessibility
|
|
592
|
+
|
|
593
|
+
KPlayer ships with built-in a11y support:
|
|
594
|
+
|
|
595
|
+
- All controls are real `<button>`s with localized `aria-label`s; decorative icons are
|
|
596
|
+
`aria-hidden`. The player root is a labelled `role="region"` (uses the video title).
|
|
597
|
+
- The progress and volume bars are `role="slider"` with live `aria-valuenow` /
|
|
598
|
+
`aria-valuetext`, and are keyboard-operable when focused:
|
|
599
|
+
- **Seek bar**: `←` / `→` (±5s), `PageUp` / `PageDown` (±30s), `Home` / `End`.
|
|
600
|
+
- **Volume bar**: `↑` / `↓` (±5%), `Home` / `End`.
|
|
601
|
+
- Settings-menu rows are `role="menuitem"`, reachable by `Tab` and activated with
|
|
602
|
+
`Enter` / `Space`.
|
|
603
|
+
- A visible focus ring is shown for keyboard users (`:focus-visible`).
|
|
604
|
+
|
|
605
|
+
Labels are localized in every supported `lang`.
|
|
606
|
+
|
|
461
607
|
---
|
|
462
608
|
|
|
463
609
|
## License
|