fsd-vod 0.14.0 → 0.15.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/LICENSE +1 -1
- package/README.md +154 -17
- package/index.d.ts +747 -16
- package/lib/index.js +9 -8
- package/package.json +11 -7
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2026 Liang Xingchen https://github.com/liangxingchen
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -1,32 +1,169 @@
|
|
|
1
1
|
# fsd-vod
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
阿里云 VOD(视频点播)适配器,专用于视频上传和管理。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 配置
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
6
8
|
const FSD = require('fsd');
|
|
7
9
|
const VodAdapter = require('fsd-vod');
|
|
8
10
|
|
|
9
|
-
const adapter = new VodAdapter(
|
|
11
|
+
const adapter = new VodAdapter({
|
|
12
|
+
accessKeyId: 'your-key',
|
|
13
|
+
accessKeySecret: 'your-secret',
|
|
14
|
+
region: 'cn-shanghai',
|
|
15
|
+
privateKey: 'your-private-key', // 必需
|
|
16
|
+
urlPrefix: 'https://your-domain.com'
|
|
17
|
+
});
|
|
18
|
+
|
|
10
19
|
const fsd = FSD({ adapter: adapter });
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 配置选项说明
|
|
23
|
+
|
|
24
|
+
| 选项 | 类型 | 必需 | 默认值 | 说明 |
|
|
25
|
+
|------|------|------|--------|------|
|
|
26
|
+
| `accessKeyId` | string | 是 | - | 阿里云访问凭证 |
|
|
27
|
+
| `accessKeySecret` | string | 是 | - | 阿里云访问凭证 |
|
|
28
|
+
| `region` | string | 否 | 'cn-shanghai' | 区域代码 |
|
|
29
|
+
| `privateKey` | string | 是 | - | 视频上传签名私钥(必需) |
|
|
30
|
+
| `templateGroupId` | string | 否 | - | 模板组 ID |
|
|
31
|
+
| `workflowId` | string | 否 | - | 工作流 ID |
|
|
32
|
+
| `urlPrefix` | string | 否 | - | URL 前缀,用于生成访问链接 |
|
|
33
|
+
| `callbackUrl` | string | 否 | - | 回调 URL |
|
|
34
|
+
|
|
35
|
+
### 重要说明
|
|
36
|
+
|
|
37
|
+
#### 1. 视频路径使用规则
|
|
38
|
+
|
|
39
|
+
VOD 适配器**不支持直接指定文件路径**,必须先通过 `adapter.alloc()` 分配视频 ID,然后使用该 ID 作为路径。
|
|
40
|
+
|
|
41
|
+
**为什么需要视频 ID?**
|
|
42
|
+
|
|
43
|
+
阿里云 VOD 不像传统的文件系统那样有目录结构,每个视频上传前需要在 VOD 服务端预先分配一个唯一的视频 ID。这个 ID 会用于后续的上传、转码、播放等操作。
|
|
44
|
+
|
|
45
|
+
**正确的使用方式:**
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
// ✅ 正确:先分配视频 ID
|
|
49
|
+
const videoId = await fsd.adapter.alloc({
|
|
50
|
+
name: 'my-video.mp4',
|
|
51
|
+
metadata: {
|
|
52
|
+
title: 'My Video',
|
|
53
|
+
description: 'Video description'
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// 使用返回的视频 ID 创建文件对象
|
|
58
|
+
const file = fsd(videoId);
|
|
59
|
+
// videoId 格式类似: 'ea5e82e7e8c54d3c8a5d8c5d8c5d8c5d'
|
|
60
|
+
|
|
61
|
+
// 上传视频
|
|
62
|
+
await file.write(videoBuffer);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**错误的使用方式:**
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
// ❌ 错误:不能直接指定路径
|
|
69
|
+
const file = fsd('/videos/my-video.mp4');
|
|
70
|
+
await file.write(videoBuffer); // Error: 无法直接写入
|
|
71
|
+
|
|
72
|
+
// ❌ 错误:路径必须是由 alloc() 返回的视频 ID
|
|
73
|
+
const file = fsd('my-video.mp4');
|
|
74
|
+
await file.write(videoBuffer); // Error: 视频不存在
|
|
75
|
+
```
|
|
11
76
|
|
|
12
|
-
|
|
13
|
-
let file = fsd(videoId);
|
|
77
|
+
**alloc() 方法说明:**
|
|
14
78
|
|
|
15
|
-
|
|
79
|
+
```javascript
|
|
80
|
+
// alloc() 返回视频 ID
|
|
81
|
+
const videoId = await fsd.adapter.alloc(options);
|
|
16
82
|
|
|
83
|
+
// options 参数:
|
|
84
|
+
{
|
|
85
|
+
name: string, // 必需:视频文件名(如 'video.mp4')
|
|
86
|
+
metadata?: { // 可选:视频元数据
|
|
87
|
+
title?: string, // 视频标题
|
|
88
|
+
description?: string, // 视频描述
|
|
89
|
+
tags?: string[], // 视频标签
|
|
90
|
+
category?: string, // 视频分类
|
|
91
|
+
// ... 其他自定义元数据
|
|
92
|
+
}
|
|
93
|
+
}
|
|
17
94
|
```
|
|
18
95
|
|
|
19
|
-
|
|
96
|
+
**文件对象属性:**
|
|
20
97
|
|
|
21
|
-
|
|
98
|
+
```javascript
|
|
99
|
+
const videoId = await fsd.adapter.alloc({ name: 'video.mp4' });
|
|
100
|
+
const file = fsd(videoId);
|
|
22
101
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
102
|
+
console.log(file.path); // 视频 ID: 'ea5e82e7e8c54d3c8a5d8c5d8c5d8c5d'
|
|
103
|
+
console.log(file.dir); // '/'
|
|
104
|
+
console.log(file.base); // 视频 ID
|
|
105
|
+
console.log(file.name); // 视频 ID(无扩展名)
|
|
106
|
+
console.log(file.ext); // ''
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
#### 2. 不支持的目录操作
|
|
112
|
+
|
|
113
|
+
由于阿里云 VOD 是对象存储服务,没有传统的目录概念,因此以下目录操作方法**不支持**:
|
|
114
|
+
|
|
115
|
+
- `mkdir()` - 创建目录
|
|
116
|
+
- `readdir()` - 列出目录
|
|
117
|
+
- `copy()` - 复制文件/目录
|
|
118
|
+
- `rename()` - 重命名/移动文件/目录
|
|
119
|
+
|
|
120
|
+
**不支持的操作及原因:**
|
|
121
|
+
|
|
122
|
+
| 方法 | 不支持原因 |
|
|
123
|
+
|------|-----------|
|
|
124
|
+
| `mkdir()` | VOD 没有目录概念,无需创建目录 |
|
|
125
|
+
| `readdir()` | 无法遍历 VOD 服务中的视频列表,需调用阿里云 VOD API |
|
|
126
|
+
| `copy()` | VOD 不支持在服务端复制视频 |
|
|
127
|
+
| `rename()` | VOD 不支持在服务端重命名视频 |
|
|
128
|
+
|
|
129
|
+
**调用这些方法会发生什么?**
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
// ❌ 创建目录
|
|
133
|
+
const dir = fsd('/videos/');
|
|
134
|
+
await dir.mkdir(); // Error: mkdir not supported
|
|
135
|
+
|
|
136
|
+
// ❌ 列出目录
|
|
137
|
+
const files = await dir.readdir(); // Error: readdir not supported
|
|
138
|
+
|
|
139
|
+
// ❌ 复制视频
|
|
140
|
+
const file = fsd(videoId);
|
|
141
|
+
await file.copy(videoId2); // Error: copy not supported
|
|
142
|
+
|
|
143
|
+
// ❌ 重命名视频
|
|
144
|
+
await file.rename(newVideoId); // Error: rename not supported
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**如何列出 VOD 中的视频?**
|
|
148
|
+
|
|
149
|
+
需要直接调用阿里云 VOD API 来查询视频列表:
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
// 使用阿里云 VOD SDK 查询视频列表
|
|
153
|
+
const vod = require('@alicloud/vod20170321');
|
|
154
|
+
const client = new vod.default({
|
|
155
|
+
accessKeyId: 'your-key',
|
|
156
|
+
accessKeySecret: 'your-secret',
|
|
157
|
+
region: 'cn-shanghai'
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// 查询视频列表
|
|
161
|
+
const result = await client.searchMedia({
|
|
162
|
+
searchType: 'video',
|
|
163
|
+
pageNo: 1,
|
|
164
|
+
pageSize: 50
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
console.log(result.mediaList); // 视频列表
|
|
168
|
+
```
|
|
32
169
|
|
package/index.d.ts
CHANGED
|
@@ -1,138 +1,801 @@
|
|
|
1
1
|
import { Adapter } from 'fsd';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* VODAdapter 配置选项
|
|
5
|
+
*
|
|
6
|
+
* 阿里云 VOD(视频点播)适配器的初始化配置。
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const adapter = new VODAdapter({
|
|
11
|
+
* accessKeyId: 'your-access-key-id',
|
|
12
|
+
* accessKeySecret: 'your-access-key-secret',
|
|
13
|
+
* privateKey: 'your-rsa-private-key'
|
|
14
|
+
* });
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
3
17
|
export interface VODAdapterOptions {
|
|
18
|
+
/**
|
|
19
|
+
* URL 前缀(可选)
|
|
20
|
+
*
|
|
21
|
+
* 用于生成播放链接时添加前缀。
|
|
22
|
+
* 通常配合 CDN 使用。
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* urlPrefix: 'https://cdn.example.com',
|
|
27
|
+
* // createUrl() 返回: https://cdn.example.com/video/HD
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
4
30
|
urlPrefix?: string;
|
|
31
|
+
|
|
5
32
|
/**
|
|
6
|
-
*
|
|
33
|
+
* 是否公共读(可选)
|
|
34
|
+
*
|
|
35
|
+
* 控制生成的播放 URL 是否需要签名访问。
|
|
36
|
+
*
|
|
37
|
+
* - `true`: 公共视频,生成直接访问 URL(无需签名)
|
|
38
|
+
* - `false`: 私有视频,生成带签名的临时 URL(默认值)
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* 如果不公共读,必须提供 `privateKey` 用于生成签名。
|
|
7
42
|
*/
|
|
8
43
|
publicRead?: boolean;
|
|
44
|
+
|
|
9
45
|
/**
|
|
10
|
-
*
|
|
46
|
+
* 私有访问签名密钥(可选)
|
|
47
|
+
*
|
|
48
|
+
* 用于生成私有视频播放 URL 的签名。
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* privateKey: '-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----'
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @remarks
|
|
56
|
+
* RSA 私钥用于生成播放 URL 的签名。
|
|
57
|
+
* 请妥善保管此密钥,不要提交到代码仓库。
|
|
58
|
+
* 建议使用环境变量存储。
|
|
11
59
|
*/
|
|
12
60
|
privateKey?: string;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* OSS 访问 Key ID(必需)
|
|
64
|
+
*
|
|
65
|
+
* 阿里云 OSS 访问凭证(VOD 依赖 OSS 存储视频文件)。
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* accessKeyId: 'LTAI5txxxxxxxxxxxxx'
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
13
72
|
accessKeyId: string;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* OSS 访问 Key Secret(必需)
|
|
76
|
+
*
|
|
77
|
+
* 阿里云 OSS 访问凭证。
|
|
78
|
+
*/
|
|
14
79
|
accessKeySecret: string;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* OSS 区域代码(可选)
|
|
83
|
+
*
|
|
84
|
+
* 阿里云 OSS 区域,如 'oss-cn-hangzhou'。
|
|
85
|
+
* 默认值:'cn-shanghai'
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* region: 'oss-cn-hangzhou', // 华东1(杭州)
|
|
90
|
+
* region: 'oss-cn-shanghai', // 华东2(上海)
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
15
93
|
region?: string;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 转码模板组 ID(可选)
|
|
97
|
+
*
|
|
98
|
+
* 用于视频转码时的模板组。
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* templateGroupId: 'your-template-group-id'
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @remarks
|
|
106
|
+
* 模板组在阿里云 VOD 控制台创建。
|
|
107
|
+
*/
|
|
16
108
|
templateGroupId?: string;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 工作流 ID(可选)
|
|
112
|
+
*
|
|
113
|
+
* 用于视频上传后的自动化处理流程。
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* workflowId: 'your-workflow-id'
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* @remarks
|
|
121
|
+
* 工作流在阿里云 VOD 控制台创建。
|
|
122
|
+
* 可以包括转码、截图、AI 处理等步骤。
|
|
123
|
+
*/
|
|
17
124
|
workflowId?: string;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 上传回调 URL(可选)
|
|
128
|
+
*
|
|
129
|
+
* 视频上传完成后,VOD 会调用此 URL 通知应用。
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* callbackUrl: 'https://api.example.com/vod/callback'
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* @remarks
|
|
137
|
+
* 回调 body 包含视频 ID、状态等信息。
|
|
138
|
+
*/
|
|
18
139
|
callbackUrl?: string;
|
|
19
140
|
}
|
|
20
141
|
|
|
142
|
+
/**
|
|
143
|
+
* 视频信息
|
|
144
|
+
*
|
|
145
|
+
* 视频的基本信息和状态。
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* {
|
|
150
|
+
* VideoId: '1234567890abcdef',
|
|
151
|
+
* Title: 'My Video',
|
|
152
|
+
* Status: 'Normal',
|
|
153
|
+
* Size: 1048576,
|
|
154
|
+
* Duration: '10.5'
|
|
155
|
+
* }
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
21
158
|
export interface VideoInfo {
|
|
159
|
+
/**
|
|
160
|
+
* 审核状态
|
|
161
|
+
*/
|
|
22
162
|
AuditStatus: string;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* 下载开关
|
|
166
|
+
*/
|
|
23
167
|
DownloadSwitch: string;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* 预处理状态
|
|
171
|
+
*/
|
|
24
172
|
PreprocessStatus: string;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 修改时间
|
|
176
|
+
*/
|
|
25
177
|
ModificationTime: string;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* 视频 ID
|
|
181
|
+
*/
|
|
26
182
|
VideoId: string;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 应用 ID
|
|
186
|
+
*/
|
|
27
187
|
AppId: string;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* 修改时间
|
|
191
|
+
*/
|
|
28
192
|
ModifyTime: string;
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* 视频标题
|
|
196
|
+
*/
|
|
29
197
|
Title: string;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 创建时间
|
|
201
|
+
*/
|
|
30
202
|
CreationTime: string;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* 状态
|
|
206
|
+
*/
|
|
31
207
|
Status: string;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* 转码模板组 ID
|
|
211
|
+
*/
|
|
32
212
|
TemplateGroupId: string;
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* 区域 ID
|
|
216
|
+
*/
|
|
33
217
|
RegionId: string;
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* 视频时长(秒)
|
|
221
|
+
*/
|
|
34
222
|
Duration: number;
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* 创建时间
|
|
226
|
+
*/
|
|
35
227
|
CreateTime: string;
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* 快照列表
|
|
231
|
+
*/
|
|
36
232
|
Snapshots: { Snapshot: string[] };
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* 存储位置
|
|
236
|
+
*/
|
|
37
237
|
StorageLocation: string;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* 视频大小(字节)
|
|
241
|
+
*/
|
|
38
242
|
Size: number;
|
|
39
243
|
}
|
|
40
244
|
|
|
245
|
+
/**
|
|
246
|
+
* 媒体信息
|
|
247
|
+
*
|
|
248
|
+
* 视频转码后的媒体信息(不同清晰度)。
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```typescript
|
|
252
|
+
* {
|
|
253
|
+
* VideoId: '1234567890abcdef',
|
|
254
|
+
* OutputType: 'MP4',
|
|
255
|
+
* PreprocessStatus: 'PreprocessingSuccess',
|
|
256
|
+
* FileURL: 'https://vod.oss-cn-hangzhou.aliyuncs.com/.../video.mp4',
|
|
257
|
+
* Duration: '10.5',
|
|
258
|
+
* Width: 1920,
|
|
259
|
+
* Height: 1080,
|
|
260
|
+
* Size: 1048576,
|
|
261
|
+
* CreationTime: '2024-01-01T00:00:00Z'
|
|
262
|
+
* }
|
|
263
|
+
* ```
|
|
264
|
+
*/
|
|
41
265
|
export interface MezzanineInfo {
|
|
266
|
+
/**
|
|
267
|
+
* 预处理状态
|
|
268
|
+
*/
|
|
42
269
|
PreprocessStatus: string;
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* 视频 ID
|
|
273
|
+
*/
|
|
43
274
|
VideoId: string;
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* 输出类型
|
|
278
|
+
*/
|
|
44
279
|
OutputType: string;
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* CRC64 校验码
|
|
283
|
+
*/
|
|
45
284
|
CRC64: string;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* 创建时间
|
|
288
|
+
*/
|
|
46
289
|
CreationTime: string;
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* 状态
|
|
293
|
+
*/
|
|
47
294
|
Status: string;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* 文件名
|
|
298
|
+
*/
|
|
48
299
|
FileName: string;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* 时长(秒)
|
|
303
|
+
*/
|
|
49
304
|
Duration: string;
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* 视频高度
|
|
308
|
+
*/
|
|
50
309
|
Height: number;
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* 视频宽度
|
|
313
|
+
*/
|
|
51
314
|
Width: number;
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* 帧率
|
|
318
|
+
*/
|
|
52
319
|
Fps: string;
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* 比特率
|
|
323
|
+
*/
|
|
53
324
|
Bitrate: string;
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* 文件 URL
|
|
328
|
+
*/
|
|
54
329
|
FileURL: string;
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* 文件大小(字节)
|
|
333
|
+
*/
|
|
55
334
|
Size: number;
|
|
56
335
|
}
|
|
57
336
|
|
|
337
|
+
/**
|
|
338
|
+
* 视频基础信息
|
|
339
|
+
*
|
|
340
|
+
* 视频的元数据信息。
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* ```typescript
|
|
344
|
+
* {
|
|
345
|
+
* VideoId: '1234567890abcdef',
|
|
346
|
+
* MediaType: 'video',
|
|
347
|
+
* Status: 'Normal',
|
|
348
|
+
* Title: 'My Video',
|
|
349
|
+
* Duration: '10.5'
|
|
350
|
+
* }
|
|
351
|
+
* ```
|
|
352
|
+
*/
|
|
58
353
|
export interface VideoBase {
|
|
354
|
+
/**
|
|
355
|
+
* 转码模式
|
|
356
|
+
*/
|
|
59
357
|
TranscodeMode: string;
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* 创建时间
|
|
361
|
+
*/
|
|
60
362
|
CreationTime: string;
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* 封面图 URL
|
|
366
|
+
*/
|
|
61
367
|
CoverURL: string;
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* 状态
|
|
371
|
+
*/
|
|
62
372
|
Status: string;
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* 媒体类型
|
|
376
|
+
*/
|
|
63
377
|
MediaType: string;
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* 视频 ID
|
|
381
|
+
*/
|
|
64
382
|
VideoId: string;
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* 时长(秒)
|
|
386
|
+
*/
|
|
65
387
|
Duration: string;
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* 输出类型
|
|
391
|
+
*/
|
|
66
392
|
OutputType: string;
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* 标题
|
|
396
|
+
*/
|
|
67
397
|
Title: string;
|
|
68
398
|
}
|
|
69
399
|
|
|
400
|
+
/**
|
|
401
|
+
* 播放信息
|
|
402
|
+
*
|
|
403
|
+
* 视频的播放配置信息。
|
|
404
|
+
*
|
|
405
|
+
* @example
|
|
406
|
+
* ```typescript
|
|
407
|
+
* {
|
|
408
|
+
* RequestId: 'request-id',
|
|
409
|
+
* VideoBase: {
|
|
410
|
+
* PlayURL: 'https://vod.oss-cn-hangzhou.aliyuncs.com/.../video.m3u8',
|
|
411
|
+
* Height: 1080,
|
|
412
|
+
* Width: 1920,
|
|
413
|
+
* Duration: '10.5',
|
|
414
|
+
* Definition: 'HD'
|
|
415
|
+
* }
|
|
416
|
+
* }
|
|
417
|
+
* ```
|
|
418
|
+
*/
|
|
70
419
|
export interface PlayInfo {
|
|
420
|
+
/**
|
|
421
|
+
* 格式(如 'mp4', 'm3u8')
|
|
422
|
+
*/
|
|
71
423
|
Format: string;
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* 流类型(如 'HLS', 'DASH')
|
|
427
|
+
*/
|
|
72
428
|
StreamType: string;
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* 预处理状态
|
|
432
|
+
*/
|
|
73
433
|
PreprocessStatus: string;
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* 修改时间
|
|
437
|
+
*/
|
|
74
438
|
ModificationTime: string;
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* 规格
|
|
442
|
+
*/
|
|
75
443
|
Specification: string;
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* 视频高度
|
|
447
|
+
*/
|
|
76
448
|
Height: number;
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* 播放 URL
|
|
452
|
+
*/
|
|
77
453
|
PlayURL: string;
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* 码率类型
|
|
457
|
+
*/
|
|
78
458
|
NarrowBandType: string;
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* 创建时间
|
|
462
|
+
*/
|
|
79
463
|
CreationTime: string;
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* 状态
|
|
467
|
+
*/
|
|
80
468
|
Status: string;
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* 时长(秒)
|
|
472
|
+
*/
|
|
81
473
|
Duration: string;
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* 任务 ID
|
|
477
|
+
*/
|
|
82
478
|
JobId: string;
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* 加密标志
|
|
482
|
+
*/
|
|
83
483
|
Encrypt: number;
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* 视频宽度
|
|
487
|
+
*/
|
|
84
488
|
Width: number;
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* 帧率
|
|
492
|
+
*/
|
|
85
493
|
Fps: string;
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* 比特率
|
|
497
|
+
*/
|
|
86
498
|
Bitrate: string;
|
|
87
|
-
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* 清晰度(如 'HD', 'SD', '4K')
|
|
502
|
+
*/
|
|
88
503
|
Definition: string;
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* 文件大小(字节)
|
|
507
|
+
*/
|
|
508
|
+
Size: number;
|
|
89
509
|
}
|
|
90
510
|
|
|
511
|
+
/**
|
|
512
|
+
* 播放信息结果
|
|
513
|
+
*
|
|
514
|
+
* 包含视频基础信息和播放信息列表。
|
|
515
|
+
*
|
|
516
|
+
* @example
|
|
517
|
+
* ```typescript
|
|
518
|
+
* {
|
|
519
|
+
* RequestId: 'request-id',
|
|
520
|
+
* VideoBase: {
|
|
521
|
+
* // ... 基础信息
|
|
522
|
+
* },
|
|
523
|
+
* PlayInfoList: {
|
|
524
|
+
* PlayInfo: [
|
|
525
|
+
* {
|
|
526
|
+
* Format: 'mp4',
|
|
527
|
+
* PlayURL: 'https://...',
|
|
528
|
+
* Definition: 'HD'
|
|
529
|
+
* },
|
|
530
|
+
* {
|
|
531
|
+
* Format: 'm3u8',
|
|
532
|
+
* PlayURL: 'https://...',
|
|
533
|
+
* Definition: 'SD'
|
|
534
|
+
* }
|
|
535
|
+
* ]
|
|
536
|
+
* }
|
|
537
|
+
* }
|
|
538
|
+
* ```
|
|
539
|
+
*/
|
|
91
540
|
export interface PlayInfoResult {
|
|
541
|
+
/**
|
|
542
|
+
* 请求 ID
|
|
543
|
+
*/
|
|
92
544
|
RequestId: string;
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* 视频基础信息
|
|
548
|
+
*/
|
|
93
549
|
VideoBase: VideoBase;
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* 播放信息列表
|
|
553
|
+
*/
|
|
94
554
|
PlayInfoList: {
|
|
555
|
+
/**
|
|
556
|
+
* 播放信息数组
|
|
557
|
+
*
|
|
558
|
+
* 可能包含多种格式(MP4、M3U8)或多种清晰度(HD、SD)的播放地址。
|
|
559
|
+
*/
|
|
95
560
|
PlayInfo: PlayInfo[];
|
|
96
561
|
};
|
|
97
562
|
}
|
|
98
563
|
|
|
564
|
+
/**
|
|
565
|
+
* 上传凭证
|
|
566
|
+
*
|
|
567
|
+
* 包含临时 OSS 访问凭证的返回值。
|
|
568
|
+
*
|
|
569
|
+
* @example
|
|
570
|
+
* ```typescript
|
|
571
|
+
* {
|
|
572
|
+
* auth: {
|
|
573
|
+
* accessKeyId: 'STS.xxxxxxxxxxxxxx',
|
|
574
|
+
* accessKeySecret: 'xxxxxxxxxxxxxxxxxxxxxxxx',
|
|
575
|
+
* stsToken: 'CAESxxxx...',
|
|
576
|
+
* bucket: 'my-bucket',
|
|
577
|
+
* endpoint: 'oss-cn-hangzhou.aliyuncs.com'
|
|
578
|
+
* },
|
|
579
|
+
* path: '/videos/video.mp4',
|
|
580
|
+
* expiration: 17001234567890
|
|
581
|
+
* }
|
|
582
|
+
* ```
|
|
583
|
+
*/
|
|
99
584
|
export interface UploadToken {
|
|
585
|
+
/**
|
|
586
|
+
* 认证信息
|
|
587
|
+
*
|
|
588
|
+
* 包含临时 OSS 访问凭证。
|
|
589
|
+
*/
|
|
100
590
|
auth: {
|
|
591
|
+
/**
|
|
592
|
+
* 临时 Access Key ID
|
|
593
|
+
*/
|
|
101
594
|
accessKeyId: string;
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* 临时 Access Key Secret
|
|
598
|
+
*/
|
|
102
599
|
accessKeySecret: string;
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* STS 临时 Token
|
|
603
|
+
*/
|
|
103
604
|
stsToken: string;
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Bucket 名称
|
|
608
|
+
*/
|
|
104
609
|
bucket: string;
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* OSS 访问地址
|
|
613
|
+
*/
|
|
105
614
|
endpoint: string;
|
|
106
615
|
};
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* 上传目标路径
|
|
619
|
+
*/
|
|
107
620
|
path: string;
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* 凭证过期时间(Unix 时间戳,秒)
|
|
624
|
+
*/
|
|
108
625
|
expiration: number;
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* 回调数据(可选)
|
|
629
|
+
*/
|
|
109
630
|
callback?: any;
|
|
110
631
|
}
|
|
111
632
|
|
|
633
|
+
/**
|
|
634
|
+
* 带自动刷新的上传凭证
|
|
635
|
+
*
|
|
636
|
+
* 包含自动刷新 STS Token 的上传凭证。
|
|
637
|
+
*
|
|
638
|
+
* @example
|
|
639
|
+
* ```typescript
|
|
640
|
+
* {
|
|
641
|
+
* auth: {
|
|
642
|
+
* // ... 认证信息
|
|
643
|
+
* refreshSTSToken: [Function: refresh]
|
|
644
|
+
* },
|
|
645
|
+
* path: '/videos/video.mp4',
|
|
646
|
+
* expiration: 17001234567890
|
|
647
|
+
* }
|
|
648
|
+
* ```
|
|
649
|
+
*
|
|
650
|
+
* @remarks
|
|
651
|
+
* 当凭证即将过期时,调用 `refreshSTSToken()` 获取新的临时凭证。
|
|
652
|
+
* 适用于大文件上传,避免上传过程中凭证过期。
|
|
653
|
+
*/
|
|
112
654
|
export interface UploadTokenWithAutoRefresh {
|
|
655
|
+
/**
|
|
656
|
+
* 认证信息
|
|
657
|
+
*/
|
|
113
658
|
auth: {
|
|
659
|
+
/**
|
|
660
|
+
* 临时 Access Key ID
|
|
661
|
+
*/
|
|
114
662
|
accessKeyId: string;
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* 临时 Access Key Secret
|
|
666
|
+
*/
|
|
115
667
|
accessKeySecret: string;
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* STS 临时 Token
|
|
671
|
+
*/
|
|
116
672
|
stsToken: string;
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Bucket 名称
|
|
676
|
+
*/
|
|
117
677
|
bucket: string;
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* OSS 访问地址
|
|
681
|
+
*/
|
|
118
682
|
endpoint: string;
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* 自动刷新 STS Token 的函数
|
|
686
|
+
*
|
|
687
|
+
* 调用此函数获取新的临时凭证。
|
|
688
|
+
*
|
|
689
|
+
* @example
|
|
690
|
+
* ```typescript
|
|
691
|
+
* const newAuth = await auth.refreshSTSToken();
|
|
692
|
+
* console.log(newAuth.stsToken);
|
|
693
|
+
* ```
|
|
694
|
+
*/
|
|
119
695
|
refreshSTSToken: () => Promise<{
|
|
120
696
|
accessKeyId: string;
|
|
121
697
|
accessKeySecret: string;
|
|
122
698
|
stsToken: string;
|
|
123
699
|
}>;
|
|
124
700
|
};
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* 上传目标路径
|
|
704
|
+
*/
|
|
125
705
|
path: string;
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* 凭证过期时间
|
|
709
|
+
*/
|
|
126
710
|
expiration: number;
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* 回调数据(可选)
|
|
714
|
+
*/
|
|
127
715
|
callback?: any;
|
|
128
716
|
}
|
|
129
717
|
|
|
130
|
-
|
|
718
|
+
/**
|
|
719
|
+
* 阿里云 VOD 适配器
|
|
720
|
+
*
|
|
721
|
+
* 提供对阿里云 VOD(视频点播)的访问能力。
|
|
722
|
+
*
|
|
723
|
+
* @remarks
|
|
724
|
+
* ### 核心特性
|
|
725
|
+
* - 视频上传
|
|
726
|
+
* - 视频信息查询
|
|
727
|
+
* - 播放 URL 生成(支持多清晰度)
|
|
728
|
+
* - STS 临时凭证(边缘上传)
|
|
729
|
+
* - Token 自动刷新
|
|
730
|
+
* - 转码模板和工作流支持
|
|
731
|
+
*
|
|
732
|
+
* ### 与 OSS 的关系
|
|
733
|
+
* - VOD 适配器内部依赖 `fsd-oss` 的 `SimpleOSSClient` 进行文件上传
|
|
734
|
+
* - 视频文件实际存储在 OSS 中
|
|
735
|
+
* - VOD 提供转码、截图等视频处理服务
|
|
736
|
+
*
|
|
737
|
+
* ### 不支持的操作
|
|
738
|
+
* - `mkdir()` - VOD 无目录概念
|
|
739
|
+
* - `readdir()` - VOD 无目录列表
|
|
740
|
+
* - `copy()` - VOD 不支持直接复制
|
|
741
|
+
* - `rename()` - VOD 不支持重命名
|
|
742
|
+
*
|
|
743
|
+
* ### alloc() 机制
|
|
744
|
+
* - 上传前必须先调用 `adapter.alloc({ name: 'video.mp4' })`
|
|
745
|
+
* - 返回视频 ID 作为文件路径
|
|
746
|
+
* - 视频 ID 格式:`/{VideoId}`
|
|
747
|
+
* - 不能直接使用 `fsd('/path')`
|
|
748
|
+
*
|
|
749
|
+
* @example
|
|
750
|
+
* ```typescript
|
|
751
|
+
* import VODAdapter from 'fsd-vod';
|
|
752
|
+
* import FSD from 'fsd';
|
|
753
|
+
*
|
|
754
|
+
* const adapter = new VODAdapter({
|
|
755
|
+
* accessKeyId: process.env.VOD_ACCESS_KEY_ID,
|
|
756
|
+
* accessKeySecret: process.env.VOD_ACCESS_KEY_SECRET,
|
|
757
|
+
* privateKey: process.env.VOD_PRIVATE_KEY
|
|
758
|
+
* });
|
|
759
|
+
*
|
|
760
|
+
* const fsd = FSD({ adapter });
|
|
761
|
+
*
|
|
762
|
+
* // ✅ 正确:先分配视频 ID
|
|
763
|
+
* const videoId = await adapter.alloc({ name: 'video.mp4' });
|
|
764
|
+
* const file = fsd(videoId);
|
|
765
|
+
* await file.write(videoData);
|
|
766
|
+
*
|
|
767
|
+
* // ❌ 错误:直接使用路径
|
|
768
|
+
* const file = fsd('/uploads/video.mp4'); // 会创建新视频而非上传到指定 ID
|
|
769
|
+
* await file.write(videoData);
|
|
770
|
+
* ```
|
|
771
|
+
*/
|
|
772
|
+
export default class VODAdapter extends Adapter<VODAdapterOptions> {
|
|
131
773
|
/**
|
|
132
774
|
* 创建上传凭证
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
775
|
+
*
|
|
776
|
+
* 生成用于客户端直接上传到 VOD 的临时凭证。
|
|
777
|
+
*
|
|
778
|
+
* @param videoId - 视频 ID(由 `alloc()` 返回)
|
|
779
|
+
* @param meta - 文件元数据(可选)
|
|
780
|
+
* @param durationSeconds - 凭证有效期(秒),默认 3600(1 小时)
|
|
781
|
+
* @returns 上传凭证对象
|
|
782
|
+
*
|
|
783
|
+
* @example
|
|
784
|
+
* ```typescript
|
|
785
|
+
* // 生成 1 小时有效的上传凭证
|
|
786
|
+
* const token = await adapter.createUploadToken(
|
|
787
|
+
* '/1234567890abcdef',
|
|
788
|
+
* { contentType: 'video/mp4' },
|
|
789
|
+
* 3600
|
|
790
|
+
* );
|
|
791
|
+
*
|
|
792
|
+
* // 将 token 发送给前端
|
|
793
|
+
* res.json({ uploadToken: token });
|
|
794
|
+
* ```
|
|
795
|
+
*
|
|
796
|
+
* @remarks
|
|
797
|
+
* 生成的凭证用于客户端直接上传到 OSS。
|
|
798
|
+
* 上传完成后,VOD 会处理转码等操作。
|
|
136
799
|
*/
|
|
137
800
|
createUploadToken: (
|
|
138
801
|
videoId: string,
|
|
@@ -142,9 +805,30 @@ export default class VODAdpter extends Adapter<VODAdapterOptions> {
|
|
|
142
805
|
|
|
143
806
|
/**
|
|
144
807
|
* 创建带自动刷新的上传凭证
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
808
|
+
*
|
|
809
|
+
* 生成支持自动刷新 STS Token 的上传凭证。
|
|
810
|
+
*
|
|
811
|
+
* @param videoId - 视频 ID(由 `alloc()` 返回)
|
|
812
|
+
* @param meta - 文件元数据(可选)
|
|
813
|
+
* @param durationSeconds - 凭证有效期(秒),默认 3600(1 小时)
|
|
814
|
+
* @returns 带自动刷新功能的上传凭证对象
|
|
815
|
+
*
|
|
816
|
+
* @example
|
|
817
|
+
* ```typescript
|
|
818
|
+
* const token = await adapter.createUploadTokenWithAutoRefresh(
|
|
819
|
+
* '/1234567890abcdef',
|
|
820
|
+
* { contentType: 'video/mp4' },
|
|
821
|
+
* 3600
|
|
822
|
+
* );
|
|
823
|
+
*
|
|
824
|
+
* // 当凭证快过期时,自动刷新
|
|
825
|
+
* const newAuth = await token.auth.refreshSTSToken();
|
|
826
|
+
* console.log(newAuth.stsToken);
|
|
827
|
+
* ```
|
|
828
|
+
*
|
|
829
|
+
* @remarks
|
|
830
|
+
* 适用于大文件上传,避免上传过程中凭证过期。
|
|
831
|
+
* 使用 LRUCache 缓存 Token,减少刷新次数。
|
|
148
832
|
*/
|
|
149
833
|
createUploadTokenWithAutoRefresh: (
|
|
150
834
|
videoId: string,
|
|
@@ -154,21 +838,68 @@ export default class VODAdpter extends Adapter<VODAdapterOptions> {
|
|
|
154
838
|
|
|
155
839
|
/**
|
|
156
840
|
* 获取视频信息
|
|
157
|
-
*
|
|
841
|
+
*
|
|
842
|
+
* 查询视频的基本信息(标题、状态、时长等)。
|
|
843
|
+
*
|
|
844
|
+
* @param videoId - 视频 ID
|
|
845
|
+
* @returns 视频信息,如果视频不存在则返回 null
|
|
846
|
+
*
|
|
847
|
+
* @example
|
|
848
|
+
* ```typescript
|
|
849
|
+
const info = await adapter.getVideoInfo('1234567890abcdef');
|
|
850
|
+
if (info) {
|
|
851
|
+
* console.log('Title:', info.Title);
|
|
852
|
+
* console.log('Status:', info.Status);
|
|
853
|
+
* console.log('Duration:', info.Duration);
|
|
854
|
+
* }
|
|
855
|
+
* ```
|
|
158
856
|
*/
|
|
159
857
|
getVideoInfo(videoId: string): Promise<null | VideoInfo>;
|
|
160
858
|
|
|
161
859
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
860
|
+
* 获取视频媒体信息
|
|
861
|
+
*
|
|
862
|
+
* 查询视频转码后的媒体信息(不同清晰度)。
|
|
863
|
+
*
|
|
864
|
+
* @param videoId - 视频 ID
|
|
865
|
+
* @param options - 可选参数
|
|
866
|
+
* @returns 媒体信息,如果不存在则返回 null
|
|
867
|
+
*
|
|
868
|
+
* @example
|
|
869
|
+
* ```typescript
|
|
870
|
+
const mezzanineInfo = await adapter.getMezzanineInfo('1234567890abcdef');
|
|
871
|
+
if (mezzanineInfo) {
|
|
872
|
+
* console.log('FileURL:', mezzanineInfo.FileURL);
|
|
873
|
+
* console.log('Duration:', mezzanineInfo.Duration);
|
|
874
|
+
* console.log('Size:', mezzanineInfo.Size);
|
|
875
|
+
* }
|
|
876
|
+
* ```
|
|
165
877
|
*/
|
|
166
878
|
getMezzanineInfo(videoId: string, options?: any): Promise<null | MezzanineInfo>;
|
|
167
879
|
|
|
168
880
|
/**
|
|
169
881
|
* 获取视频播放信息
|
|
170
|
-
*
|
|
171
|
-
*
|
|
882
|
+
*
|
|
883
|
+
* 查询视频的播放配置信息(不同格式和清晰度的播放地址)。
|
|
884
|
+
*
|
|
885
|
+
* @param videoId - 视频 ID
|
|
886
|
+
* @param options - 可选参数
|
|
887
|
+
* @returns 播放信息结果
|
|
888
|
+
*
|
|
889
|
+
* @example
|
|
890
|
+
* ```typescript
|
|
891
|
+
* const playInfo = await adapter.getPlayInfo('1234567890abcdef');
|
|
892
|
+
console.log('PlayInfoList:', playInfo.PlayInfoList);
|
|
893
|
+
*
|
|
894
|
+
// PlayInfoList 包含多种格式和清晰度
|
|
895
|
+
// - Format: mp4, m3u8
|
|
896
|
+
// - Definition: HD, SD, FHD, 4K
|
|
897
|
+
* - PlayURL: 每种配置的播放地址
|
|
898
|
+
* ```
|
|
899
|
+
*
|
|
900
|
+
* @remarks
|
|
901
|
+
* 返回的信息可能包含多个清晰度(HD、SD、FHD、4K)的播放地址。
|
|
902
|
+
* 可以根据用户网络和设备选择合适的清晰度。
|
|
172
903
|
*/
|
|
173
904
|
getPlayInfo(videoId: string, options?: any): Promise<null | PlayInfoResult>;
|
|
174
905
|
}
|
package/lib/index.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const crypto_1 = tslib_1.__importDefault(require("crypto"));
|
|
4
5
|
const stream_1 = require("stream");
|
|
5
6
|
const lru_cache_1 = require("lru-cache");
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const akita_1 = require("akita");
|
|
9
|
-
const simple_oss_client_1 = require("fsd-oss/simple-oss-client");
|
|
10
|
-
const debug =
|
|
7
|
+
const debug_1 = tslib_1.__importDefault(require("debug"));
|
|
8
|
+
const pop_core_1 = tslib_1.__importDefault(require("@alicloud/pop-core"));
|
|
9
|
+
const akita_1 = tslib_1.__importDefault(require("akita"));
|
|
10
|
+
const simple_oss_client_1 = tslib_1.__importDefault(require("fsd-oss/simple-oss-client"));
|
|
11
|
+
const debug = (0, debug_1.default)('fsd-vod');
|
|
11
12
|
const client = akita_1.default.resolve('fsd-vod');
|
|
12
13
|
const CALLBACK_BODY = 'bucket=${bucket}&path=${object}&etag=${etag}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}&format=${imageInfo.format}';
|
|
13
14
|
function parseToken(result) {
|
|
@@ -35,7 +36,7 @@ function parseVideoId(id) {
|
|
|
35
36
|
return { id, path };
|
|
36
37
|
}
|
|
37
38
|
function md5(str) {
|
|
38
|
-
return
|
|
39
|
+
return crypto_1.default.createHash('md5').update(str).digest('hex');
|
|
39
40
|
}
|
|
40
41
|
class VODAdapter {
|
|
41
42
|
constructor(options) {
|
|
@@ -57,7 +58,7 @@ class VODAdapter {
|
|
|
57
58
|
max: 1000,
|
|
58
59
|
ttl: 60000
|
|
59
60
|
});
|
|
60
|
-
this._rpc = new
|
|
61
|
+
this._rpc = new pop_core_1.default({
|
|
61
62
|
accessKeyId: options.accessKeyId,
|
|
62
63
|
accessKeySecret: options.accessKeySecret,
|
|
63
64
|
endpoint: `https://vod.${options.region || 'cn-shanghai'}.aliyuncs.com`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fsd-vod",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Aliyun OSS adapter for fsd",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -9,14 +9,18 @@
|
|
|
9
9
|
"prepublish": "npm run build"
|
|
10
10
|
},
|
|
11
11
|
"repository": "https://github.com/liangxingchen/fsd/tree/master/packages/fsd-vod",
|
|
12
|
-
"author":
|
|
12
|
+
"author": {
|
|
13
|
+
"name": "Liang",
|
|
14
|
+
"email": "liang@miaomo.cn",
|
|
15
|
+
"url": "https://github.com/liangxingchen"
|
|
16
|
+
},
|
|
13
17
|
"license": "MIT",
|
|
14
18
|
"dependencies": {
|
|
15
19
|
"@alicloud/pop-core": "^1.8.0",
|
|
16
|
-
"akita": "^1.
|
|
17
|
-
"debug": "^4.4.
|
|
18
|
-
"fsd-oss": "^0.
|
|
19
|
-
"lru-cache": "^11.
|
|
20
|
+
"akita": "^1.2.0",
|
|
21
|
+
"debug": "^4.4.3",
|
|
22
|
+
"fsd-oss": "^0.15.0",
|
|
23
|
+
"lru-cache": "^11.2.4"
|
|
20
24
|
},
|
|
21
|
-
"gitHead": "
|
|
25
|
+
"gitHead": "ea754919fb95b49deffd529b5c01c66da0dc08f9"
|
|
22
26
|
}
|