alpha-video-player-js 1.1.0 → 1.3.0
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 +153 -168
- package/README.zh-CN.md +154 -0
- package/dist/alpha-video-player-js.d.ts +13 -4
- package/dist/alpha-video-player-js.js +1 -1
- package/dist/react.d.ts +34 -18
- package/dist/react.js +1 -1
- package/dist/vue2.d.ts +84 -1
- package/dist/vue2.js +1 -1
- package/dist/vue3.d.ts +108 -1
- package/dist/vue3.js +1 -1
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -1,191 +1,179 @@
|
|
|
1
1
|
# alpha-video-player-js
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[中文文档](./README.zh-CN.md) · [Demo](https://trp1119.github.io/alpha-video-player-js-demo)
|
|
4
4
|
|
|
5
|
-
alpha-video-player-js
|
|
5
|
+
`alpha-video-player-js` is a zero-dependency web SDK for playing videos with transparency. It rebuilds an alpha video frame on a `<canvas>` by combining its RGB image with a grayscale alpha mask. Use it for high-fidelity motion effects that are more complex than APNG or Lottie.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Highlights
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
9
|
+
- WebGL rendering with a Canvas 2D fallback.
|
|
10
|
+
- Native `<video>` playback for regular, opaque videos.
|
|
11
|
+
- Supports horizontal and vertical RGB/alpha layouts, including reversed layouts.
|
|
12
|
+
- Supports scaled alpha masks and alignment on the secondary axis.
|
|
13
|
+
- Framework components for Vue 3, Vue 2.7+, and React.
|
|
14
|
+
- No runtime dependencies; framework packages are optional peer dependencies.
|
|
13
15
|
|
|
14
|
-
##
|
|
15
|
-
|
|
16
|
-
### 安装
|
|
16
|
+
## Installation
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
npm
|
|
19
|
+
npm install alpha-video-player-js
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
The container needs an explicit size when `width` and `height` are not supplied.
|
|
23
25
|
|
|
24
26
|
```ts
|
|
25
|
-
import
|
|
27
|
+
import AlphaVideoPlayer from 'alpha-video-player-js'
|
|
28
|
+
|
|
29
|
+
const container = document.querySelector<HTMLElement>('#player')!
|
|
30
|
+
|
|
31
|
+
const player = new AlphaVideoPlayer({
|
|
32
|
+
container,
|
|
33
|
+
src: 'https://example.com/alpha-video.mp4',
|
|
34
|
+
width: 320,
|
|
35
|
+
height: 180,
|
|
36
|
+
muted: true,
|
|
37
|
+
loop: true,
|
|
38
|
+
autoShow: true,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
await player.play()
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
For autoplay, keep the video muted and handle the rejected `play()` promise; browsers may still enforce autoplay policies.
|
|
45
|
+
|
|
46
|
+
## Alpha video format
|
|
47
|
+
|
|
48
|
+
An alpha video stores two images in each ordinary MP4 frame:
|
|
26
49
|
|
|
27
|
-
|
|
50
|
+
- **RGB region**: the visible color image.
|
|
51
|
+
- **Alpha region**: a grayscale mask. Its red channel becomes the output alpha (`white = opaque`, `black = transparent`).
|
|
52
|
+
|
|
53
|
+
`orientation` determines how the regions are packed and `side` determines where the RGB region is located:
|
|
54
|
+
|
|
55
|
+
| `orientation` | `side: 'front'` | `side: 'back'` |
|
|
56
|
+
| --- | --- | --- |
|
|
57
|
+
| `landscape` | RGB left, alpha right | Alpha left, RGB right |
|
|
58
|
+
| `portrait` | RGB top, alpha bottom | Alpha top, RGB bottom |
|
|
59
|
+
|
|
60
|
+
### Scaled alpha masks
|
|
61
|
+
|
|
62
|
+
`alphaScale` is the alpha mask's width and height relative to the RGB image:
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
1 equal-size RGB and alpha regions (default)
|
|
66
|
+
0.5 alpha is half the RGB width and half the RGB height
|
|
67
|
+
0 no alpha mask; play the source as a native opaque video
|
|
28
68
|
```
|
|
29
69
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
| 参数 | 含义 | 默认值 | 是否必传 |
|
|
33
|
-
| ------------- | ---------------------------------- | --------- | -------- |
|
|
34
|
-
| container | dom 容器 | - | 是 |
|
|
35
|
-
| src | 播放地址 | - | 否(无则仅创建画布,可后续 `setSrc`) |
|
|
36
|
-
| width | 渲染宽度(默认取容器宽度) | - | 否 |
|
|
37
|
-
| height | 渲染高度(默认取容器高度) | - | 否 |
|
|
38
|
-
| crossOrigin | 跨域视频:`anonymous` \| `use-credentials` | `anonymous` | 否 |
|
|
39
|
-
| muted | 是否静音播放 | true | 否 |
|
|
40
|
-
| loop | 是否循环播放 | false | 否 |
|
|
41
|
-
| playbackRate | 播放速率 | 1 | 否 |
|
|
42
|
-
| fps | 限帧(0 表示不额外限帧) | 0 | 否 |
|
|
43
|
-
| videoFrame | 是否使用 `requestVideoFrameCallback` 驱动帧循环 | false | 否 |
|
|
44
|
-
| orientation | 视频排布方式 `landscape` \| `portrait` | landscape | 否 |
|
|
45
|
-
| side | RGB 通道区域位置 `front` \| `back` | front | 否 |
|
|
46
|
-
| autoShow | 可播放后自动绘制首帧 | false | 否 |
|
|
47
|
-
| autoClear | 播放结束后是否清空画布 | true | 否 |
|
|
48
|
-
| autoDestroy | 播放结束后是否自动销毁实例 | false | 否 |
|
|
49
|
-
| autoResize | 元数据加载后是否按视频比例调整 canvas:`contain` \| `width` \| `height` \| `false` | `contain` | 否 |
|
|
50
|
-
| debug | 是否在控制台输出调试信息 | false | 否 |
|
|
51
|
-
| onInitSuccess | 初始化成功回调 | - | 否 |
|
|
52
|
-
| onInitError | 初始化失败回调 | - | 否 |
|
|
53
|
-
| onLoad | 元数据加载完成回调 | - | 否 |
|
|
54
|
-
| onCanPlay | 可以播放回调(首次) | - | 否 |
|
|
55
|
-
| onPlay | 开始播放回调 | - | 否 |
|
|
56
|
-
| onLoop | 循环再次可播放时回调 | - | 否 |
|
|
57
|
-
| onPause | 暂停播放回调 | - | 否 |
|
|
58
|
-
| onEnded | 结束播放回调 | - | 否 |
|
|
59
|
-
| onError | 错误回调,参数为 `unknown`(见下「错误处理」) | - | 否 |
|
|
60
|
-
| onDestroy | 销毁实例回调 | - | 否 |
|
|
61
|
-
|
|
62
|
-
### 实例属性
|
|
63
|
-
|
|
64
|
-
| 属性 | 含义 | 类型 |
|
|
65
|
-
| ------- | ---------- | ------- |
|
|
66
|
-
| playing | 是否播放中 | Boolean |
|
|
67
|
-
| loop | 是否循环 | Boolean |
|
|
68
|
-
|
|
69
|
-
### 实例方法
|
|
70
|
-
|
|
71
|
-
| 方法 | 含义 | 参数 |
|
|
72
|
-
| ----------------------------- | ---------------- | ------------------- |
|
|
73
|
-
| play(config?) | 播放/继续播放,返回 `Promise`;失败时 reject 原始错误 | 可选,同实例参数的部分字段 |
|
|
74
|
-
| pause() | 暂停播放 | - |
|
|
75
|
-
| destroy() | 销毁实例 | - |
|
|
76
|
-
| reset() | 重置播放进度 | - |
|
|
77
|
-
| setSrc(src) | 设置播放地址 | 播放地址(string) |
|
|
78
|
-
| setCurrentTime(time) | 设置播放进度 | 秒(number) |
|
|
79
|
-
| setMute(muted) | 设置是否静音 | boolean |
|
|
80
|
-
| setLoop(loop) | 设置是否循环 | boolean |
|
|
81
|
-
| setPlaybackRate(playbackRate) | 设置播放倍速 | number |
|
|
82
|
-
|
|
83
|
-
### 错误处理
|
|
84
|
-
|
|
85
|
-
- **`play()` 失败**(如自动播放策略拒绝等):`Promise` 会被 **reject**,reject 的值为浏览器抛出的**原始错误**(常见为 `DOMException`);同时若配置了 **`onError`**,也会用**同一引用**调用一次。
|
|
86
|
-
- **`<video>` 媒体错误**(地址无效、解码失败、跨域等):通过 **`onError`** 传入(多为 `Event` / `ErrorEvent`),随后实例会 **`destroy()`**。
|
|
87
|
-
|
|
88
|
-
示例(在创建实例时传入 `onError`):
|
|
70
|
+
When `alphaScale < 1`, use `alphaAlign` to locate the mask on the secondary axis: `start` means top for `landscape` / left for `portrait`; `end` means bottom / right.
|
|
89
71
|
|
|
90
72
|
```ts
|
|
91
|
-
|
|
73
|
+
new AlphaVideoPlayer({
|
|
92
74
|
container,
|
|
93
75
|
src,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
76
|
+
orientation: 'landscape',
|
|
77
|
+
side: 'front',
|
|
78
|
+
alphaScale: 0.5,
|
|
79
|
+
alphaAlign: 'start',
|
|
97
80
|
})
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
await player.play()
|
|
101
|
-
} catch (e) {
|
|
102
|
-
// play 失败时与 onError 为同一 err 引用
|
|
103
|
-
console.error(e)
|
|
104
|
-
}
|
|
105
81
|
```
|
|
106
82
|
|
|
107
|
-
##
|
|
108
|
-
|
|
109
|
-
|
|
83
|
+
## Core API
|
|
84
|
+
|
|
85
|
+
### Configuration
|
|
86
|
+
|
|
87
|
+
| Option | Type / default | Description |
|
|
88
|
+
| --- | --- | --- |
|
|
89
|
+
| `container` | `HTMLElement` | **Required.** Mount target. |
|
|
90
|
+
| `src` | `string` | Video URL. Optional at construction; call `setSrc()` later. |
|
|
91
|
+
| `poster` | `string` | Poster image. A transparent fallback is used by default. |
|
|
92
|
+
| `width`, `height` | `number` | Logical render size; defaults to container dimensions. |
|
|
93
|
+
| `crossOrigin` | `'anonymous'` | CORS mode: `'anonymous'` or `'use-credentials'`. |
|
|
94
|
+
| `muted` | `true` | Whether the video is muted. |
|
|
95
|
+
| `loop` | `false` | Loop playback. |
|
|
96
|
+
| `playbackRate` | `1` | Playback speed. |
|
|
97
|
+
| `fps` | `0` | Animation-frame cap; `0` means uncapped. |
|
|
98
|
+
| `videoFrame` | `false` | Prefer `requestVideoFrameCallback` when supported. |
|
|
99
|
+
| `orientation` | `'landscape'` | Alpha-video packing direction. |
|
|
100
|
+
| `side` | `'front'` | RGB region position. |
|
|
101
|
+
| `alphaScale` | `1` | Alpha mask scale from `0` to `1`; `0` uses native video. |
|
|
102
|
+
| `alphaAlign` | `'start'` | Scaled mask alignment: `'start'` or `'end'`. |
|
|
103
|
+
| `autoShow` | `false` | Draw the first frame once playable. |
|
|
104
|
+
| `autoClear` | `true` | Clear the canvas when playback ends. |
|
|
105
|
+
| `autoDestroy` | `false` | Destroy the player when playback ends. |
|
|
106
|
+
| `autoResize` | `'contain'` | Resize mode: `'contain'`, `'width'`, `'height'`, or `false`. |
|
|
107
|
+
| `debug` | `false` | Print debug output. |
|
|
108
|
+
|
|
109
|
+
Callbacks: `onInitSuccess`, `onInitError`, `onLoad`, `onCanPlay`, `onPlay`, `onLoop`, `onPause`, `onEnded`, `onError`, and `onDestroy`.
|
|
110
|
+
|
|
111
|
+
### Instance methods and properties
|
|
112
|
+
|
|
113
|
+
| Member | Description |
|
|
114
|
+
| --- | --- |
|
|
115
|
+
| `playing` | Read-only boolean that reports whether playback is active. |
|
|
116
|
+
| `loop` | Read-only boolean that reports loop state. |
|
|
117
|
+
| `play(config?)` | Starts or resumes playback and returns a `Promise`. The optional config overrides applicable settings. |
|
|
118
|
+
| `pause()` | Pauses playback and stops the frame loop. |
|
|
119
|
+
| `reset()` | Resets playback progress. |
|
|
120
|
+
| `setSrc(src)` | Changes the video source. |
|
|
121
|
+
| `setCurrentTime(seconds)` | Seeks to a time in seconds. |
|
|
122
|
+
| `setMute(muted)` | Changes mute state. |
|
|
123
|
+
| `setLoop(loop)` | Changes loop state. |
|
|
124
|
+
| `setPlaybackRate(rate)` | Changes playback speed. |
|
|
125
|
+
| `destroy()` | Releases DOM, canvas, and rendering resources. Do not reuse the instance afterward. |
|
|
126
|
+
|
|
127
|
+
`play()` rejects with the browser's original error (for example, a `DOMException` from autoplay restrictions) and also invokes `onError` with that same value. Media load/decode failures are delivered through `onError` and then destroy the instance.
|
|
128
|
+
|
|
129
|
+
## Framework components
|
|
130
|
+
|
|
131
|
+
All component packages expose the same player options except `container`, which the component owns. Their refs expose `play`, `pause`, `destroy`, `reset`, `setSrc`, `setCurrentTime`, `setMute`, `setLoop`, `setPlaybackRate`, and `getPlayer`.
|
|
110
132
|
|
|
111
133
|
### Vue 3
|
|
112
134
|
|
|
113
|
-
```
|
|
135
|
+
```vue
|
|
136
|
+
<script setup lang="ts">
|
|
137
|
+
import { ref } from 'vue'
|
|
114
138
|
import AlphaVideoPlayer from 'alpha-video-player-js/vue3'
|
|
115
|
-
|
|
139
|
+
import type { IAlphaVideoPlayerRef } from 'alpha-video-player-js/vue3'
|
|
140
|
+
|
|
141
|
+
const player = ref<IAlphaVideoPlayerRef | null>(null)
|
|
142
|
+
</script>
|
|
116
143
|
|
|
117
|
-
```html
|
|
118
144
|
<template>
|
|
119
|
-
|
|
120
|
-
<div class="player-wrap" :style="{ width: '250px', height: '133px' }">
|
|
145
|
+
<div style="width: 320px; height: 180px">
|
|
121
146
|
<AlphaVideoPlayer
|
|
122
|
-
ref="
|
|
123
|
-
src="https://example.com/video.mp4"
|
|
124
|
-
:width="
|
|
125
|
-
:height="
|
|
147
|
+
ref="player"
|
|
148
|
+
src="https://example.com/alpha-video.mp4"
|
|
149
|
+
:width="320"
|
|
150
|
+
:height="180"
|
|
126
151
|
:muted="true"
|
|
127
|
-
:loop="
|
|
128
|
-
|
|
129
|
-
orientation="landscape"
|
|
130
|
-
side="front"
|
|
131
|
-
@initSuccess="onReady"
|
|
132
|
-
@error="onError"
|
|
152
|
+
:loop="true"
|
|
153
|
+
@initSuccess="player?.play()"
|
|
133
154
|
/>
|
|
134
155
|
</div>
|
|
135
|
-
<!-- 倍速滑块:须用 v-model.number,否则 range 会得到字符串,与 playbackRate 的 Number 类型不符 -->
|
|
136
|
-
<input v-model.number="playbackRate" type="range" min="0.5" max="2" step="0.5" />
|
|
137
156
|
</template>
|
|
138
|
-
|
|
139
|
-
<script setup lang="ts">
|
|
140
|
-
import { ref } from 'vue'
|
|
141
|
-
import AlphaVideoPlayer from 'alpha-video-player-js/vue3'
|
|
142
|
-
|
|
143
|
-
const playerRef = ref()
|
|
144
|
-
const playbackRate = ref(1)
|
|
145
|
-
|
|
146
|
-
const onReady = () => {
|
|
147
|
-
playerRef.value?.play()
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const onError = (e: unknown) => {
|
|
151
|
-
console.error(e)
|
|
152
|
-
}
|
|
153
|
-
</script>
|
|
154
157
|
```
|
|
155
158
|
|
|
156
|
-
|
|
159
|
+
Use `v-model.number` for numeric form controls such as `playbackRate`; native range inputs otherwise produce strings. After calling a component ref's `destroy()`, remount the component (for example, change its `:key`) to create a new player.
|
|
157
160
|
|
|
158
|
-
|
|
159
|
-
import AlphaVideoPlayer from 'alpha-video-player-js/vue2'
|
|
160
|
-
```
|
|
161
|
+
### Vue 2.7+
|
|
161
162
|
|
|
162
|
-
```
|
|
163
|
+
```vue
|
|
163
164
|
<template>
|
|
164
165
|
<AlphaVideoPlayer
|
|
165
166
|
ref="player"
|
|
166
|
-
src="
|
|
167
|
+
:src="src"
|
|
167
168
|
:muted="true"
|
|
168
|
-
|
|
169
|
-
side="front"
|
|
170
|
-
@init-success="onReady"
|
|
171
|
-
@error="onError"
|
|
169
|
+
@init-success="$refs.player.play()"
|
|
172
170
|
/>
|
|
173
171
|
</template>
|
|
174
172
|
|
|
175
173
|
<script>
|
|
176
174
|
import AlphaVideoPlayer from 'alpha-video-player-js/vue2'
|
|
177
175
|
|
|
178
|
-
export default {
|
|
179
|
-
components: { AlphaVideoPlayer },
|
|
180
|
-
methods: {
|
|
181
|
-
onReady() {
|
|
182
|
-
this.$refs.player.play()
|
|
183
|
-
},
|
|
184
|
-
onError(e) {
|
|
185
|
-
console.error(e)
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
}
|
|
176
|
+
export default { components: { AlphaVideoPlayer } }
|
|
189
177
|
</script>
|
|
190
178
|
```
|
|
191
179
|
|
|
@@ -194,44 +182,41 @@ export default {
|
|
|
194
182
|
```tsx
|
|
195
183
|
import { useRef } from 'react'
|
|
196
184
|
import AlphaVideoPlayer from 'alpha-video-player-js/react'
|
|
197
|
-
import type {
|
|
198
|
-
|
|
199
|
-
function App() {
|
|
200
|
-
const playerRef = useRef<AlphaVideoPlayerRef>(null)
|
|
185
|
+
import type { IAlphaVideoPlayerRef } from 'alpha-video-player-js/react'
|
|
201
186
|
|
|
187
|
+
export function Effect() {
|
|
188
|
+
const player = useRef<IAlphaVideoPlayerRef>(null)
|
|
202
189
|
return (
|
|
203
190
|
<AlphaVideoPlayer
|
|
204
|
-
ref={
|
|
205
|
-
src="https://example.com/video.mp4"
|
|
191
|
+
ref={player}
|
|
192
|
+
src="https://example.com/alpha-video.mp4"
|
|
206
193
|
muted
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
onInitSuccess={() => playerRef.current?.play()}
|
|
210
|
-
onError={(e) => console.error(e)}
|
|
194
|
+
loop
|
|
195
|
+
onInitSuccess={() => player.current?.play()}
|
|
211
196
|
/>
|
|
212
197
|
)
|
|
213
198
|
}
|
|
214
199
|
```
|
|
215
200
|
|
|
216
|
-
|
|
201
|
+
The React component also accepts `className` and `style`. Components reactively synchronize changes to `src`, `muted`, `loop`, and `playbackRate`; changing packing options (`orientation`, `side`, `alphaScale`, `alphaAlign`) requires remounting.
|
|
202
|
+
|
|
203
|
+
### TypeScript exports
|
|
204
|
+
|
|
205
|
+
| Import path | Types |
|
|
206
|
+
| --- | --- |
|
|
207
|
+
| `alpha-video-player-js` | `IAlphaVideoPlayer`, `IConfig`, `IOptionalConfig`, `IOrientation`, `ISide`, `IAlphaAlign` |
|
|
208
|
+
| `alpha-video-player-js/vue3`, `.../vue2` | `IAlphaVideoPlayer`, `IAlphaVideoPlayerRef` |
|
|
209
|
+
| `alpha-video-player-js/react` | `IAlphaVideoPlayerProps`, `IAlphaVideoPlayerRef` |
|
|
217
210
|
|
|
218
|
-
|
|
219
|
-
- **根节点与布局**:组件只渲染一个**无业务 class** 的根 `div`;若需要与业务一致的绝对定位、背景图上的对齐等,请在**外层元素**上写样式,并通过 **`width` / `height` props**(及 `orientation` / `side` 等)控制画布与拼合逻辑。
|
|
220
|
-
- **销毁后再次挂载**:调用 ref 上的 `destroy()` 后实例已清空,不会在同一次挂载中自动重新 `init`;需要再次初始化时,可对组件使用 **`:key` 递增**或 **`v-if` 切换**,以重新挂载(演示项目 `alpha-video-player-js-demo` 的 `Item.vue` 即采用 `:key` 方案)。
|
|
221
|
-
- **事件/回调**:
|
|
222
|
-
- Vue 3:`@initSuccess`、`@initError`、`@load`、`@canPlay`、`@play`、`@loop`、`@pause`、`@ended`、`@error`、`@destroy`
|
|
223
|
-
- Vue 2:`@init-success`、`@init-error`、`@load`、`@can-play`、`@play`、`@loop`、`@pause`、`@ended`、`@error`、`@destroy`
|
|
224
|
-
- React:`onInitSuccess`、`onInitError`、`onLoad`、`onCanPlay`、`onPlay`、`onLoop`、`onPause`、`onEnded`、`onError`、`onDestroy`
|
|
225
|
-
- **实例方法**(通过 ref 调用):`play()`、`pause()`、`destroy()`、`reset()`、`setSrc()`、`setCurrentTime()`、`setMute()`、`setLoop()`、`setPlaybackRate()`、`getPlayer()`
|
|
226
|
-
- **响应式 props**:`src`、`muted`、`loop`、`playbackRate` 变更时自动同步到播放器实例。
|
|
227
|
-
- **生命周期**:组件挂载时自动初始化,卸载时自动销毁。
|
|
228
|
-
- **peerDependencies**:vue / react / react-dom 均为可选,只需安装你使用的框架。
|
|
211
|
+
If you need both a framework ref and the core instance type, import them from the same framework subpath. This avoids incompatibility when tooling resolves separate generated declarations.
|
|
229
212
|
|
|
230
|
-
##
|
|
213
|
+
## Development
|
|
231
214
|
|
|
232
|
-
|
|
233
|
-
|
|
215
|
+
```bash
|
|
216
|
+
npm run dev # Watch with Rollup
|
|
217
|
+
npm run build # Production bundles and declarations
|
|
218
|
+
```
|
|
234
219
|
|
|
235
|
-
##
|
|
220
|
+
## License
|
|
236
221
|
|
|
237
|
-
|
|
222
|
+
[ISC](./package.json)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# alpha-video-player-js(中文文档)
|
|
2
|
+
|
|
3
|
+
[English](./README.md) · [在线演示](https://trp1119.github.io/alpha-video-player-js-demo)
|
|
4
|
+
|
|
5
|
+
`alpha-video-player-js` 是零运行时依赖的 Web 透明视频播放 SDK。它把同一 MP4 帧内的 RGB 画面与灰度 Alpha 遮罩重新合成到 `<canvas>`,用于播放高还原度的透明视频动效。
|
|
6
|
+
|
|
7
|
+
## 特性
|
|
8
|
+
|
|
9
|
+
- 优先使用 WebGL,Canvas 2D 自动降级。
|
|
10
|
+
- `alphaScale: 0` 时自动使用原生 `<video>` 播放普通不透明视频。
|
|
11
|
+
- 支持横向、纵向、RGB 在前/后四类拼合格式,以及缩放 Alpha 遮罩。
|
|
12
|
+
- 提供 Vue 3、Vue 2.7+、React 组件入口。
|
|
13
|
+
- 零运行时依赖。
|
|
14
|
+
|
|
15
|
+
## 安装与快速使用
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install alpha-video-player-js
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import AlphaVideoPlayer from 'alpha-video-player-js'
|
|
23
|
+
|
|
24
|
+
const player = new AlphaVideoPlayer({
|
|
25
|
+
container: document.querySelector<HTMLElement>('#player')!,
|
|
26
|
+
src: 'https://example.com/alpha-video.mp4',
|
|
27
|
+
width: 320,
|
|
28
|
+
height: 180,
|
|
29
|
+
muted: true,
|
|
30
|
+
loop: true,
|
|
31
|
+
autoShow: true,
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
await player.play()
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
未传 `width` / `height` 时,容器必须有可计算的尺寸。浏览器自动播放策略可能拒绝 `play()`,请处理其 Promise 拒绝。
|
|
38
|
+
|
|
39
|
+
## 素材格式
|
|
40
|
+
|
|
41
|
+
每帧视频由 RGB 区和 Alpha 区组成:RGB 区为彩色画面,Alpha 区为灰度遮罩,其 R 通道被用作输出透明度(白色不透明,黑色透明)。
|
|
42
|
+
|
|
43
|
+
| `orientation` | `side: 'front'` | `side: 'back'` |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| `landscape` | RGB 在左,Alpha 在右 | Alpha 在左,RGB 在右 |
|
|
46
|
+
| `portrait` | RGB 在上,Alpha 在下 | Alpha 在上,RGB 在下 |
|
|
47
|
+
|
|
48
|
+
`alphaScale` 表示 Alpha 遮罩相对 RGB 的宽高缩放:`1` 为等尺寸(默认),`0.5` 为宽高各一半,`0` 表示普通不透明视频。缩小遮罩可由 `alphaAlign` 对齐:横向布局的 `start/end` 分别为上/下;纵向布局分别为左/右。
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
new AlphaVideoPlayer({
|
|
52
|
+
container,
|
|
53
|
+
src,
|
|
54
|
+
orientation: 'landscape',
|
|
55
|
+
side: 'front',
|
|
56
|
+
alphaScale: 0.5,
|
|
57
|
+
alphaAlign: 'start',
|
|
58
|
+
})
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 核心配置
|
|
62
|
+
|
|
63
|
+
| 配置 | 默认值 | 说明 |
|
|
64
|
+
| --- | --- | --- |
|
|
65
|
+
| `container` | — | **必填**,挂载容器。 |
|
|
66
|
+
| `src` | — | 视频地址;可稍后用 `setSrc()` 设置。 |
|
|
67
|
+
| `poster` | 透明封面 | 视频封面。 |
|
|
68
|
+
| `width` / `height` | 容器尺寸 | 逻辑渲染尺寸。 |
|
|
69
|
+
| `crossOrigin` | `'anonymous'` | `'anonymous'` 或 `'use-credentials'`。 |
|
|
70
|
+
| `muted` / `loop` / `playbackRate` | `true` / `false` / `1` | 播放状态与倍速。 |
|
|
71
|
+
| `fps` / `videoFrame` | `0` / `false` | 帧率上限;是否优先用 `requestVideoFrameCallback`。 |
|
|
72
|
+
| `orientation` / `side` | `'landscape'` / `'front'` | 素材拼合方式。 |
|
|
73
|
+
| `alphaScale` / `alphaAlign` | `1` / `'start'` | 遮罩缩放与副轴对齐。 |
|
|
74
|
+
| `autoShow` / `autoClear` / `autoDestroy` | `false` / `true` / `false` | 首帧、结束清理、自动销毁。 |
|
|
75
|
+
| `autoResize` | `'contain'` | `'contain'`、`'width'`、`'height'` 或 `false`。 |
|
|
76
|
+
| `debug` | `false` | 是否输出调试日志。 |
|
|
77
|
+
|
|
78
|
+
回调:`onInitSuccess`、`onInitError`、`onLoad`、`onCanPlay`、`onPlay`、`onLoop`、`onPause`、`onEnded`、`onError`、`onDestroy`。
|
|
79
|
+
|
|
80
|
+
## 实例 API
|
|
81
|
+
|
|
82
|
+
`playing` 与 `loop` 为只读状态;其余公开方法包括:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
player.play(config?)
|
|
86
|
+
player.pause()
|
|
87
|
+
player.reset()
|
|
88
|
+
player.setSrc(src)
|
|
89
|
+
player.setCurrentTime(seconds)
|
|
90
|
+
player.setMute(muted)
|
|
91
|
+
player.setLoop(loop)
|
|
92
|
+
player.setPlaybackRate(rate)
|
|
93
|
+
player.destroy()
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`play()` 失败时会 reject 浏览器的原始错误,并以相同值调用 `onError`。媒体加载、解码或跨域失败也会通过 `onError` 上报,然后销毁实例。`destroy()` 后不要复用该实例。
|
|
97
|
+
|
|
98
|
+
## 框架组件
|
|
99
|
+
|
|
100
|
+
组件入口分别为 `alpha-video-player-js/vue3`、`alpha-video-player-js/vue2` 和 `alpha-video-player-js/react`。组件接收除 `container` 外的全部核心配置,ref 暴露 `play`、`pause`、`destroy`、`reset`、`setSrc`、`setCurrentTime`、`setMute`、`setLoop`、`setPlaybackRate` 与 `getPlayer`。
|
|
101
|
+
|
|
102
|
+
### Vue 3
|
|
103
|
+
|
|
104
|
+
```vue
|
|
105
|
+
<script setup lang="ts">
|
|
106
|
+
import { ref } from 'vue'
|
|
107
|
+
import AlphaVideoPlayer from 'alpha-video-player-js/vue3'
|
|
108
|
+
import type { IAlphaVideoPlayerRef } from 'alpha-video-player-js/vue3'
|
|
109
|
+
|
|
110
|
+
const player = ref<IAlphaVideoPlayerRef | null>(null)
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
<template>
|
|
114
|
+
<AlphaVideoPlayer ref="player" :src="src" :muted="true" @initSuccess="player?.play()" />
|
|
115
|
+
</template>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`playbackRate` 等数字型表单绑定请用 `v-model.number`。手动调用组件 ref 的 `destroy()` 后,应通过 `:key` 或 `v-if` 重新挂载组件。
|
|
119
|
+
|
|
120
|
+
### React
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
import { useRef } from 'react'
|
|
124
|
+
import AlphaVideoPlayer from 'alpha-video-player-js/react'
|
|
125
|
+
import type { IAlphaVideoPlayerRef } from 'alpha-video-player-js/react'
|
|
126
|
+
|
|
127
|
+
export function Effect({ src }: { src: string }) {
|
|
128
|
+
const player = useRef<IAlphaVideoPlayerRef>(null)
|
|
129
|
+
return <AlphaVideoPlayer ref={player} src={src} muted onInitSuccess={() => player.current?.play()} />
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
React 组件额外支持 `className` 与 `style`。`src`、`muted`、`loop`、`playbackRate` 会响应式同步;`orientation`、`side`、`alphaScale`、`alphaAlign` 变更时需要重新挂载。
|
|
134
|
+
|
|
135
|
+
## 类型导入
|
|
136
|
+
|
|
137
|
+
| 导入路径 | 类型 |
|
|
138
|
+
| --- | --- |
|
|
139
|
+
| `alpha-video-player-js` | `IAlphaVideoPlayer`、`IConfig`、`IOptionalConfig`、`IOrientation`、`ISide`、`IAlphaAlign` |
|
|
140
|
+
| `.../vue3`、`.../vue2` | `IAlphaVideoPlayer`、`IAlphaVideoPlayerRef` |
|
|
141
|
+
| `.../react` | `IAlphaVideoPlayerProps`、`IAlphaVideoPlayerRef` |
|
|
142
|
+
|
|
143
|
+
同时使用框架 ref 与核心实例类型时,请从同一个框架子路径导入,避免生成声明文件被拆分解析时的类型不兼容。
|
|
144
|
+
|
|
145
|
+
## 开发
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npm run dev
|
|
149
|
+
npm run build
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## 许可证
|
|
153
|
+
|
|
154
|
+
[ISC](./package.json)
|
|
@@ -3,6 +3,8 @@ interface IConfig {
|
|
|
3
3
|
width?: number;
|
|
4
4
|
height?: number;
|
|
5
5
|
src?: string;
|
|
6
|
+
/** 视频封面;未传时使用内置透明封面规避 Android WebView 默认 poster 的 CORS 问题 */
|
|
7
|
+
poster?: string;
|
|
6
8
|
/** 跨域视频资源;默认 anonymous */
|
|
7
9
|
crossOrigin?: 'anonymous' | 'use-credentials';
|
|
8
10
|
muted?: boolean;
|
|
@@ -11,17 +13,21 @@ interface IConfig {
|
|
|
11
13
|
fps?: number;
|
|
12
14
|
orientation?: IOrientation;
|
|
13
15
|
side?: ISide;
|
|
16
|
+
/** Alpha 遮罩宽高相对 RGB 内容的缩放比例;0 表示普通不透明视频 */
|
|
17
|
+
alphaScale?: number;
|
|
18
|
+
/** Alpha 缩小后在副轴上的对齐方式 */
|
|
19
|
+
alphaAlign?: IAlphaAlign;
|
|
14
20
|
videoFrame?: boolean;
|
|
15
21
|
debug?: boolean;
|
|
16
22
|
autoShow?: boolean;
|
|
17
23
|
autoClear?: boolean;
|
|
18
24
|
autoDestroy?: boolean;
|
|
19
25
|
/**
|
|
20
|
-
*
|
|
21
|
-
* - 'contain'
|
|
26
|
+
* 视频加载后按比例自适应渲染目标尺寸(默认 'contain')。
|
|
27
|
+
* - 'contain':自动判断,确保视频完整填入容器盒子(类似 object-fit: contain)
|
|
22
28
|
* - 'width':固定宽度,按视频比例自动调整高度
|
|
23
29
|
* - 'height':固定高度,按视频比例自动调整宽度
|
|
24
|
-
* - false
|
|
30
|
+
* - false:不自适应,渲染目标保持初始尺寸
|
|
25
31
|
*/
|
|
26
32
|
autoResize?: 'width' | 'height' | 'contain' | false;
|
|
27
33
|
onInitSuccess?: () => void;
|
|
@@ -39,6 +45,7 @@ interface IConfig {
|
|
|
39
45
|
type IOptionalConfig = Omit<IConfig, 'container' | 'src'> & Partial<Pick<IConfig, 'container' | 'src'>>;
|
|
40
46
|
type IOrientation = 'landscape' | 'portrait';
|
|
41
47
|
type ISide = 'front' | 'back';
|
|
48
|
+
type IAlphaAlign = 'start' | 'end';
|
|
42
49
|
|
|
43
50
|
declare class Render {
|
|
44
51
|
private render;
|
|
@@ -55,5 +62,7 @@ declare class Render {
|
|
|
55
62
|
setLoop(loop: boolean): void;
|
|
56
63
|
setPlaybackRate(playbackRate: number): void;
|
|
57
64
|
}
|
|
65
|
+
/** 核心类实例类型(`new Render(...)` 的实例),便于业务侧标注 ref / getPlayer() 等 */
|
|
66
|
+
type IAlphaVideoPlayer = InstanceType<typeof Render>;
|
|
58
67
|
|
|
59
|
-
export { type IConfig, Render as default };
|
|
68
|
+
export { type IAlphaAlign, type IAlphaVideoPlayer, type IConfig, type IOptionalConfig, type IOrientation, type ISide, Render as default };
|