fsd-vod 0.12.0 → 0.13.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2018 郑州脉冲软件科技有限公司
3
+ Copyright (c) 2023 郑州渺漠信息科技有限公司
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/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;
package/lib/index.js CHANGED
@@ -1,15 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const crypto = require("crypto");
4
+ const stream_1 = require("stream");
3
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,6 +46,8 @@ 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
52
  this._authCache = new lru_cache_1.LRUCache({
38
53
  max: 1000,
@@ -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);
91
+ let token = parseToken(result);
77
92
  this._authCache.set(result.VideoId, token, { ttl: token.expiration });
78
- return result.VideoId;
93
+ return `/${result.VideoId}#${token.path}`;
79
94
  };
80
95
  this.createUploadToken = async (videoId, meta, durationSeconds) => {
81
- if (videoId[0] === '/')
82
- videoId = videoId.substring(1);
83
- let token = this._authCache.get(videoId);
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, { ttl: 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.12.0",
3
+ "version": "0.13.1",
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.12.0",
19
- "lru-cache": "^9.1.1"
18
+ "fsd-oss": "^0.13.1",
19
+ "lru-cache": "^10.0.1"
20
20
  },
21
- "gitHead": "ad01afd0117496a9b857e566a404f0ececbd723d"
21
+ "gitHead": "12ff02bfc634ba84c771ca433d33aae2dc881436"
22
22
  }