fsd-vod 0.11.1 → 0.13.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.
Files changed (3) hide show
  1. package/index.d.ts +44 -2
  2. package/lib/index.js +64 -31
  3. package/package.json +5 -5
package/index.d.ts CHANGED
@@ -2,6 +2,14 @@ import { Adapter } from 'fsd';
2
2
 
3
3
  export interface VODAdapterOptions {
4
4
  urlPrefix?: string;
5
+ /**
6
+ * 是否公开读,默认为false
7
+ */
8
+ publicRead?: boolean;
9
+ /**
10
+ * 非公开读时,生成URL时的鉴权秘钥
11
+ */
12
+ privateKey?: string;
5
13
  accessKeyId: string;
6
14
  accessKeySecret: string;
7
15
  region?: string;
@@ -120,13 +128,47 @@ export interface UploadTokenWithAutoRefresh {
120
128
  }
121
129
 
122
130
  export default class VODAdpter extends Adapter<VODAdapterOptions> {
123
- createUploadToken: (videoId: string, meta?: any) => Promise<UploadToken>;
131
+ /**
132
+ * 创建上传凭证
133
+ * @param {string} videoId 视频ID
134
+ * @param {any} [meta] 文件元信息
135
+ * @param {number} [durationSeconds] 上传凭证有效期,单位秒, 默认 3600
136
+ */
137
+ createUploadToken: (
138
+ videoId: string,
139
+ meta?: any,
140
+ durationSeconds?: number
141
+ ) => Promise<UploadToken>;
142
+
143
+ /**
144
+ * 创建带自动刷新的上传凭证
145
+ * @param {string} videoId 视频ID
146
+ * @param {any} [meta] 文件元信息
147
+ * @param {number} [durationSeconds] 上传凭证有效期,单位秒, 默认 3600
148
+ */
124
149
  createUploadTokenWithAutoRefresh: (
125
150
  videoId: string,
126
- meta?: any
151
+ meta?: any,
152
+ durationSeconds?: number
127
153
  ) => Promise<UploadTokenWithAutoRefresh>;
128
154
 
155
+ /**
156
+ * 获取视频信息
157
+ * @param {string} videoId 视频ID
158
+ */
129
159
  getVideoInfo(videoId: string): Promise<null | VideoInfo>;
160
+
161
+ /**
162
+ * 获取视频播放信息
163
+ * @param {string} videoId 视频ID
164
+ * @param {any} [options] 参数选项
165
+ */
130
166
  getMezzanineInfo(videoId: string, options?: any): Promise<null | MezzanineInfo>;
167
+
168
+ /**
169
+ * 获取视频播放信息
170
+ * @param {string} videoId 视频ID
171
+ * @param {any} [options] 参数选项
172
+ */
131
173
  getPlayInfo(videoId: string, options?: any): Promise<null | PlayInfoResult>;
132
174
  }
package/lib/index.js CHANGED
@@ -1,15 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const LRUCache = require("lru-cache");
3
+ const crypto = require("crypto");
4
+ const stream_1 = require("stream");
5
+ const lru_cache_1 = require("lru-cache");
4
6
  const Debugger = require("debug");
5
7
  const RPC = require("@alicloud/pop-core");
6
- const stream_1 = require("stream");
7
8
  const akita_1 = require("akita");
8
9
  const simple_oss_client_1 = require("fsd-oss/simple-oss-client");
9
10
  const debug = Debugger('fsd-vod');
10
11
  const client = akita_1.default.resolve('fsd-vod');
11
12
  const CALLBACK_BODY = 'bucket=${bucket}&path=${object}&etag=${etag}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}&format=${imageInfo.format}';
12
- function resultToCache(result) {
13
+ function parseToken(result) {
13
14
  let UploadAddress = JSON.parse(Buffer.from(result.UploadAddress, 'base64').toString());
14
15
  let UploadAuth = JSON.parse(Buffer.from(result.UploadAuth, 'base64').toString());
15
16
  return {
@@ -24,6 +25,18 @@ function resultToCache(result) {
24
25
  expiration: UploadAuth.Expiration * 950
25
26
  };
26
27
  }
28
+ function parseVideoId(id) {
29
+ if (id[0] === '/')
30
+ id = id.substring(1);
31
+ let path = '';
32
+ if (id.includes('#')) {
33
+ [id, path] = id.split('#');
34
+ }
35
+ return { id, path };
36
+ }
37
+ function md5(str) {
38
+ return crypto.createHash('md5').update(str).digest('hex');
39
+ }
27
40
  class VODAdapter {
28
41
  constructor(options) {
29
42
  this.instanceOfFSDAdapter = true;
@@ -33,14 +46,16 @@ class VODAdapter {
33
46
  throw new Error('option accessKeyId is required for fsd-vod');
34
47
  if (!options.accessKeySecret)
35
48
  throw new Error('option accessKeySecret is required for fsd-vod');
49
+ if (!options.publicRead && !options.privateKey)
50
+ throw new Error('option privateKey is required when publicRead is false');
36
51
  this._options = options;
37
- this._authCache = new LRUCache({
52
+ this._authCache = new lru_cache_1.LRUCache({
38
53
  max: 1000,
39
- maxAge: 1800000
54
+ ttl: 1800000
40
55
  });
41
- this._videoCache = new LRUCache({
56
+ this._videoCache = new lru_cache_1.LRUCache({
42
57
  max: 1000,
43
- maxAge: 60000
58
+ ttl: 60000
44
59
  });
45
60
  this._rpc = new RPC({
46
61
  accessKeyId: options.accessKeyId,
@@ -73,24 +88,23 @@ class VODAdapter {
73
88
  let result = await this._rpc.request('CreateUploadVideo', params, { method: 'POST' });
74
89
  if (result.Message)
75
90
  throw new Error(result.Message);
76
- let token = resultToCache(result);
77
- this._authCache.set(result.VideoId, token, token.expiration);
78
- return result.VideoId;
91
+ let token = parseToken(result);
92
+ this._authCache.set(result.VideoId, token, { ttl: token.expiration });
93
+ return `/${result.VideoId}#${token.path}`;
79
94
  };
80
- this.createUploadToken = async (videoId, meta) => {
81
- if (videoId[0] === '/')
82
- videoId = videoId.substring(1);
83
- let token = this._authCache.get(videoId);
95
+ this.createUploadToken = async (videoId, meta, durationSeconds) => {
96
+ let vid = parseVideoId(videoId);
97
+ let token = this._authCache.get(vid.id);
84
98
  debug('getAuth', videoId, token);
85
99
  if (!token) {
86
100
  let params = {
87
- VideoId: videoId
101
+ VideoId: vid.id
88
102
  };
89
103
  let result = await this._rpc.request('RefreshUploadVideo', params, { method: 'POST' });
90
104
  if (result.Message)
91
105
  throw new Error(result.Message);
92
- token = resultToCache(result);
93
- this._authCache.set(videoId, token, token.expiration);
106
+ token = parseToken(result);
107
+ this._authCache.set(vid.id, token, { ttl: token.expiration });
94
108
  }
95
109
  if (options.callbackUrl && meta) {
96
110
  token.callback = {
@@ -118,18 +132,17 @@ class VODAdapter {
118
132
  };
119
133
  }
120
134
  async getVideoInfo(videoId) {
121
- if (videoId[0] === '/')
122
- videoId = videoId.substring(1);
123
- let cache = this._videoCache.get(videoId);
135
+ let vid = parseVideoId(videoId);
136
+ let cache = this._videoCache.get(vid.id);
124
137
  if (cache)
125
138
  return cache;
126
139
  let params = {
127
- VideoId: videoId
140
+ VideoId: vid.id
128
141
  };
129
142
  try {
130
143
  let result = await this._rpc.request('GetVideoInfo', params, { method: 'POST' });
131
144
  if (result.Video) {
132
- this._videoCache.set(videoId, result.Video);
145
+ this._videoCache.set(vid.id, result.Video);
133
146
  return result.Video;
134
147
  }
135
148
  }
@@ -137,10 +150,9 @@ class VODAdapter {
137
150
  return null;
138
151
  }
139
152
  async getMezzanineInfo(videoId, options) {
140
- if (videoId[0] === '/')
141
- videoId = videoId.substring(1);
153
+ let vid = parseVideoId(videoId);
142
154
  let params = Object.assign({
143
- VideoId: videoId,
155
+ VideoId: vid.id,
144
156
  OutputType: 'cdn'
145
157
  }, options || {});
146
158
  try {
@@ -153,10 +165,9 @@ class VODAdapter {
153
165
  return null;
154
166
  }
155
167
  async getPlayInfo(videoId, options) {
156
- if (videoId[0] === '/')
157
- videoId = videoId.substring(1);
168
+ let vid = parseVideoId(videoId);
158
169
  let params = Object.assign({
159
- VideoId: videoId
170
+ VideoId: vid.id
160
171
  }, options || {});
161
172
  return await this._rpc.request('GetPlayInfo', params, { method: 'POST' });
162
173
  }
@@ -172,6 +183,7 @@ class VODAdapter {
172
183
  async createReadStream(videoId, options) {
173
184
  debug('createReadStream %s options: %o', videoId, options);
174
185
  let url = await this.createUrl(videoId);
186
+ console.log('url', url);
175
187
  let headers = {};
176
188
  if (options) {
177
189
  let start = options.start || 0;
@@ -239,6 +251,26 @@ class VODAdapter {
239
251
  }
240
252
  async createUrl(videoId, options) {
241
253
  debug('createUrl %s', videoId);
254
+ options = options || {};
255
+ let vid = parseVideoId(videoId);
256
+ let path = options.path || vid.path;
257
+ if (path && this._options.publicRead) {
258
+ if (/^https?\:\/\//.test(path))
259
+ return path;
260
+ return `${this._options.urlPrefix || ''}${path}`;
261
+ }
262
+ if (path) {
263
+ let urlPrefix = this._options.urlPrefix || '';
264
+ if (/^https?\:\/\//.test(path)) {
265
+ let url = new URL(path);
266
+ path = url.pathname;
267
+ urlPrefix = url.origin;
268
+ }
269
+ let timestamp = parseInt((Date.now() / 1000));
270
+ let string = `${path}-${timestamp}-0-0-${this._options.privateKey}`;
271
+ let hash = md5(string);
272
+ return `${urlPrefix}${path}?auth_key=${timestamp}-0-0-${hash}`;
273
+ }
242
274
  let info = await this.getMezzanineInfo(videoId, options);
243
275
  if (info)
244
276
  return info.FileURL;
@@ -246,14 +278,15 @@ class VODAdapter {
246
278
  }
247
279
  async unlink(videoId) {
248
280
  debug('unlink %s', videoId);
249
- if (videoId[0] === '/')
250
- videoId = videoId.substring(1);
281
+ let vid = parseVideoId(videoId);
251
282
  let params = {
252
- VideoIds: videoId
283
+ VideoIds: vid.id
253
284
  };
254
285
  let result = await this._rpc.request('DeleteVideo', params, { method: 'POST' });
255
286
  if (result.Message)
256
287
  throw new Error(result.Message);
288
+ this._videoCache.delete(vid.id);
289
+ this._authCache.delete(vid.id);
257
290
  }
258
291
  async exists(videoId) {
259
292
  return !!(await this.getVideoInfo(videoId));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fsd-vod",
3
- "version": "0.11.1",
3
+ "version": "0.13.0",
4
4
  "description": "Aliyun OSS adapter for fsd",
5
5
  "main": "lib/index.js",
6
6
  "types": "index.d.ts",
@@ -12,11 +12,11 @@
12
12
  "author": "Liang <liang@miaomo.cc> (https://github.com/liangxingchen)",
13
13
  "license": "MIT",
14
14
  "dependencies": {
15
- "@alicloud/pop-core": "^1.7.12",
15
+ "@alicloud/pop-core": "^1.7.13",
16
16
  "akita": "^1.0.4",
17
17
  "debug": "^4.3.4",
18
- "fsd-oss": "^0.11.1",
19
- "lru-cache": "^6.0.0"
18
+ "fsd-oss": "^0.13.0",
19
+ "lru-cache": "^9.1.1"
20
20
  },
21
- "gitHead": "5f39a56e4f5ae28e6f15c7888413561a924b54de"
21
+ "gitHead": "1548128573c0fd22977706a6704029ec3ca3bab6"
22
22
  }