├── .eslintrc.js
├── .gitignore
├── .npmignore
├── .npmrc
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── dist
├── vod-js-sdk-v6.js
└── vod-js-sdk-v6.js.map
├── docs
├── import-demo
│ ├── README.md
│ ├── bundle.js
│ ├── bundle.js.map
│ ├── index.html
│ ├── main.js
│ └── package.json
└── index.html
├── lib
├── package.json
└── src
│ ├── tc_vod.d.ts
│ ├── tc_vod.js
│ ├── tc_vod.js.map
│ ├── uploader.d.ts
│ ├── uploader.js
│ ├── uploader.js.map
│ ├── util.d.ts
│ ├── util.js
│ ├── util.js.map
│ ├── vod_reporter.d.ts
│ ├── vod_reporter.js
│ └── vod_reporter.js.map
├── package.json
├── src
├── tc_vod.ts
├── types.d.ts
├── uploader.ts
├── util.ts
└── vod_reporter.ts
├── test
├── env.ts
├── tc_vod.test.ts
├── uploader.test.ts
└── vod_reporter.test.ts
├── tsconfig.json
├── webpack.config.js
└── webpack.dev.config.js
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: "@typescript-eslint/parser", // Specifies the ESLint parser
3 | extends: [
4 | "plugin:@typescript-eslint/recommended", // Uses the recommended rules from the @typescript-eslint/eslint-plugin
5 | "prettier/@typescript-eslint", // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
6 | "plugin:prettier/recommended" // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
7 | ],
8 | parserOptions: {
9 | ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
10 | sourceType: "module" // Allows for the use of imports
11 | },
12 | rules: {
13 | // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
14 | // e.g. "@typescript-eslint/explicit-function-return-type": "off",
15 | "@typescript-eslint/explicit-member-accessibility": "off",
16 | "@typescript-eslint/no-var-requires": "off",
17 | "@typescript-eslint/camelcase": "off",
18 | "@typescript-eslint/interface-name-prefix": "off",
19 | "@typescript-eslint/no-explicit-any": "off",
20 | "@typescript-eslint/explicit-function-return-type": "off"
21 | }
22 | };
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | docs/import-demo/node_modules
38 | jspm_packages/
39 |
40 | # TypeScript v1 declaration files
41 | typings/
42 |
43 | # Optional npm cache directory
44 | .npm
45 |
46 | # Optional eslint cache
47 | .eslintcache
48 |
49 | # Optional REPL history
50 | .node_repl_history
51 |
52 | # Output of 'npm pack'
53 | *.tgz
54 |
55 | # Yarn Integrity file
56 | .yarn-integrity
57 |
58 | # dotenv environment variables file
59 | .env
60 |
61 | # next.js build output
62 | .next
63 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | docs
2 | src
3 | test
4 | .vscode
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.autoFixOnSave": true,
3 | "eslint.validate": [
4 | "javascript",
5 | "javascriptreact",
6 | { "language": "typescript", "autoFix": true },
7 | { "language": "typescriptreact", "autoFix": true }
8 | ],
9 | "editor.codeActionsOnSave": {
10 | "source.fixAll.eslint": true
11 | }
12 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 腾讯云
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vod-js-sdk-v6
2 |
3 | Web SDK for Tencent Cloud Video Service
4 |
5 | Document: https://cloud.tencent.com/document/product/266
6 |
7 | ## Install
8 |
9 | `npm install vod-js-sdk-v6`
10 |
11 | For browser, there is a umd bundle: `dist/vod-js-sdk-v6.js`
12 |
13 | We use `Promise` in the source code. You should imoprt Promise polyfill when target legacy browsers.
14 |
15 | ## Demo
16 |
17 | demo https://tencentyun.github.io/vod-js-sdk-v6/
18 |
19 | demo source code https://github.com/tencentyun/vod-js-sdk-v6/blob/master/docs/index.html
20 |
21 | `import` usage demo: https://github.com/tencentyun/vod-js-sdk-v6/tree/master/docs/import-demo
22 |
23 | troubleshooting https://github.com/tencentyun/vod-js-sdk-v6/wiki/%E5%B8%B8%E8%A7%81%E6%95%85%E9%9A%9C%E6%8E%92%E6%9F%A5
24 |
25 | ## Usage
26 |
27 | * NOTICE: Document may be outdated, but demo and source code are always latest*
28 |
29 | See: https://cloud.tencent.com/document/product/266/9239
30 |
31 | ## Contributing
32 |
33 | 1. `git clone` this project
34 | 2. `npm install`
35 | 3. `npm run test`
36 | 4. add more task cases
--------------------------------------------------------------------------------
/docs/import-demo/README.md:
--------------------------------------------------------------------------------
1 | ## desc
2 |
3 | This demo show how to install `vod-js-sdk-v6` by npm and use it in a webpack environment.
4 |
5 | ## demo url
6 |
7 | https://tencentyun.github.io/vod-js-sdk-v6/import-demo/index.html
8 |
9 | ## How to build
10 |
11 | 1. run `npm install` in this directory
12 | 2. run `npx webpack --entry ./main.js --output ./bundle.js` to build bundle.js
13 | 3. launch a http server in this directory, and open `index.html`
--------------------------------------------------------------------------------
/docs/import-demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | QCloud VIDEO UGC UPLOAD SDK
10 |
11 |
39 |
40 |
41 |
42 |
43 |
44 |
UGC-Uploader
45 |
46 |
47 |
48 |
49 |
50 | 1.示例中的签名是直接从demo后台获取签名。该 demo 对应的点播账号已开启防盗链功能,此视频分发 URL 仅限 2 个独立 IP 进行访问,有效期为 10 分钟。
51 | 2.示例1点击“直接上传视频”按钮即可上传视频。
52 | 3.示例2点击“添加视频”添加视频文件,点击“添加封面”添加封面文件,然后点击“上传视频和封面”按钮即可上传视频和封面。
53 | 4.取消上传为取消上传中的视频,上传成功的视频不能取消上传。
54 |
55 |
56 |
57 |
60 |
61 |
示例1:直接上传视频
62 |
直接上传视频
63 |
64 |
65 |
69 |
75 |
76 |
79 |
89 |
90 |
91 |
92 |
93 | 视频名称:{{uploaderInfo.videoInfo.name + '.' + uploaderInfo.videoInfo.type}};
94 | 上传进度:{{Math.floor(uploaderInfo.progress * 100) + '%'}};
95 | fileId:{{uploaderInfo.fileId}};
96 | 上传结果:{{uploaderInfo.isVideoUploadCancel ? '已取消' : uploaderInfo.isVideoUploadSuccess ? '上传成功' : '上传中'}};
97 |
98 | 地址:{{uploaderInfo.videoUrl}};
99 |
取消上传
100 |
101 |
102 |
103 | 封面名称:{{uploaderInfo.coverInfo.name}};
104 | 上传进度:{{Math.floor(uploaderInfo.coverProgress * 100) + '%'}};
105 | 上传结果:{{uploaderInfo.isCoverUploadSuccess ? '上传成功' : '上传中'}};
106 |
107 | 地址:{{uploaderInfo.coverUrl}};
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/docs/import-demo/main.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue/dist/vue.js";
2 | import axios from "axios";
3 | import TcVod from "vod-js-sdk-v6";
4 |
5 | /**
6 | * 计算签名。
7 | **/
8 | function getSignature() {
9 | return axios
10 | .post(
11 | "https://demo.vod2.myqcloud.com/ugc-upload/",
12 | JSON.stringify({
13 | Action: "GetUgcUploadSign"
14 | })
15 | )
16 | .then(function(response) {
17 | return response.data.data.sign;
18 | });
19 | }
20 |
21 | /*
22 | 防盗链地址获取。这是腾讯云官网demo的特殊逻辑,用户可忽略此处。
23 | */
24 | function getAntiLeechUrl(videoUrl, callback) {
25 | return axios
26 | .post(
27 | "https://demo.vod2.myqcloud.com/ugc-upload/",
28 | JSON.stringify({
29 | Action: "GetAntiLeechUrl",
30 | Url: videoUrl
31 | })
32 | )
33 | .then(function(response) {
34 | return response.data.data.url;
35 | });
36 | }
37 |
38 | var app = new Vue({
39 | el: "#main-area",
40 | data: {
41 | uploaderInfos: [],
42 |
43 | vcExampleVideoName: "",
44 | vcExampleCoverName: "",
45 |
46 | cExampleFileId: ""
47 | },
48 | created: function() {
49 | this.tcVod = new TcVod({
50 | getSignature: getSignature
51 | });
52 | },
53 | methods: {
54 | /**
55 | * vExample示例。添加视频
56 | **/
57 | vExampleAdd: function() {
58 | this.$refs.vExampleFile.click();
59 | },
60 | /**
61 | * vExample示例。上传视频过程。
62 | **/
63 | vExampleUpload: function() {
64 | var self = this;
65 | var mediaFile = this.$refs.vExampleFile.files[0];
66 |
67 | var uploader = this.tcVod.upload({
68 | mediaFile: mediaFile
69 | });
70 | uploader.on("media_progress", function(info) {
71 | uploaderInfo.progress = info.percent;
72 | });
73 | uploader.on("media_upload", function(info) {
74 | uploaderInfo.isVideoUploadSuccess = true;
75 | });
76 |
77 | console.log(uploader, "uploader");
78 |
79 | var uploaderInfo = {
80 | videoInfo: uploader.videoInfo,
81 | isVideoUploadSuccess: false,
82 | isVideoUploadCancel: false,
83 | progress: 0,
84 | fileId: "",
85 | videoUrl: "",
86 | cancel: function() {
87 | uploaderInfo.isVideoUploadCancel = true;
88 | uploader.cancel();
89 | }
90 | };
91 |
92 | this.uploaderInfos.push(uploaderInfo);
93 |
94 | uploader
95 | .done()
96 | .then(function(doneResult) {
97 | console.log("doneResult", doneResult);
98 |
99 | uploaderInfo.fileId = doneResult.fileId;
100 |
101 | return getAntiLeechUrl(doneResult.video.url);
102 | })
103 | .then(function(videoUrl) {
104 | uploaderInfo.videoUrl = videoUrl;
105 | self.$refs.vExample.reset();
106 | });
107 | },
108 |
109 | setVcExampleVideoName: function() {
110 | this.vcExampleVideoName = this.$refs.vcExampleVideo.files[0].name;
111 | },
112 | setVcExampleCoverName: function() {
113 | this.vcExampleCoverName = this.$refs.vcExampleCover.files[0].name;
114 | },
115 | /*
116 | vcExample添加视频
117 | */
118 | vcExampleAddVideo: function() {
119 | this.$refs.vcExampleVideo.click();
120 | },
121 | /*
122 | vcExample添加封面
123 | */
124 | vcExampleAddCover: function() {
125 | this.$refs.vcExampleCover.click();
126 | },
127 | /*
128 | vcExample上传过程
129 | */
130 | vcExampleAddUpload: function() {
131 | var self = this;
132 |
133 | var mediaFile = this.$refs.vcExampleVideo.files[0];
134 | var coverFile = this.$refs.vcExampleCover.files[0];
135 |
136 | var uploader = this.tcVod.upload({
137 | mediaFile: mediaFile,
138 | coverFile: coverFile
139 | });
140 | uploader.on("media_progress", function(info) {
141 | uploaderInfo.progress = info.percent;
142 | });
143 | uploader.on("media_upload", function(info) {
144 | uploaderInfo.isVideoUploadSuccess = true;
145 | });
146 | uploader.on("cover_progress", function(info) {
147 | uploaderInfo.coverProgress = info.percent;
148 | });
149 | uploader.on("cover_upload", function(info) {
150 | uploaderInfo.isCoverUploadSuccess = true;
151 | });
152 | console.log(uploader, "uploader");
153 |
154 | var uploaderInfo = {
155 | videoInfo: uploader.videoInfo,
156 | coverInfo: uploader.coverInfo,
157 | isVideoUploadSuccess: false,
158 | isVideoUploadCancel: false,
159 | isCoverUploadSuccess: false,
160 | progress: 0,
161 | coverProgress: 0,
162 | fileId: "",
163 | videoUrl: "",
164 | coverUrl: "",
165 | cancel: function() {
166 | uploaderInfo.isVideoUploadCancel = true;
167 | uploader.cancel();
168 | }
169 | };
170 |
171 | this.uploaderInfos.push(uploaderInfo);
172 |
173 | uploader
174 | .done()
175 | .then(function(doneResult) {
176 | console.log("doneResult", doneResult);
177 |
178 | uploaderInfo.fileId = doneResult.fileId;
179 |
180 | uploaderInfo.coverUrl = doneResult.cover.url;
181 | return getAntiLeechUrl(doneResult.video.url);
182 | })
183 | .then(function(videoUrl) {
184 | uploaderInfo.videoUrl = videoUrl;
185 | self.$refs.vcExample.reset();
186 | self.vcExampleVideoName = "";
187 | self.vcExampleCoverName = "";
188 | });
189 | },
190 |
191 | // cExample 添加封面
192 | cExampleAddCover: function() {
193 | this.$refs.cExampleCover.click();
194 | },
195 | // cExample 上传过程
196 | cExampleUpload: function() {
197 | var self = this;
198 |
199 | var coverFile = this.$refs.cExampleCover.files[0];
200 |
201 | var uploader = this.tcVod.upload({
202 | fileId: this.cExampleFileId,
203 | coverFile: coverFile
204 | });
205 | uploader.on("cover_progress", function(info) {
206 | uploaderInfo.coverProgress = info.percent;
207 | });
208 | uploader.on("cover_upload", function(info) {
209 | uploaderInfo.isCoverUploadSuccess = true;
210 | });
211 | console.log(uploader, "uploader");
212 |
213 | var uploaderInfo = {
214 | coverInfo: uploader.coverInfo,
215 | isCoverUploadSuccess: false,
216 | coverProgress: 0,
217 | coverUrl: "",
218 | cancel: function() {
219 | uploader.cancel();
220 | }
221 | };
222 |
223 | this.uploaderInfos.push(uploaderInfo);
224 |
225 | uploader.done().then(function(doneResult) {
226 | console.log("doneResult", doneResult);
227 |
228 | uploaderInfo.coverUrl = doneResult.cover.url;
229 |
230 | self.$refs.cExample.reset();
231 | });
232 | }
233 | }
234 | });
235 |
--------------------------------------------------------------------------------
/docs/import-demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "import-demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "main.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "MIT",
11 | "dependencies": {
12 | "axios": "^0.18.0",
13 | "vod-js-sdk-v6": "^1.4.8",
14 | "vue": "^2.6.10"
15 | },
16 | "devDependencies": {
17 | "webpack": "^4.30.0",
18 | "webpack-cli": "^3.3.1"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | QCloud VIDEO UGC UPLOAD SDK
10 |
11 |
39 |
40 |
41 |
42 |
43 |
44 |
UGC-Uploader
45 |
46 |
47 |
48 |
49 |
50 | 1.示例中的签名是直接从demo后台获取签名。该 demo 对应的点播账号已开启防盗链功能,此视频分发 URL 仅限 2 个独立 IP 进行访问,有效期为 10 分钟。
51 | 2.示例1点击“直接上传视频”按钮即可上传视频。
52 | 3.示例2点击“添加视频”添加视频文件,点击“添加封面”添加封面文件,然后点击“上传视频和封面”按钮即可上传视频和封面。
53 | 4.取消上传为取消上传中的视频,上传成功的视频不能取消上传。
54 |
55 |
56 |
57 |
60 |
61 |
示例1:直接上传视频
62 |
直接上传视频
63 |
64 |
65 |
69 |
75 |
76 |
79 |
89 |
90 |
91 |
92 |
93 | 视频名称:{{uploaderInfo.videoInfo.name + '.' + uploaderInfo.videoInfo.type}};
94 | 上传进度:{{Math.floor(uploaderInfo.progress * 100) + '%'}};
95 | fileId:{{uploaderInfo.fileId}};
96 | 上传结果:{{uploaderInfo.isVideoUploadCancel ? '已取消' : uploaderInfo.isVideoUploadSuccess ? '上传成功' : '上传中'}};
97 |
98 | 地址:{{uploaderInfo.videoUrl}};
99 |
取消上传
100 |
101 |
102 |
103 | 封面名称:{{uploaderInfo.coverInfo.name}};
104 | 上传进度:{{Math.floor(uploaderInfo.coverProgress * 100) + '%'}};
105 | 上传结果:{{uploaderInfo.isCoverUploadSuccess ? '上传成功' : '上传中'}};
106 |
107 | 地址:{{uploaderInfo.coverUrl}};
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
341 |
342 |
343 |
351 |
352 |
353 |
354 |
--------------------------------------------------------------------------------
/lib/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vod-js-sdk-v6",
3 | "version": "1.4.12",
4 | "description": "tencent cloud vod js sdk v6",
5 | "main": "lib/src/tc_vod.js",
6 | "unpkg": "dist/vod-js-sdk-v6.js",
7 | "typings": "lib/src/tc_vod.d.ts",
8 | "scripts": {
9 | "test": "cross-env NODE_ENV=test mocha -r espower-typescript/guess -r jsdom-global/register -r test/env test/**/*.test.ts",
10 | "cover": "cross-env NODE_ENV=test nyc mocha -r espower-typescript/guess -r jsdom-global/register -r test/env test/**/*.test.ts",
11 | "dev": "webpack --config webpack.dev.config.js --watch",
12 | "dist": "webpack --config webpack.config.js",
13 | "build": "npm run test && npm run dist && npm run compile",
14 | "compile": "tsc -p tsconfig.json",
15 | "prepublish": "npm run build",
16 | "lint": "tsc --noEmit && eslint 'src/**/*.{js,ts,tsx}' --quiet --fix"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/tencentyun/vod-js-sdk-v6.git"
21 | },
22 | "keywords": [
23 | "tencentcloud",
24 | "sdk",
25 | "vod"
26 | ],
27 | "author": "alsotang ",
28 | "license": "MIT",
29 | "bugs": {
30 | "url": "https://github.com/tencentyun/vod-js-sdk-v6/issues"
31 | },
32 | "homepage": "https://github.com/tencentyun/vod-js-sdk-v6#readme",
33 | "dependencies": {
34 | "axios": "^0.21.1",
35 | "cos-js-sdk-v5": "0.5.27",
36 | "eventemitter3": "^4.0.7",
37 | "js-sha1": "^0.6.0",
38 | "uuid": "^3.3.2"
39 | },
40 | "devDependencies": {
41 | "@types/mocha": "^5.2.5",
42 | "@types/semver": "^6.0.0",
43 | "@types/sha1": "^1.1.1",
44 | "@types/uuid": "^3.4.4",
45 | "@typescript-eslint/eslint-plugin": "^1.9.0",
46 | "@typescript-eslint/parser": "^1.9.0",
47 | "cross-env": "^6.0.3",
48 | "eslint": "^5.16.0",
49 | "eslint-config-prettier": "^4.3.0",
50 | "eslint-plugin-prettier": "^3.1.0",
51 | "espower-typescript": "^9.0.1",
52 | "jsdom": "^13.1.0",
53 | "jsdom-global": "^3.0.2",
54 | "mm": "^2.4.1",
55 | "mocha": "^5.2.0",
56 | "nyc": "^13.1.0",
57 | "power-assert": "^1.6.1",
58 | "prettier": "^1.17.1",
59 | "semver": "^6.1.1",
60 | "ts-loader": "^5.3.3",
61 | "typescript": "^3.5.3",
62 | "webpack": "^4.28.1",
63 | "webpack-cli": "^3.2.1"
64 | },
65 | "nyc": {
66 | "extension": [
67 | ".ts",
68 | ".tsx"
69 | ],
70 | "include": [
71 | "src"
72 | ],
73 | "reporter": [
74 | "html"
75 | ],
76 | "all": true
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/lib/src/tc_vod.d.ts:
--------------------------------------------------------------------------------
1 | import Uploader, { IGetSignature, UploaderOptions } from "./uploader";
2 | interface TcVodParams {
3 | getSignature: IGetSignature;
4 | allowReport?: boolean;
5 | appId?: number;
6 | reportId?: string;
7 | enableResume?: boolean;
8 | }
9 | declare class TcVod {
10 | getSignature: IGetSignature;
11 | allowReport: boolean;
12 | appId: number;
13 | reportId: string;
14 | enableResume: boolean;
15 | constructor(params: TcVodParams);
16 | upload(params: Omit): Uploader;
17 | initReporter(uploader: Uploader): void;
18 | }
19 | export default TcVod;
20 |
--------------------------------------------------------------------------------
/lib/src/tc_vod.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __assign = (this && this.__assign) || function () {
3 | __assign = Object.assign || function(t) {
4 | for (var s, i = 1, n = arguments.length; i < n; i++) {
5 | s = arguments[i];
6 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7 | t[p] = s[p];
8 | }
9 | return t;
10 | };
11 | return __assign.apply(this, arguments);
12 | };
13 | Object.defineProperty(exports, "__esModule", { value: true });
14 | var uploader_1 = require("./uploader");
15 | var vod_reporter_1 = require("./vod_reporter");
16 | var TcVod = /** @class */ (function () {
17 | function TcVod(params) {
18 | this.allowReport = true; // report sdk status to tencent cloud
19 | this.enableResume = true; // resume uploading from break point
20 | this.getSignature = params.getSignature;
21 | if (params.allowReport !== void 0) {
22 | this.allowReport = params.allowReport;
23 | }
24 | if (params.enableResume !== void 0) {
25 | this.enableResume = params.enableResume;
26 | }
27 | this.appId = params.appId;
28 | this.reportId = params.reportId;
29 | }
30 | TcVod.prototype.upload = function (params) {
31 | var uploaderParams = __assign({ getSignature: this.getSignature, appId: this.appId, reportId: this.reportId, enableResume: this.enableResume }, params);
32 | var uploader = new uploader_1.default(uploaderParams);
33 | if (this.allowReport) {
34 | this.initReporter(uploader);
35 | }
36 | uploader.start();
37 | return uploader;
38 | };
39 | // report to official report system
40 | TcVod.prototype.initReporter = function (uploader) {
41 | new vod_reporter_1.VodReporter(uploader);
42 | };
43 | return TcVod;
44 | }());
45 | exports.default = TcVod;
46 | //# sourceMappingURL=tc_vod.js.map
--------------------------------------------------------------------------------
/lib/src/tc_vod.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"tc_vod.js","sourceRoot":"","sources":["../../src/tc_vod.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,uCAAsE;AACtE,+CAA6C;AAS7C;IAME,eAAY,MAAmB;QAJ/B,gBAAW,GAAG,IAAI,CAAC,CAAC,qCAAqC;QAGzD,iBAAY,GAAG,IAAI,CAAC,CAAC,oCAAoC;QAEvD,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QACxC,IAAI,MAAM,CAAC,WAAW,KAAK,KAAK,CAAC,EAAE;YACjC,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;SACvC;QACD,IAAI,MAAM,CAAC,YAAY,KAAK,KAAK,CAAC,EAAE;YAClC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;SACzC;QACD,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAClC,CAAC;IAED,sBAAM,GAAN,UAAO,MAA6C;QAClD,IAAM,cAAc,cAClB,YAAY,EAAE,IAAI,CAAC,YAAY,EAC/B,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ,EACvB,YAAY,EAAE,IAAI,CAAC,YAAY,IAC5B,MAAM,CACV,CAAC;QACF,IAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,cAAc,CAAC,CAAC;QAC9C,IAAI,IAAI,CAAC,WAAW,EAAE;YACpB,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;SAC7B;QACD,QAAQ,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,mCAAmC;IACnC,4BAAY,GAAZ,UAAa,QAAkB;QAC7B,IAAI,0BAAW,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IACH,YAAC;AAAD,CAAC,AAtCD,IAsCC;AAED,kBAAe,KAAK,CAAC"}
--------------------------------------------------------------------------------
/lib/src/uploader.d.ts:
--------------------------------------------------------------------------------
1 | import { EventEmitter } from "eventemitter3";
2 | import { HOST } from "./util";
3 | export declare const vodAxios: import("axios").AxiosInstance;
4 | export declare type IGetSignature = () => Promise;
5 | export interface TcVodFileInfo {
6 | name: string;
7 | type: string;
8 | size: number;
9 | }
10 | export declare enum UploaderEvent {
11 | video_progress = "video_progress",
12 | media_progress = "media_progress",
13 | video_upload = "video_upload",
14 | media_upload = "media_upload",
15 | cover_progress = "cover_progress",
16 | cover_upload = "cover_upload"
17 | }
18 | interface IApplyData {
19 | video: {
20 | storageSignature: string;
21 | storagePath: string;
22 | };
23 | cover?: {
24 | storageSignature: string;
25 | storagePath: string;
26 | };
27 | storageAppId: number;
28 | storageBucket: string;
29 | storageRegion: string;
30 | storageRegionV5: string;
31 | domain: string;
32 | vodSessionKey: string;
33 | tempCertificate: {
34 | secretId: string;
35 | secretKey: string;
36 | token: string;
37 | expiredTime: number;
38 | };
39 | appId: number;
40 | timestamp: number;
41 | StorageRegionV5: string;
42 | }
43 | export interface UploaderOptions {
44 | getSignature: IGetSignature;
45 | videoFile?: File;
46 | mediaFile?: File;
47 | coverFile?: File;
48 | videoName?: string;
49 | mediaName?: string;
50 | fileId?: string;
51 | appId?: number;
52 | reportId?: string;
53 | applyRequestTimeout?: number;
54 | commitRequestTimeout?: number;
55 | retryDelay?: number;
56 | enableResume?: boolean;
57 | }
58 | declare class Uploader extends EventEmitter implements UploaderOptions {
59 | getSignature: IGetSignature;
60 | videoFile: File;
61 | videoInfo: TcVodFileInfo;
62 | coverFile: File;
63 | coverInfo: TcVodFileInfo;
64 | cos: any;
65 | taskId: string;
66 | cosAuthTime: number;
67 | videoName: string;
68 | sessionName: string;
69 | vodSessionKey: string;
70 | appId: number;
71 | fileId: string;
72 | reqKey: string;
73 | reportId: string;
74 | enableResume: boolean;
75 | donePromise: Promise;
76 | applyRequestTimeout: number;
77 | applyRequestRetryCount: number;
78 | commitRequestTimeout: number;
79 | commitRequestRetryCount: number;
80 | retryDelay: number;
81 | static host: HOST;
82 | constructor(params: UploaderOptions);
83 | setStorage(name: string, value: string): void;
84 | getStorage(name: string): string;
85 | delStorage(name: string): void;
86 | validateInitParams(params: UploaderOptions): void;
87 | genFileInfo(): void;
88 | applyUploadUGC(retryCount?: number): Promise;
89 | uploadToCos(applyData: IApplyData): Promise;
90 | commitUploadUGC(retryCount?: number): Promise;
91 | start(): void;
92 | _start(): Promise;
93 | done(): Promise;
94 | cancel(): void;
95 | }
96 | export default Uploader;
97 |
--------------------------------------------------------------------------------
/lib/src/uploader.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __extends = (this && this.__extends) || (function () {
3 | var extendStatics = function (d, b) {
4 | extendStatics = Object.setPrototypeOf ||
5 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7 | return extendStatics(d, b);
8 | };
9 | return function (d, b) {
10 | extendStatics(d, b);
11 | function __() { this.constructor = d; }
12 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13 | };
14 | })();
15 | var __assign = (this && this.__assign) || function () {
16 | __assign = Object.assign || function(t) {
17 | for (var s, i = 1, n = arguments.length; i < n; i++) {
18 | s = arguments[i];
19 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
20 | t[p] = s[p];
21 | }
22 | return t;
23 | };
24 | return __assign.apply(this, arguments);
25 | };
26 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
27 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
28 | return new (P || (P = Promise))(function (resolve, reject) {
29 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
30 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
31 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
32 | step((generator = generator.apply(thisArg, _arguments || [])).next());
33 | });
34 | };
35 | var __generator = (this && this.__generator) || function (thisArg, body) {
36 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
37 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
38 | function verb(n) { return function (v) { return step([n, v]); }; }
39 | function step(op) {
40 | if (f) throw new TypeError("Generator is already executing.");
41 | while (_) try {
42 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
43 | if (y = 0, t) op = [op[0] & 2, t.value];
44 | switch (op[0]) {
45 | case 0: case 1: t = op; break;
46 | case 4: _.label++; return { value: op[1], done: false };
47 | case 5: _.label++; y = op[1]; op = [0]; continue;
48 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
49 | default:
50 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
51 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
52 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
53 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
54 | if (t[2]) _.ops.pop();
55 | _.trys.pop(); continue;
56 | }
57 | op = body.call(thisArg, _);
58 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
59 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
60 | }
61 | };
62 | Object.defineProperty(exports, "__esModule", { value: true });
63 | exports.UploaderEvent = exports.vodAxios = void 0;
64 | var sha1 = require("js-sha1");
65 | var COS = require("cos-js-sdk-v5");
66 | var eventemitter3_1 = require("eventemitter3");
67 | var axios_1 = require("axios");
68 | var util_1 = require("./util");
69 | var vod_reporter_1 = require("./vod_reporter");
70 | var uuidv4 = require("uuid/v4");
71 | exports.vodAxios = axios_1.default.create();
72 | exports.vodAxios.interceptors.response.use(function (response) {
73 | return response;
74 | }, function (error) {
75 | if (isNaN(error.code)) {
76 | error.code = 500;
77 | }
78 | return Promise.reject(error);
79 | });
80 | var UploaderEvent;
81 | (function (UploaderEvent) {
82 | UploaderEvent["video_progress"] = "video_progress";
83 | UploaderEvent["media_progress"] = "media_progress";
84 | UploaderEvent["video_upload"] = "video_upload";
85 | UploaderEvent["media_upload"] = "media_upload";
86 | UploaderEvent["cover_progress"] = "cover_progress";
87 | UploaderEvent["cover_upload"] = "cover_upload";
88 | })(UploaderEvent = exports.UploaderEvent || (exports.UploaderEvent = {}));
89 | var Uploader = /** @class */ (function (_super) {
90 | __extends(Uploader, _super);
91 | function Uploader(params) {
92 | var _this = _super.call(this) || this;
93 | _this.sessionName = "";
94 | _this.vodSessionKey = "";
95 | _this.appId = 0;
96 | _this.reqKey = uuidv4();
97 | _this.reportId = "";
98 | // resume from break point
99 | _this.enableResume = true;
100 | // apply 请求的超时时间
101 | _this.applyRequestTimeout = 5000;
102 | _this.applyRequestRetryCount = 3;
103 | // commit 请求的超时时间
104 | _this.commitRequestTimeout = 5000;
105 | _this.commitRequestRetryCount = 3;
106 | // 重试请求的等待时间
107 | _this.retryDelay = 1000;
108 | _this.validateInitParams(params);
109 | _this.videoFile = params.mediaFile || params.videoFile;
110 | _this.getSignature = params.getSignature;
111 | _this.enableResume = params.enableResume;
112 | _this.videoName = params.mediaName || params.videoName;
113 | _this.coverFile = params.coverFile;
114 | _this.fileId = params.fileId;
115 | _this.applyRequestTimeout =
116 | params.applyRequestTimeout || _this.applyRequestTimeout;
117 | _this.commitRequestTimeout =
118 | params.commitRequestTimeout || _this.commitRequestTimeout;
119 | _this.retryDelay = params.retryDelay || _this.retryDelay;
120 | // custom report metrics
121 | _this.appId = params.appId || _this.appId;
122 | _this.reportId = params.reportId || _this.reportId;
123 | _this.cosAuthTime = 0;
124 | _this.genFileInfo();
125 | return _this;
126 | }
127 | // set storage
128 | Uploader.prototype.setStorage = function (name, value) {
129 | if (!name) {
130 | return;
131 | }
132 | var cname = "webugc_" + sha1(name);
133 | try {
134 | localStorage.setItem(cname, value);
135 | }
136 | catch (e) { }
137 | };
138 | // get storage
139 | Uploader.prototype.getStorage = function (name) {
140 | if (!name) {
141 | return;
142 | }
143 | var cname = "webugc_" + sha1(name);
144 | var result = null;
145 | try {
146 | result = localStorage.getItem(cname);
147 | }
148 | catch (e) { }
149 | return result;
150 | };
151 | // delete storage
152 | Uploader.prototype.delStorage = function (name) {
153 | if (!name) {
154 | return;
155 | }
156 | var cname = "webugc_" + sha1(name);
157 | try {
158 | localStorage.removeItem(cname);
159 | }
160 | catch (e) { }
161 | };
162 | // validate init params
163 | Uploader.prototype.validateInitParams = function (params) {
164 | if (!util_1.default.isFunction(params.getSignature)) {
165 | throw new Error("getSignature must be a function");
166 | }
167 | if (params.videoFile && !util_1.default.isFile(params.videoFile)) {
168 | throw new Error("videoFile must be a File");
169 | }
170 | };
171 | Uploader.prototype.genFileInfo = function () {
172 | // video file info
173 | var videoFile = this.videoFile;
174 | if (videoFile) {
175 | var lastDotIndex = videoFile.name.lastIndexOf(".");
176 | var videoName = "";
177 | // if specified, use it.
178 | if (this.videoName) {
179 | if (!util_1.default.isString(this.videoName)) {
180 | throw new Error("mediaName must be a string");
181 | }
182 | else if (/[:*?<>\"\\/|]/g.test(this.videoName)) {
183 | throw new Error('Cant use these chars in filename: \\ / : * ? " < > |');
184 | }
185 | else {
186 | videoName = this.videoName;
187 | }
188 | }
189 | else {
190 | // else use the meta info of file
191 | videoName = videoFile.name.substring(0, lastDotIndex);
192 | }
193 | this.videoInfo = {
194 | name: videoName,
195 | type: videoFile.name.substring(lastDotIndex + 1).toLowerCase(),
196 | size: videoFile.size
197 | };
198 | this.sessionName += videoFile.name + "_" + videoFile.size + ";";
199 | }
200 | // cover file info
201 | var coverFile = this.coverFile;
202 | if (coverFile) {
203 | var coverName = coverFile.name;
204 | var coverLastDotIndex = coverName.lastIndexOf(".");
205 | this.coverInfo = {
206 | name: coverName.substring(0, coverLastDotIndex),
207 | type: coverName.substring(coverLastDotIndex + 1).toLowerCase(),
208 | size: coverFile.size
209 | };
210 | this.sessionName += coverFile.name + "_" + coverFile.size + ";";
211 | }
212 | };
213 | Uploader.prototype.applyUploadUGC = function (retryCount) {
214 | if (retryCount === void 0) { retryCount = 0; }
215 | return __awaiter(this, void 0, void 0, function () {
216 | function whenError(err) {
217 | return __awaiter(this, void 0, void 0, function () {
218 | return __generator(this, function (_a) {
219 | switch (_a.label) {
220 | case 0:
221 | if (err.code === 500) {
222 | Uploader.host = Uploader.host === util_1.HOST.MAIN ? util_1.HOST.BACKUP : util_1.HOST.MAIN;
223 | }
224 | self.emit(vod_reporter_1.VodReportEvent.report_apply, {
225 | err: err,
226 | requestStartTime: requestStartTime
227 | });
228 | self.delStorage(self.sessionName);
229 | if (self.applyRequestRetryCount == retryCount) {
230 | if (err) {
231 | throw err;
232 | }
233 | throw new Error("apply upload failed");
234 | }
235 | return [4 /*yield*/, util_1.default.delay(self.retryDelay)];
236 | case 1:
237 | _a.sent();
238 | return [2 /*return*/, self.applyUploadUGC(retryCount + 1)];
239 | }
240 | });
241 | });
242 | }
243 | var self, signature, sendParams, videoInfo, coverInfo, vodSessionKey, requestStartTime, response, e_1, applyResult, applyData, vodSessionKey_1, err;
244 | return __generator(this, function (_a) {
245 | switch (_a.label) {
246 | case 0:
247 | self = this;
248 | return [4 /*yield*/, this.getSignature()];
249 | case 1:
250 | signature = _a.sent();
251 | videoInfo = this.videoInfo;
252 | coverInfo = this.coverInfo;
253 | vodSessionKey = this.vodSessionKey ||
254 | (this.enableResume && this.getStorage(this.sessionName));
255 | // resume from break point
256 | if (vodSessionKey) {
257 | sendParams = {
258 | signature: signature,
259 | vodSessionKey: vodSessionKey
260 | };
261 | }
262 | else if (videoInfo) {
263 | sendParams = {
264 | signature: signature,
265 | videoName: videoInfo.name,
266 | videoType: videoInfo.type,
267 | videoSize: videoInfo.size
268 | };
269 | if (coverInfo) {
270 | // upload video together with cover
271 | sendParams.coverName = coverInfo.name;
272 | sendParams.coverType = coverInfo.type;
273 | sendParams.coverSize = coverInfo.size;
274 | }
275 | }
276 | else if (this.fileId && coverInfo) {
277 | // alter cover
278 | sendParams = {
279 | signature: signature,
280 | fileId: this.fileId,
281 | coverName: coverInfo.name,
282 | coverType: coverInfo.type,
283 | coverSize: coverInfo.size
284 | };
285 | }
286 | else {
287 | throw "Wrong params, please check and try again";
288 | }
289 | requestStartTime = new Date();
290 | _a.label = 2;
291 | case 2:
292 | _a.trys.push([2, 4, , 5]);
293 | return [4 /*yield*/, exports.vodAxios.post("https://" + Uploader.host + "/v3/index.php?Action=ApplyUploadUGC", sendParams, {
294 | timeout: this.applyRequestTimeout,
295 | withCredentials: false
296 | })];
297 | case 3:
298 | response = _a.sent();
299 | return [3 /*break*/, 5];
300 | case 4:
301 | e_1 = _a.sent();
302 | return [2 /*return*/, whenError(e_1)];
303 | case 5:
304 | applyResult = response.data;
305 | // all err code https://user-images.githubusercontent.com/1147375/51222454-bf6ef280-1978-11e9-8e33-1b0fdb2fe200.png
306 | if (applyResult.code == 0) {
307 | applyData = applyResult.data;
308 | vodSessionKey_1 = applyData.vodSessionKey;
309 | this.setStorage(this.sessionName, vodSessionKey_1);
310 | this.vodSessionKey = vodSessionKey_1;
311 | this.appId = applyData.appId;
312 | this.emit(vod_reporter_1.VodReportEvent.report_apply, {
313 | data: applyData,
314 | requestStartTime: requestStartTime
315 | });
316 | return [2 /*return*/, applyData];
317 | }
318 | else {
319 | err = new Error(applyResult.message);
320 | err.code = applyResult.code;
321 | return [2 /*return*/, whenError(err)];
322 | }
323 | return [2 /*return*/];
324 | }
325 | });
326 | });
327 | };
328 | Uploader.prototype.uploadToCos = function (applyData) {
329 | return __awaiter(this, void 0, void 0, function () {
330 | var self, cosParam, cos, uploadCosParams, cosVideoParam, cosCoverParam, requestStartTime, uploadPromises;
331 | return __generator(this, function (_a) {
332 | switch (_a.label) {
333 | case 0:
334 | self = this;
335 | cosParam = {
336 | bucket: applyData.storageBucket + "-" + applyData.storageAppId,
337 | region: applyData.storageRegionV5
338 | };
339 | cos = new COS({
340 | getAuthorization: function (options, callback) {
341 | return __awaiter(this, void 0, void 0, function () {
342 | var currentTimeStamp, safeExpireTime;
343 | return __generator(this, function (_a) {
344 | switch (_a.label) {
345 | case 0:
346 | currentTimeStamp = util_1.default.getUnix();
347 | safeExpireTime = (applyData.tempCertificate.expiredTime - applyData.timestamp) * 0.9;
348 | if (!(self.cosAuthTime === 0)) return [3 /*break*/, 1];
349 | self.cosAuthTime = currentTimeStamp;
350 | return [3 /*break*/, 3];
351 | case 1:
352 | if (!(self.cosAuthTime &&
353 | currentTimeStamp - self.cosAuthTime >= safeExpireTime)) return [3 /*break*/, 3];
354 | return [4 /*yield*/, self.applyUploadUGC()];
355 | case 2:
356 | applyData = _a.sent();
357 | self.cosAuthTime = util_1.default.getUnix();
358 | _a.label = 3;
359 | case 3:
360 | callback({
361 | TmpSecretId: applyData.tempCertificate.secretId,
362 | TmpSecretKey: applyData.tempCertificate.secretKey,
363 | XCosSecurityToken: applyData.tempCertificate.token,
364 | StartTime: applyData.timestamp,
365 | ExpiredTime: applyData.tempCertificate.expiredTime
366 | });
367 | return [2 /*return*/];
368 | }
369 | });
370 | });
371 | }
372 | });
373 | this.cos = cos;
374 | uploadCosParams = [];
375 | if (this.videoFile) {
376 | cosVideoParam = __assign(__assign({}, cosParam), { file: this.videoFile, key: applyData.video.storagePath, onProgress: function (data) {
377 | self.emit(UploaderEvent.video_progress, data);
378 | self.emit(UploaderEvent.media_progress, data);
379 | }, onUpload: function (data) {
380 | self.emit(UploaderEvent.video_upload, data);
381 | self.emit(UploaderEvent.media_upload, data);
382 | }, onTaskReady: function (taskId) {
383 | self.taskId = taskId;
384 | } });
385 | uploadCosParams.push(cosVideoParam);
386 | }
387 | if (this.coverFile) {
388 | cosCoverParam = __assign(__assign({}, cosParam), { file: this.coverFile, key: applyData.cover.storagePath, onProgress: function (data) {
389 | self.emit(UploaderEvent.cover_progress, data);
390 | }, onUpload: function (data) {
391 | self.emit(UploaderEvent.cover_upload, data);
392 | }, onTaskReady: util_1.default.noop });
393 | uploadCosParams.push(cosCoverParam);
394 | }
395 | requestStartTime = new Date();
396 | uploadPromises = uploadCosParams.map(function (uploadCosParam) {
397 | return new Promise(function (resolve, reject) {
398 | cos.sliceUploadFile({
399 | Bucket: uploadCosParam.bucket,
400 | Region: uploadCosParam.region,
401 | Key: uploadCosParam.key,
402 | Body: uploadCosParam.file,
403 | onTaskReady: uploadCosParam.onTaskReady,
404 | onProgress: uploadCosParam.onProgress
405 | }, function (err, data) {
406 | // only report video file
407 | if (uploadCosParam.file === self.videoFile) {
408 | self.emit(vod_reporter_1.VodReportEvent.report_cos_upload, {
409 | err: err,
410 | requestStartTime: requestStartTime
411 | });
412 | }
413 | if (!err) {
414 | uploadCosParam.onUpload(data);
415 | return resolve();
416 | }
417 | self.delStorage(self.sessionName);
418 | if (JSON.stringify(err) === '{"error":"error","headers":{}}') {
419 | return reject(new Error("cors error"));
420 | }
421 | reject(err);
422 | });
423 | });
424 | });
425 | return [4 /*yield*/, Promise.all(uploadPromises)];
426 | case 1: return [2 /*return*/, _a.sent()];
427 | }
428 | });
429 | });
430 | };
431 | Uploader.prototype.commitUploadUGC = function (retryCount) {
432 | if (retryCount === void 0) { retryCount = 0; }
433 | return __awaiter(this, void 0, void 0, function () {
434 | function whenError(err) {
435 | return __awaiter(this, void 0, void 0, function () {
436 | return __generator(this, function (_a) {
437 | switch (_a.label) {
438 | case 0:
439 | if (err.code === 500) {
440 | Uploader.host = Uploader.host === util_1.HOST.MAIN ? util_1.HOST.BACKUP : util_1.HOST.MAIN;
441 | }
442 | self.emit(vod_reporter_1.VodReportEvent.report_commit, {
443 | err: err,
444 | requestStartTime: requestStartTime
445 | });
446 | if (self.commitRequestRetryCount == retryCount) {
447 | if (err) {
448 | throw err;
449 | }
450 | throw new Error("commit upload failed");
451 | }
452 | return [4 /*yield*/, util_1.default.delay(self.retryDelay)];
453 | case 1:
454 | _a.sent();
455 | return [2 /*return*/, self.commitUploadUGC(retryCount + 1)];
456 | }
457 | });
458 | });
459 | }
460 | var self, signature, vodSessionKey, requestStartTime, response, e_2, commitResult, err;
461 | return __generator(this, function (_a) {
462 | switch (_a.label) {
463 | case 0:
464 | self = this;
465 | return [4 /*yield*/, this.getSignature()];
466 | case 1:
467 | signature = _a.sent();
468 | this.delStorage(this.sessionName);
469 | vodSessionKey = this.vodSessionKey;
470 | requestStartTime = new Date();
471 | _a.label = 2;
472 | case 2:
473 | _a.trys.push([2, 4, , 5]);
474 | return [4 /*yield*/, exports.vodAxios.post("https://" + Uploader.host + "/v3/index.php?Action=CommitUploadUGC", {
475 | signature: signature,
476 | vodSessionKey: vodSessionKey
477 | }, {
478 | timeout: this.commitRequestTimeout,
479 | withCredentials: false
480 | })];
481 | case 3:
482 | response = _a.sent();
483 | return [3 /*break*/, 5];
484 | case 4:
485 | e_2 = _a.sent();
486 | return [2 /*return*/, whenError(e_2)];
487 | case 5:
488 | commitResult = response.data;
489 | if (commitResult.code == 0) {
490 | this.emit(vod_reporter_1.VodReportEvent.report_commit, {
491 | data: commitResult.data,
492 | requestStartTime: requestStartTime
493 | });
494 | return [2 /*return*/, commitResult.data];
495 | }
496 | else {
497 | err = new Error(commitResult.message);
498 | err.code = commitResult.code;
499 | return [2 /*return*/, whenError(err)];
500 | }
501 | return [2 /*return*/];
502 | }
503 | });
504 | });
505 | };
506 | Uploader.prototype.start = function () {
507 | var _this = this;
508 | var requestStartTime = new Date();
509 | this.donePromise = this._start()
510 | .then(function (doneResult) {
511 | _this.emit(vod_reporter_1.VodReportEvent.report_done, {
512 | err: { code: 0 },
513 | requestStartTime: requestStartTime
514 | });
515 | return doneResult;
516 | })
517 | .catch(function (err) {
518 | _this.emit(vod_reporter_1.VodReportEvent.report_done, {
519 | err: {
520 | code: (err && err.code) || util_1.default.CLIENT_ERROR_CODE.UPLOAD_FAIL
521 | },
522 | requestStartTime: requestStartTime
523 | });
524 | throw err;
525 | });
526 | };
527 | Uploader.prototype._start = function () {
528 | return __awaiter(this, void 0, void 0, function () {
529 | var applyData;
530 | return __generator(this, function (_a) {
531 | switch (_a.label) {
532 | case 0: return [4 /*yield*/, this.applyUploadUGC()];
533 | case 1:
534 | applyData = _a.sent();
535 | return [4 /*yield*/, this.uploadToCos(applyData)];
536 | case 2:
537 | _a.sent();
538 | return [4 /*yield*/, this.commitUploadUGC()];
539 | case 3: return [2 /*return*/, _a.sent()];
540 | }
541 | });
542 | });
543 | };
544 | Uploader.prototype.done = function () {
545 | return this.donePromise;
546 | };
547 | Uploader.prototype.cancel = function () {
548 | this.cos.cancelTask(this.taskId);
549 | };
550 | // domain
551 | Uploader.host = util_1.HOST.MAIN;
552 | return Uploader;
553 | }(eventemitter3_1.EventEmitter));
554 | exports.default = Uploader;
555 | //# sourceMappingURL=uploader.js.map
--------------------------------------------------------------------------------
/lib/src/uploader.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"uploader.js","sourceRoot":"","sources":["../../src/uploader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAChC,IAAM,GAAG,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;AAErC,+CAA6C;AAC7C,+BAA0B;AAC1B,+BAAoC;AAEpC,+CAAgD;AAChD,gCAAkC;AAErB,QAAA,QAAQ,GAAG,eAAK,CAAC,MAAM,EAAE,CAAC;AAEvC,gBAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAChC,UAAS,QAAQ;IACf,OAAO,QAAQ,CAAC;AAClB,CAAC,EACD,UAAS,KAAK;IACZ,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;QACrB,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC;KAClB;IACD,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC,CACF,CAAC;AASF,IAAY,aASX;AATD,WAAY,aAAa;IACvB,kDAAiC,CAAA;IACjC,kDAAiC,CAAA;IAEjC,8CAA6B,CAAA;IAC7B,8CAA6B,CAAA;IAE7B,kDAAiC,CAAA;IACjC,8CAA6B,CAAA;AAC/B,CAAC,EATW,aAAa,GAAb,qBAAa,KAAb,qBAAa,QASxB;AAgED;IAAuB,4BAAY;IAuCjC,kBAAY,MAAuB;QAAnC,YACE,iBAAO,SAuBR;QAnDD,iBAAW,GAAW,EAAE,CAAC;QACzB,mBAAa,GAAW,EAAE,CAAC;QAC3B,WAAK,GAAW,CAAC,CAAC;QAGlB,YAAM,GAAW,MAAM,EAAE,CAAC;QAC1B,cAAQ,GAAW,EAAE,CAAC;QAEtB,0BAA0B;QAC1B,kBAAY,GAAY,IAAI,CAAC;QAI7B,gBAAgB;QAChB,yBAAmB,GAAG,IAAI,CAAC;QAC3B,4BAAsB,GAAG,CAAC,CAAC;QAE3B,iBAAiB;QACjB,0BAAoB,GAAG,IAAI,CAAC;QAC5B,6BAAuB,GAAG,CAAC,CAAC;QAE5B,YAAY;QACZ,gBAAU,GAAG,IAAI,CAAC;QAOhB,KAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAEhC,KAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC;QACtD,KAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QAExC,KAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QACxC,KAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC;QACtD,KAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAClC,KAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAE5B,KAAI,CAAC,mBAAmB;YACtB,MAAM,CAAC,mBAAmB,IAAI,KAAI,CAAC,mBAAmB,CAAC;QACzD,KAAI,CAAC,oBAAoB;YACvB,MAAM,CAAC,oBAAoB,IAAI,KAAI,CAAC,oBAAoB,CAAC;QAC3D,KAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,KAAI,CAAC,UAAU,CAAC;QAEvD,wBAAwB;QACxB,KAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,KAAI,CAAC,KAAK,CAAC;QACxC,KAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,KAAI,CAAC,QAAQ,CAAC;QAEjD,KAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QACrB,KAAI,CAAC,WAAW,EAAE,CAAC;;IACrB,CAAC;IAED,cAAc;IACd,6BAAU,GAAV,UAAW,IAAY,EAAE,KAAa;QACpC,IAAI,CAAC,IAAI,EAAE;YACT,OAAO;SACR;QAED,IAAM,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI;YACF,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;SACpC;QAAC,OAAO,CAAC,EAAE,GAAE;IAChB,CAAC;IAED,cAAc;IACd,6BAAU,GAAV,UAAW,IAAY;QACrB,IAAI,CAAC,IAAI,EAAE;YACT,OAAO;SACR;QACD,IAAM,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,MAAM,GAAG,IAAI,CAAC;QAClB,IAAI;YACF,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;SACtC;QAAC,OAAO,CAAC,EAAE,GAAE;QAEd,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,iBAAiB;IACjB,6BAAU,GAAV,UAAW,IAAY;QACrB,IAAI,CAAC,IAAI,EAAE;YACT,OAAO;SACR;QACD,IAAM,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI;YACF,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;SAChC;QAAC,OAAO,CAAC,EAAE,GAAE;IAChB,CAAC;IAED,uBAAuB;IACvB,qCAAkB,GAAlB,UAAmB,MAAuB;QACxC,IAAI,CAAC,cAAI,CAAC,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE;YACzC,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;SACpD;QACD,IAAI,MAAM,CAAC,SAAS,IAAI,CAAC,cAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE;YACtD,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;SAC7C;IACH,CAAC;IAED,8BAAW,GAAX;QACE,kBAAkB;QAClB,IAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QACjC,IAAI,SAAS,EAAE;YACb,IAAM,YAAY,GAAG,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YACrD,IAAI,SAAS,GAAG,EAAE,CAAC;YACnB,wBAAwB;YACxB,IAAI,IAAI,CAAC,SAAS,EAAE;gBAClB,IAAI,CAAC,cAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;oBAClC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;iBAC/C;qBAAM,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;oBAChD,MAAM,IAAI,KAAK,CACb,sDAAsD,CACvD,CAAC;iBACH;qBAAM;oBACL,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;iBAC5B;aACF;iBAAM;gBACL,iCAAiC;gBACjC,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;aACvD;YACD,IAAI,CAAC,SAAS,GAAG;gBACf,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE;gBAC9D,IAAI,EAAE,SAAS,CAAC,IAAI;aACrB,CAAC;YACF,IAAI,CAAC,WAAW,IAAO,SAAS,CAAC,IAAI,SAAI,SAAS,CAAC,IAAI,MAAG,CAAC;SAC5D;QAED,kBAAkB;QAClB,IAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QACjC,IAAI,SAAS,EAAE;YACb,IAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC;YACjC,IAAM,iBAAiB,GAAG,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YACrD,IAAI,CAAC,SAAS,GAAG;gBACf,IAAI,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,iBAAiB,CAAC;gBAC/C,IAAI,EAAE,SAAS,CAAC,SAAS,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE;gBAC9D,IAAI,EAAE,SAAS,CAAC,IAAI;aACrB,CAAC;YACF,IAAI,CAAC,WAAW,IAAO,SAAS,CAAC,IAAI,SAAI,SAAS,CAAC,IAAI,MAAG,CAAC;SAC5D;IACH,CAAC;IAEK,iCAAc,GAApB,UAAqB,UAAsB;QAAtB,2BAAA,EAAA,cAAsB;;YA6CzC,SAAe,SAAS,CAAC,GAAc;;;;;gCACrC,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE;oCACpB,QAAQ,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,KAAK,WAAI,CAAC,IAAI,CAAC,CAAC,CAAC,WAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAI,CAAC,IAAI,CAAC;iCACvE;gCACD,IAAI,CAAC,IAAI,CAAC,6BAAc,CAAC,YAAY,EAAE;oCACrC,GAAG,EAAE,GAAG;oCACR,gBAAgB,EAAE,gBAAgB;iCACnC,CAAC,CAAC;gCACH,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gCAClC,IAAI,IAAI,CAAC,sBAAsB,IAAI,UAAU,EAAE;oCAC7C,IAAI,GAAG,EAAE;wCACP,MAAM,GAAG,CAAC;qCACX;oCACD,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;iCACxC;gCACD,qBAAM,cAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAA;;gCAAjC,SAAiC,CAAC;gCAClC,sBAAO,IAAI,CAAC,cAAc,CAAC,UAAU,GAAG,CAAC,CAAC,EAAC;;;;aAC5C;;;;;wBA7DK,IAAI,GAAG,IAAI,CAAC;wBAEA,qBAAM,IAAI,CAAC,YAAY,EAAE,EAAA;;wBAArC,SAAS,GAAG,SAAyB;wBAGrC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;wBAC3B,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;wBAC3B,aAAa,GACjB,IAAI,CAAC,aAAa;4BAClB,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;wBAE3D,0BAA0B;wBAC1B,IAAI,aAAa,EAAE;4BACjB,UAAU,GAAG;gCACX,SAAS,EAAE,SAAS;gCACpB,aAAa,EAAE,aAAa;6BAC7B,CAAC;yBACH;6BAAM,IAAI,SAAS,EAAE;4BACpB,UAAU,GAAG;gCACX,SAAS,EAAE,SAAS;gCACpB,SAAS,EAAE,SAAS,CAAC,IAAI;gCACzB,SAAS,EAAE,SAAS,CAAC,IAAI;gCACzB,SAAS,EAAE,SAAS,CAAC,IAAI;6BAC1B,CAAC;4BACF,IAAI,SAAS,EAAE;gCACb,mCAAmC;gCACnC,UAAU,CAAC,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC;gCACtC,UAAU,CAAC,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC;gCACtC,UAAU,CAAC,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC;6BACvC;yBACF;6BAAM,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE;4BACnC,cAAc;4BACd,UAAU,GAAG;gCACX,SAAS,EAAE,SAAS;gCACpB,MAAM,EAAE,IAAI,CAAC,MAAM;gCACnB,SAAS,EAAE,SAAS,CAAC,IAAI;gCACzB,SAAS,EAAE,SAAS,CAAC,IAAI;gCACzB,SAAS,EAAE,SAAS,CAAC,IAAI;6BAC1B,CAAC;yBACH;6BAAM;4BACL,MAAM,0CAA0C,CAAC;yBAClD;wBACK,gBAAgB,GAAG,IAAI,IAAI,EAAE,CAAC;;;;wBAuBvB,qBAAM,gBAAQ,CAAC,IAAI,CAC5B,aAAW,QAAQ,CAAC,IAAI,wCAAqC,EAC7D,UAAU,EACV;gCACE,OAAO,EAAE,IAAI,CAAC,mBAAmB;gCACjC,eAAe,EAAE,KAAK;6BACvB,CACF,EAAA;;wBAPD,QAAQ,GAAG,SAOV,CAAC;;;;wBAEF,sBAAO,SAAS,CAAC,GAAC,CAAC,EAAC;;wBAGhB,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC;wBAElC,mHAAmH;wBACnH,IAAI,WAAW,CAAC,IAAI,IAAI,CAAC,EAAE;4BACnB,SAAS,GAAG,WAAW,CAAC,IAAkB,CAAC;4BAC3C,kBAAgB,SAAS,CAAC,aAAa,CAAC;4BAC9C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,eAAa,CAAC,CAAC;4BACjD,IAAI,CAAC,aAAa,GAAG,eAAa,CAAC;4BACnC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;4BAE7B,IAAI,CAAC,IAAI,CAAC,6BAAc,CAAC,YAAY,EAAE;gCACrC,IAAI,EAAE,SAAS;gCACf,gBAAgB,EAAE,gBAAgB;6BACnC,CAAC,CAAC;4BACH,sBAAO,SAAS,EAAC;yBAClB;6BAAM;4BAEC,GAAG,GAAa,IAAI,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;4BACrD,GAAG,CAAC,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC;4BAE5B,sBAAO,SAAS,CAAC,GAAG,CAAC,EAAC;yBACvB;;;;;KACF;IAEK,8BAAW,GAAjB,UAAkB,SAAqB;;;;;;wBAC/B,IAAI,GAAG,IAAI,CAAC;wBAEZ,QAAQ,GAAG;4BACf,MAAM,EAAE,SAAS,CAAC,aAAa,GAAG,GAAG,GAAG,SAAS,CAAC,YAAY;4BAC9D,MAAM,EAAE,SAAS,CAAC,eAAe;yBAClC,CAAC;wBAEI,GAAG,GAAG,IAAI,GAAG,CAAC;4BAClB,gBAAgB,EAAE,UAAe,OAAe,EAAE,QAAkB;;;;;;gDAC5D,gBAAgB,GAAG,cAAI,CAAC,OAAO,EAAE,CAAC;gDAClC,cAAc,GAClB,CAAC,SAAS,CAAC,eAAe,CAAC,WAAW,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC;qDAClE,CAAA,IAAI,CAAC,WAAW,KAAK,CAAC,CAAA,EAAtB,wBAAsB;gDACxB,IAAI,CAAC,WAAW,GAAG,gBAAgB,CAAC;;;qDAEpC,CAAA,IAAI,CAAC,WAAW;oDAChB,gBAAgB,GAAG,IAAI,CAAC,WAAW,IAAI,cAAc,CAAA,EADrD,wBACqD;gDAEzC,qBAAM,IAAI,CAAC,cAAc,EAAE,EAAA;;gDAAvC,SAAS,GAAG,SAA2B,CAAC;gDACxC,IAAI,CAAC,WAAW,GAAG,cAAI,CAAC,OAAO,EAAE,CAAC;;;gDAGpC,QAAQ,CAAC;oDACP,WAAW,EAAE,SAAS,CAAC,eAAe,CAAC,QAAQ;oDAC/C,YAAY,EAAE,SAAS,CAAC,eAAe,CAAC,SAAS;oDACjD,iBAAiB,EAAE,SAAS,CAAC,eAAe,CAAC,KAAK;oDAClD,SAAS,EAAE,SAAS,CAAC,SAAS;oDAC9B,WAAW,EAAE,SAAS,CAAC,eAAe,CAAC,WAAW;iDACnD,CAAC,CAAC;;;;;6BACJ;yBACF,CAAC,CAAC;wBACH,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;wBAET,eAAe,GAAG,EAAE,CAAC;wBAE3B,IAAI,IAAI,CAAC,SAAS,EAAE;4BACZ,aAAa,yBACd,QAAQ,KACX,IAAI,EAAE,IAAI,CAAC,SAAS,EACpB,GAAG,EAAE,SAAS,CAAC,KAAK,CAAC,WAAW,EAChC,UAAU,EAAE,UAAS,IAAS;oCAC5B,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;oCAC9C,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;gCAChD,CAAC,EACD,QAAQ,EAAE,UAAS,IAAS;oCAC1B,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;oCAC5C,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;gCAC9C,CAAC,EACD,WAAW,EAAE,UAAS,MAAc;oCAClC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;gCACvB,CAAC,GACF,CAAC;4BACF,eAAe,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;yBACrC;wBAED,IAAI,IAAI,CAAC,SAAS,EAAE;4BACZ,aAAa,yBACd,QAAQ,KACX,IAAI,EAAE,IAAI,CAAC,SAAS,EACpB,GAAG,EAAE,SAAS,CAAC,KAAK,CAAC,WAAW,EAChC,UAAU,EAAE,UAAS,IAAS;oCAC5B,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;gCAChD,CAAC,EACD,QAAQ,EAAE,UAAS,IAAS;oCAC1B,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;gCAC9C,CAAC,EACD,WAAW,EAAE,cAAI,CAAC,IAAI,GACvB,CAAC;4BACF,eAAe,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;yBACrC;wBACK,gBAAgB,GAAG,IAAI,IAAI,EAAE,CAAC;wBAC9B,cAAc,GAAG,eAAe,CAAC,GAAG,CAAC,UAAA,cAAc;4BACvD,OAAO,IAAI,OAAO,CAAO,UAAS,OAAO,EAAE,MAAM;gCAC/C,GAAG,CAAC,eAAe,CACjB;oCACE,MAAM,EAAE,cAAc,CAAC,MAAM;oCAC7B,MAAM,EAAE,cAAc,CAAC,MAAM;oCAC7B,GAAG,EAAE,cAAc,CAAC,GAAG;oCACvB,IAAI,EAAE,cAAc,CAAC,IAAI;oCACzB,WAAW,EAAE,cAAc,CAAC,WAAW;oCACvC,UAAU,EAAE,cAAc,CAAC,UAAU;iCACtC,EACD,UAAS,GAAQ,EAAE,IAAS;oCAC1B,yBAAyB;oCACzB,IAAI,cAAc,CAAC,IAAI,KAAK,IAAI,CAAC,SAAS,EAAE;wCAC1C,IAAI,CAAC,IAAI,CAAC,6BAAc,CAAC,iBAAiB,EAAE;4CAC1C,GAAG,EAAE,GAAG;4CACR,gBAAgB,EAAE,gBAAgB;yCACnC,CAAC,CAAC;qCACJ;oCACD,IAAI,CAAC,GAAG,EAAE;wCACR,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;wCAC9B,OAAO,OAAO,EAAE,CAAC;qCAClB;oCACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;oCAClC,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,gCAAgC,EAAE;wCAC5D,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;qCACxC;oCACD,MAAM,CAAC,GAAG,CAAC,CAAC;gCACd,CAAC,CACF,CAAC;4BACJ,CAAC,CAAC,CAAC;wBACL,CAAC,CAAC,CAAC;wBAEI,qBAAM,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAA;4BAAxC,sBAAO,SAAiC,EAAC;;;;KAC1C;IAEK,kCAAe,GAArB,UAAsB,UAAsB;QAAtB,2BAAA,EAAA,cAAsB;;YAQ1C,SAAe,SAAS,CAAC,GAAc;;;;;gCACrC,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE;oCACpB,QAAQ,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,KAAK,WAAI,CAAC,IAAI,CAAC,CAAC,CAAC,WAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAI,CAAC,IAAI,CAAC;iCACvE;gCACD,IAAI,CAAC,IAAI,CAAC,6BAAc,CAAC,aAAa,EAAE;oCACtC,GAAG,EAAE,GAAG;oCACR,gBAAgB,EAAE,gBAAgB;iCACnC,CAAC,CAAC;gCACH,IAAI,IAAI,CAAC,uBAAuB,IAAI,UAAU,EAAE;oCAC9C,IAAI,GAAG,EAAE;wCACP,MAAM,GAAG,CAAC;qCACX;oCACD,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;iCACzC;gCACD,qBAAM,cAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAA;;gCAAjC,SAAiC,CAAC;gCAClC,sBAAO,IAAI,CAAC,eAAe,CAAC,UAAU,GAAG,CAAC,CAAC,EAAC;;;;aAC7C;;;;;wBAvBK,IAAI,GAAG,IAAI,CAAC;wBAEA,qBAAM,IAAI,CAAC,YAAY,EAAE,EAAA;;wBAArC,SAAS,GAAG,SAAyB;wBAC3C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;wBAC5B,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;wBAEnC,gBAAgB,GAAG,IAAI,IAAI,EAAE,CAAC;;;;wBAqBvB,qBAAM,gBAAQ,CAAC,IAAI,CAC5B,aAAW,QAAQ,CAAC,IAAI,yCAAsC,EAC9D;gCACE,SAAS,EAAE,SAAS;gCACpB,aAAa,EAAE,aAAa;6BAC7B,EACD;gCACE,OAAO,EAAE,IAAI,CAAC,oBAAoB;gCAClC,eAAe,EAAE,KAAK;6BACvB,CACF,EAAA;;wBAVD,QAAQ,GAAG,SAUV,CAAC;;;;wBAEF,sBAAO,SAAS,CAAC,GAAC,CAAC,EAAC;;wBAGhB,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC;wBAEnC,IAAI,YAAY,CAAC,IAAI,IAAI,CAAC,EAAE;4BAC1B,IAAI,CAAC,IAAI,CAAC,6BAAc,CAAC,aAAa,EAAE;gCACtC,IAAI,EAAE,YAAY,CAAC,IAAI;gCACvB,gBAAgB,EAAE,gBAAgB;6BACnC,CAAC,CAAC;4BACH,sBAAO,YAAY,CAAC,IAAI,EAAC;yBAC1B;6BAAM;4BACC,GAAG,GAAa,IAAI,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;4BACtD,GAAG,CAAC,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC;4BAC7B,sBAAO,SAAS,CAAC,GAAG,CAAC,EAAC;yBACvB;;;;;KACF;IAED,wBAAK,GAAL;QAAA,iBAoBC;QAnBC,IAAM,gBAAgB,GAAG,IAAI,IAAI,EAAE,CAAC;QAEpC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE;aAC7B,IAAI,CAAC,UAAA,UAAU;YACd,KAAI,CAAC,IAAI,CAAC,6BAAc,CAAC,WAAW,EAAE;gBACpC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE;gBAChB,gBAAgB,EAAE,gBAAgB;aACnC,CAAC,CAAC;YACH,OAAO,UAAU,CAAC;QACpB,CAAC,CAAC;aACD,KAAK,CAAC,UAAA,GAAG;YACR,KAAI,CAAC,IAAI,CAAC,6BAAc,CAAC,WAAW,EAAE;gBACpC,GAAG,EAAE;oBACH,IAAI,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,cAAI,CAAC,iBAAiB,CAAC,WAAW;iBAC9D;gBACD,gBAAgB,EAAE,gBAAgB;aACnC,CAAC,CAAC;YACH,MAAM,GAAG,CAAC;QACZ,CAAC,CAAC,CAAC;IACP,CAAC;IAEK,yBAAM,GAAZ;;;;;4BACoB,qBAAM,IAAI,CAAC,cAAc,EAAE,EAAA;;wBAAvC,SAAS,GAAG,SAA2B;wBAE7C,qBAAM,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAA;;wBAAjC,SAAiC,CAAC;wBAE3B,qBAAM,IAAI,CAAC,eAAe,EAAE,EAAA;4BAAnC,sBAAO,SAA4B,EAAC;;;;KACrC;IAED,uBAAI,GAAJ;QACE,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,yBAAM,GAAN;QACE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAvaD,SAAS;IACF,aAAI,GAAG,WAAI,CAAC,IAAI,CAAC;IAua1B,eAAC;CAAA,AA5cD,CAAuB,4BAAY,GA4clC;AAED,kBAAe,QAAQ,CAAC"}
--------------------------------------------------------------------------------
/lib/src/util.d.ts:
--------------------------------------------------------------------------------
1 | declare function isFile(v: any): boolean;
2 | declare function isFunction(v: any): boolean;
3 | declare function isString(v: any): boolean;
4 | declare function noop(): void;
5 | declare function delay(ms: number): Promise;
6 | declare function getUnix(): number;
7 | declare enum CLIENT_ERROR_CODE {
8 | UPLOAD_FAIL = 1
9 | }
10 | export declare enum HOST {
11 | MAIN = "vod2.qcloud.com",
12 | BACKUP = "vod2.dnsv1.com"
13 | }
14 | declare const _default: {
15 | isFile: typeof isFile;
16 | isFunction: typeof isFunction;
17 | isString: typeof isString;
18 | noop: typeof noop;
19 | delay: typeof delay;
20 | getUnix: typeof getUnix;
21 | isTest: boolean;
22 | isDev: boolean;
23 | CLIENT_ERROR_CODE: typeof CLIENT_ERROR_CODE;
24 | };
25 | export default _default;
26 |
--------------------------------------------------------------------------------
/lib/src/util.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.HOST = void 0;
4 | function isFile(v) {
5 | return Object.prototype.toString.call(v) == "[object File]";
6 | }
7 | function isFunction(v) {
8 | return typeof v === "function";
9 | }
10 | function isString(v) {
11 | return typeof v === "string";
12 | }
13 | // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
14 | function noop() { }
15 | function delay(ms) {
16 | return new Promise(function (resolve) {
17 | setTimeout(function () {
18 | resolve();
19 | }, ms);
20 | });
21 | }
22 | function getUnix() {
23 | return Math.floor(Date.now() / 1000);
24 | }
25 | var CLIENT_ERROR_CODE;
26 | (function (CLIENT_ERROR_CODE) {
27 | CLIENT_ERROR_CODE[CLIENT_ERROR_CODE["UPLOAD_FAIL"] = 1] = "UPLOAD_FAIL";
28 | })(CLIENT_ERROR_CODE || (CLIENT_ERROR_CODE = {}));
29 | var HOST;
30 | (function (HOST) {
31 | HOST["MAIN"] = "vod2.qcloud.com";
32 | HOST["BACKUP"] = "vod2.dnsv1.com";
33 | })(HOST = exports.HOST || (exports.HOST = {}));
34 | exports.default = {
35 | isFile: isFile,
36 | isFunction: isFunction,
37 | isString: isString,
38 | noop: noop,
39 | delay: delay,
40 | getUnix: getUnix,
41 | isTest: process.env.NODE_ENV === "test",
42 | isDev: process.env.NODE_ENV === "development",
43 | CLIENT_ERROR_CODE: CLIENT_ERROR_CODE
44 | };
45 | //# sourceMappingURL=util.js.map
--------------------------------------------------------------------------------
/lib/src/util.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/util.ts"],"names":[],"mappings":";;;AAAA,SAAS,MAAM,CAAC,CAAM;IACpB,OAAO,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC;AAC9D,CAAC;AAED,SAAS,UAAU,CAAC,CAAM;IACxB,OAAO,OAAO,CAAC,KAAK,UAAU,CAAC;AACjC,CAAC;AAED,SAAS,QAAQ,CAAC,CAAM;IACtB,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC;AAC/B,CAAC;AAED,4EAA4E;AAC5E,SAAS,IAAI,KAAI,CAAC;AAElB,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,UAAA,OAAO;QACxB,UAAU,CAAC;YACT,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,OAAO;IACd,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,IAAK,iBAEJ;AAFD,WAAK,iBAAiB;IACpB,uEAAe,CAAA;AACjB,CAAC,EAFI,iBAAiB,KAAjB,iBAAiB,QAErB;AAED,IAAY,IAGX;AAHD,WAAY,IAAI;IACd,gCAAwB,CAAA;IACxB,iCAAyB,CAAA;AAC3B,CAAC,EAHW,IAAI,GAAJ,YAAI,KAAJ,YAAI,QAGf;AAED,kBAAe;IACb,MAAM,QAAA;IACN,UAAU,YAAA;IACV,QAAQ,UAAA;IACR,IAAI,MAAA;IACJ,KAAK,OAAA;IACL,OAAO,SAAA;IACP,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM;IACvC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;IAC7C,iBAAiB,mBAAA;CAClB,CAAC"}
--------------------------------------------------------------------------------
/lib/src/vod_reporter.d.ts:
--------------------------------------------------------------------------------
1 | import Uploader from "./uploader";
2 | interface IVodReporter {
3 | }
4 | export declare enum VodReportEvent {
5 | report_apply = "report_apply",
6 | report_cos_upload = "report_cos_upload",
7 | report_commit = "report_commit",
8 | report_done = "report_done"
9 | }
10 | interface ReportObj {
11 | err: any;
12 | requestStartTime: Date;
13 | data: any;
14 | }
15 | export declare class VodReporter {
16 | uploader: Uploader;
17 | options: IVodReporter;
18 | baseReportData: any;
19 | reportUrl: string;
20 | constructor(uploader: Uploader, options?: IVodReporter);
21 | init(): void;
22 | onApply(reportObj: ReportObj): void;
23 | onCosUpload(reportObj: ReportObj): void;
24 | onCommit(reportObj: ReportObj): void;
25 | onDone(reportObj: ReportObj): void;
26 | report(reportData: any): void;
27 | send(reportData: any): void;
28 | }
29 | export {};
30 |
--------------------------------------------------------------------------------
/lib/src/vod_reporter.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __assign = (this && this.__assign) || function () {
3 | __assign = Object.assign || function(t) {
4 | for (var s, i = 1, n = arguments.length; i < n; i++) {
5 | s = arguments[i];
6 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7 | t[p] = s[p];
8 | }
9 | return t;
10 | };
11 | return __assign.apply(this, arguments);
12 | };
13 | Object.defineProperty(exports, "__esModule", { value: true });
14 | exports.VodReporter = exports.VodReportEvent = void 0;
15 | var uploader_1 = require("./uploader");
16 | var pkg = require("../package.json");
17 | var util_1 = require("./util");
18 | var VodReportEvent;
19 | (function (VodReportEvent) {
20 | VodReportEvent["report_apply"] = "report_apply";
21 | VodReportEvent["report_cos_upload"] = "report_cos_upload";
22 | VodReportEvent["report_commit"] = "report_commit";
23 | VodReportEvent["report_done"] = "report_done";
24 | })(VodReportEvent = exports.VodReportEvent || (exports.VodReportEvent = {}));
25 | var ReqType;
26 | (function (ReqType) {
27 | ReqType[ReqType["apply"] = 10001] = "apply";
28 | ReqType[ReqType["cos_upload"] = 20001] = "cos_upload";
29 | ReqType[ReqType["commit"] = 10002] = "commit";
30 | ReqType[ReqType["done"] = 40001] = "done";
31 | })(ReqType || (ReqType = {}));
32 | var VodReporter = /** @class */ (function () {
33 | function VodReporter(uploader, options) {
34 | // only partial data when created
35 | this.baseReportData = {
36 | version: pkg.version,
37 | platform: 3000,
38 | device: navigator.userAgent
39 | };
40 | this.reportUrl = "https://vodreport.qcloud.com/ugcupload_new";
41 | this.uploader = uploader;
42 | this.options = options;
43 | this.init();
44 | }
45 | VodReporter.prototype.init = function () {
46 | this.uploader.on(VodReportEvent.report_apply, this.onApply.bind(this));
47 | this.uploader.on(VodReportEvent.report_cos_upload, this.onCosUpload.bind(this));
48 | this.uploader.on(VodReportEvent.report_commit, this.onCommit.bind(this));
49 | this.uploader.on(VodReportEvent.report_done, this.onDone.bind(this));
50 | };
51 | // ApplyUploadUGC
52 | VodReporter.prototype.onApply = function (reportObj) {
53 | try {
54 | var uploader = this.uploader;
55 | if (!uploader.videoFile) {
56 | return;
57 | }
58 | Object.assign(this.baseReportData, {
59 | appId: uploader.appId,
60 | fileSize: uploader.videoFile.size,
61 | fileName: uploader.videoFile.name,
62 | fileType: uploader.videoFile.type,
63 | vodSessionKey: uploader.vodSessionKey,
64 | reqKey: uploader.reqKey,
65 | reportId: uploader.reportId
66 | });
67 | var customReportData = {
68 | reqType: ReqType.apply,
69 | errCode: 0,
70 | vodErrCode: 0,
71 | errMsg: "",
72 | reqTimeCost: Number(new Date()) - Number(reportObj.requestStartTime),
73 | reqTime: Number(reportObj.requestStartTime)
74 | };
75 | if (reportObj.err) {
76 | customReportData.errCode = 1;
77 | customReportData.vodErrCode = reportObj.err.code;
78 | customReportData.errMsg = reportObj.err.message;
79 | }
80 | if (reportObj.data) {
81 | this.baseReportData.cosRegion = reportObj.data.storageRegionV5;
82 | }
83 | this.report(customReportData);
84 | }
85 | catch (e) {
86 | console.error("onApply", e);
87 | if (util_1.default.isTest) {
88 | throw e;
89 | }
90 | }
91 | };
92 | // upload to cos
93 | VodReporter.prototype.onCosUpload = function (reportObj) {
94 | try {
95 | var customReportData = {
96 | reqType: ReqType.cos_upload,
97 | errCode: 0,
98 | cosErrCode: "",
99 | errMsg: "",
100 | reqTimeCost: Number(new Date()) - Number(reportObj.requestStartTime),
101 | reqTime: Number(reportObj.requestStartTime)
102 | };
103 | if (reportObj.err) {
104 | customReportData.errCode = 1;
105 | customReportData.cosErrCode = reportObj.err.error
106 | ? reportObj.err.error.Code
107 | : reportObj.err;
108 | if (reportObj.err && reportObj.err.error === "error") {
109 | customReportData.cosErrCode = "cors error";
110 | }
111 | customReportData.errMsg = JSON.stringify(reportObj.err);
112 | }
113 | this.report(customReportData);
114 | }
115 | catch (e) {
116 | console.error("onCosUpload", e);
117 | if (util_1.default.isTest) {
118 | throw e;
119 | }
120 | }
121 | };
122 | // CommitUploadUGC
123 | VodReporter.prototype.onCommit = function (reportObj) {
124 | try {
125 | var customReportData = {
126 | reqType: ReqType.commit,
127 | errCode: 0,
128 | vodErrCode: 0,
129 | errMsg: "",
130 | reqTimeCost: Number(new Date()) - Number(reportObj.requestStartTime),
131 | reqTime: Number(reportObj.requestStartTime)
132 | };
133 | if (reportObj.err) {
134 | customReportData.errCode = 1;
135 | customReportData.vodErrCode = reportObj.err.code;
136 | customReportData.errMsg = reportObj.err.message;
137 | }
138 | if (reportObj.data) {
139 | this.baseReportData.fileId = reportObj.data.fileId;
140 | }
141 | this.report(customReportData);
142 | }
143 | catch (e) {
144 | console.error("onCommit", e);
145 | if (util_1.default.isTest) {
146 | throw e;
147 | }
148 | }
149 | };
150 | VodReporter.prototype.onDone = function (reportObj) {
151 | try {
152 | var customReportData = {
153 | reqType: ReqType.done,
154 | errCode: reportObj.err && reportObj.err.code,
155 | reqTimeCost: Number(new Date()) - Number(reportObj.requestStartTime),
156 | reqTime: Number(reportObj.requestStartTime)
157 | };
158 | this.report(customReportData);
159 | }
160 | catch (e) {
161 | console.error("onDone", e);
162 | if (util_1.default.isTest) {
163 | throw e;
164 | }
165 | }
166 | };
167 | VodReporter.prototype.report = function (reportData) {
168 | reportData = __assign(__assign({}, this.baseReportData), reportData);
169 | this.send(reportData);
170 | };
171 | VodReporter.prototype.send = function (reportData) {
172 | if (util_1.default.isDev || util_1.default.isTest) {
173 | console.log("send reportData", reportData);
174 | return;
175 | }
176 | uploader_1.vodAxios.post(this.reportUrl, reportData);
177 | };
178 | return VodReporter;
179 | }());
180 | exports.VodReporter = VodReporter;
181 | //# sourceMappingURL=vod_reporter.js.map
--------------------------------------------------------------------------------
/lib/src/vod_reporter.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"vod_reporter.js","sourceRoot":"","sources":["../../src/vod_reporter.ts"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vod-js-sdk-v6",
3 | "version": "1.4.12",
4 | "description": "tencent cloud vod js sdk v6",
5 | "main": "lib/src/tc_vod.js",
6 | "unpkg": "dist/vod-js-sdk-v6.js",
7 | "typings": "lib/src/tc_vod.d.ts",
8 | "scripts": {
9 | "test": "cross-env NODE_ENV=test mocha -r espower-typescript/guess -r jsdom-global/register -r test/env test/**/*.test.ts",
10 | "cover": "cross-env NODE_ENV=test nyc mocha -r espower-typescript/guess -r jsdom-global/register -r test/env test/**/*.test.ts",
11 | "dev": "webpack --config webpack.dev.config.js --watch",
12 | "dist": "webpack --config webpack.config.js",
13 | "build": "npm run test && npm run dist && npm run compile",
14 | "compile": "tsc -p tsconfig.json",
15 | "prepublish": "npm run build",
16 | "lint": "tsc --noEmit && eslint 'src/**/*.{js,ts,tsx}' --quiet --fix"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/tencentyun/vod-js-sdk-v6.git"
21 | },
22 | "keywords": [
23 | "tencentcloud",
24 | "sdk",
25 | "vod"
26 | ],
27 | "author": "alsotang ",
28 | "license": "MIT",
29 | "bugs": {
30 | "url": "https://github.com/tencentyun/vod-js-sdk-v6/issues"
31 | },
32 | "homepage": "https://github.com/tencentyun/vod-js-sdk-v6#readme",
33 | "dependencies": {
34 | "axios": "^0.21.1",
35 | "cos-js-sdk-v5": "^1.3.7",
36 | "eventemitter3": "^4.0.7",
37 | "js-sha1": "^0.6.0",
38 | "uuid": "^3.3.2"
39 | },
40 | "devDependencies": {
41 | "@types/mocha": "^5.2.5",
42 | "@types/semver": "^6.0.0",
43 | "@types/sha1": "^1.1.1",
44 | "@types/uuid": "^3.4.4",
45 | "@typescript-eslint/eslint-plugin": "^1.9.0",
46 | "@typescript-eslint/parser": "^1.9.0",
47 | "cross-env": "^6.0.3",
48 | "eslint": "^5.16.0",
49 | "eslint-config-prettier": "^4.3.0",
50 | "eslint-plugin-prettier": "^3.1.0",
51 | "espower-typescript": "^9.0.1",
52 | "jsdom": "^13.1.0",
53 | "jsdom-global": "^3.0.2",
54 | "mm": "^2.4.1",
55 | "mocha": "^5.2.0",
56 | "nyc": "^13.1.0",
57 | "power-assert": "^1.6.1",
58 | "prettier": "^1.17.1",
59 | "semver": "^6.1.1",
60 | "ts-loader": "^5.3.3",
61 | "typescript": "^3.5.3",
62 | "webpack": "^4.28.1",
63 | "webpack-cli": "^3.2.1"
64 | },
65 | "nyc": {
66 | "extension": [
67 | ".ts",
68 | ".tsx"
69 | ],
70 | "include": [
71 | "src"
72 | ],
73 | "reporter": [
74 | "html"
75 | ],
76 | "all": true
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/tc_vod.ts:
--------------------------------------------------------------------------------
1 | import Uploader, { IGetSignature, UploaderOptions } from "./uploader";
2 | import { VodReporter } from "./vod_reporter";
3 |
4 | interface TcVodParams {
5 | getSignature: IGetSignature;
6 | allowReport?: boolean;
7 | appId?: number;
8 | reportId?: string;
9 | enableResume?: boolean;
10 | }
11 | class TcVod {
12 | getSignature: IGetSignature;
13 | allowReport = true; // report sdk status to tencent cloud
14 | appId: number;
15 | reportId: string;
16 | enableResume = true; // resume uploading from break point
17 | constructor(params: TcVodParams) {
18 | this.getSignature = params.getSignature;
19 | if (params.allowReport !== void 0) {
20 | this.allowReport = params.allowReport;
21 | }
22 | if (params.enableResume !== void 0) {
23 | this.enableResume = params.enableResume;
24 | }
25 | this.appId = params.appId;
26 | this.reportId = params.reportId;
27 | }
28 |
29 | upload(params: Omit): Uploader {
30 | const uploaderParams = {
31 | getSignature: this.getSignature,
32 | appId: this.appId,
33 | reportId: this.reportId,
34 | enableResume: this.enableResume,
35 | ...params
36 | };
37 | const uploader = new Uploader(uploaderParams);
38 | if (this.allowReport) {
39 | this.initReporter(uploader);
40 | }
41 | uploader.start();
42 | return uploader;
43 | }
44 |
45 | // report to official report system
46 | initReporter(uploader: Uploader): void {
47 | new VodReporter(uploader);
48 | }
49 | }
50 |
51 | export default TcVod;
52 |
--------------------------------------------------------------------------------
/src/types.d.ts:
--------------------------------------------------------------------------------
1 | export type vodError = Error & {
2 | code?: number;
3 | };
4 |
--------------------------------------------------------------------------------
/src/uploader.ts:
--------------------------------------------------------------------------------
1 | const sha1 = require("js-sha1");
2 | const COS = require("cos-js-sdk-v5");
3 |
4 | import { EventEmitter } from "eventemitter3";
5 | import axios from "axios";
6 | import util, { HOST } from "./util";
7 | import { vodError } from "./types";
8 | import { VodReportEvent } from "./vod_reporter";
9 | import * as uuidv4 from "uuid/v4";
10 |
11 | export const vodAxios = axios.create();
12 |
13 | vodAxios.interceptors.response.use(
14 | function(response) {
15 | return response;
16 | },
17 | function(error) {
18 | if (isNaN(error.code)) {
19 | error.code = 500;
20 | }
21 | return Promise.reject(error);
22 | }
23 | );
24 |
25 | export type IGetSignature = () => Promise;
26 | export interface TcVodFileInfo {
27 | name: string;
28 | type: string;
29 | size: number;
30 | }
31 |
32 | export enum UploaderEvent {
33 | video_progress = "video_progress",
34 | media_progress = "media_progress",
35 |
36 | video_upload = "video_upload",
37 | media_upload = "media_upload",
38 |
39 | cover_progress = "cover_progress",
40 | cover_upload = "cover_upload"
41 | }
42 |
43 | interface IApplyUpload {
44 | signature: string;
45 | vodSessionKey?: string;
46 |
47 | videoName?: string;
48 | videoType?: string;
49 | videoSize?: number;
50 |
51 | coverName?: string;
52 | coverType?: string;
53 | coverSize?: number;
54 |
55 | fileId?: string;
56 | }
57 |
58 | interface IApplyData {
59 | video: {
60 | storageSignature: string;
61 | storagePath: string;
62 | };
63 | cover?: {
64 | storageSignature: string;
65 | storagePath: string;
66 | };
67 | storageAppId: number;
68 | storageBucket: string;
69 | storageRegion: string;
70 | storageRegionV5: string;
71 | domain: string;
72 | vodSessionKey: string;
73 | tempCertificate: {
74 | secretId: string;
75 | secretKey: string;
76 | token: string;
77 | expiredTime: number;
78 | };
79 | appId: number;
80 | timestamp: number;
81 | StorageRegionV5: string;
82 | }
83 |
84 | export interface UploaderOptions {
85 | getSignature: IGetSignature;
86 |
87 | videoFile?: File;
88 | mediaFile?: File;
89 | coverFile?: File;
90 |
91 | videoName?: string;
92 | mediaName?: string;
93 | fileId?: string;
94 |
95 | appId?: number;
96 | reportId?: string;
97 |
98 | applyRequestTimeout?: number;
99 | commitRequestTimeout?: number;
100 | retryDelay?: number;
101 |
102 | enableResume?: boolean;
103 | }
104 |
105 | class Uploader extends EventEmitter implements UploaderOptions {
106 | getSignature: IGetSignature;
107 | videoFile: File;
108 | videoInfo: TcVodFileInfo;
109 | coverFile: File;
110 | coverInfo: TcVodFileInfo;
111 |
112 | cos: any;
113 | taskId: string;
114 | cosAuthTime: number;
115 |
116 | videoName: string;
117 | sessionName: string = "";
118 | vodSessionKey: string = "";
119 | appId: number = 0;
120 | fileId: string;
121 |
122 | reqKey: string = uuidv4();
123 | reportId: string = "";
124 |
125 | // resume from break point
126 | enableResume: boolean = true;
127 |
128 | donePromise: Promise;
129 |
130 | // apply 请求的超时时间
131 | applyRequestTimeout = 5000;
132 | applyRequestRetryCount = 3;
133 |
134 | // commit 请求的超时时间
135 | commitRequestTimeout = 5000;
136 | commitRequestRetryCount = 3;
137 |
138 | // 重试请求的等待时间
139 | retryDelay = 1000;
140 |
141 | // domain
142 | static host = HOST.MAIN;
143 |
144 | constructor(params: UploaderOptions) {
145 | super();
146 | this.validateInitParams(params);
147 |
148 | this.videoFile = params.mediaFile || params.videoFile;
149 | this.getSignature = params.getSignature;
150 |
151 | this.enableResume = params.enableResume;
152 | this.videoName = params.mediaName || params.videoName;
153 | this.coverFile = params.coverFile;
154 | this.fileId = params.fileId;
155 |
156 | this.applyRequestTimeout =
157 | params.applyRequestTimeout || this.applyRequestTimeout;
158 | this.commitRequestTimeout =
159 | params.commitRequestTimeout || this.commitRequestTimeout;
160 | this.retryDelay = params.retryDelay || this.retryDelay;
161 |
162 | // custom report metrics
163 | this.appId = params.appId || this.appId;
164 | this.reportId = params.reportId || this.reportId;
165 |
166 | this.cosAuthTime = 0;
167 | this.genFileInfo();
168 | }
169 |
170 | // set storage
171 | setStorage(name: string, value: string): void {
172 | if (!name) {
173 | return;
174 | }
175 |
176 | const cname = "webugc_" + sha1(name);
177 | try {
178 | localStorage.setItem(cname, value);
179 | } catch (e) {}
180 | }
181 |
182 | // get storage
183 | getStorage(name: string): string {
184 | if (!name) {
185 | return;
186 | }
187 | const cname = "webugc_" + sha1(name);
188 | let result = null;
189 | try {
190 | result = localStorage.getItem(cname);
191 | } catch (e) {}
192 |
193 | return result;
194 | }
195 |
196 | // delete storage
197 | delStorage(name: string): void {
198 | if (!name) {
199 | return;
200 | }
201 | const cname = "webugc_" + sha1(name);
202 | try {
203 | localStorage.removeItem(cname);
204 | } catch (e) {}
205 | }
206 |
207 | // validate init params
208 | validateInitParams(params: UploaderOptions): void {
209 | if (!util.isFunction(params.getSignature)) {
210 | throw new Error("getSignature must be a function");
211 | }
212 | if (params.videoFile && !util.isFile(params.videoFile)) {
213 | throw new Error("videoFile must be a File");
214 | }
215 | }
216 |
217 | genFileInfo(): void {
218 | // video file info
219 | const videoFile = this.videoFile;
220 | if (videoFile) {
221 | const lastDotIndex = videoFile.name.lastIndexOf(".");
222 | let videoName = "";
223 | // if specified, use it.
224 | if (this.videoName) {
225 | if (!util.isString(this.videoName)) {
226 | throw new Error("mediaName must be a string");
227 | } else if (/[:*?<>\"\\/|]/g.test(this.videoName)) {
228 | throw new Error(
229 | 'Cant use these chars in filename: \\ / : * ? " < > |'
230 | );
231 | } else {
232 | videoName = this.videoName;
233 | }
234 | } else {
235 | // else use the meta info of file
236 | videoName = videoFile.name.substring(0, lastDotIndex);
237 | }
238 | this.videoInfo = {
239 | name: videoName,
240 | type: videoFile.name.substring(lastDotIndex + 1).toLowerCase(),
241 | size: videoFile.size
242 | };
243 | this.sessionName += `${videoFile.name}_${videoFile.size};`;
244 | }
245 |
246 | // cover file info
247 | const coverFile = this.coverFile;
248 | if (coverFile) {
249 | const coverName = coverFile.name;
250 | const coverLastDotIndex = coverName.lastIndexOf(".");
251 | this.coverInfo = {
252 | name: coverName.substring(0, coverLastDotIndex),
253 | type: coverName.substring(coverLastDotIndex + 1).toLowerCase(),
254 | size: coverFile.size
255 | };
256 | this.sessionName += `${coverFile.name}_${coverFile.size};`;
257 | }
258 | }
259 |
260 | async applyUploadUGC(retryCount: number = 0): Promise {
261 | const self = this;
262 |
263 | const signature = await this.getSignature();
264 |
265 | let sendParams: IApplyUpload;
266 | const videoInfo = this.videoInfo;
267 | const coverInfo = this.coverInfo;
268 | const vodSessionKey =
269 | this.vodSessionKey ||
270 | (this.enableResume && this.getStorage(this.sessionName));
271 |
272 | // resume from break point
273 | if (vodSessionKey) {
274 | sendParams = {
275 | signature: signature,
276 | vodSessionKey: vodSessionKey
277 | };
278 | } else if (videoInfo) {
279 | sendParams = {
280 | signature: signature,
281 | videoName: videoInfo.name,
282 | videoType: videoInfo.type,
283 | videoSize: videoInfo.size
284 | };
285 | if (coverInfo) {
286 | // upload video together with cover
287 | sendParams.coverName = coverInfo.name;
288 | sendParams.coverType = coverInfo.type;
289 | sendParams.coverSize = coverInfo.size;
290 | }
291 | } else if (this.fileId && coverInfo) {
292 | // alter cover
293 | sendParams = {
294 | signature: signature,
295 | fileId: this.fileId,
296 | coverName: coverInfo.name,
297 | coverType: coverInfo.type,
298 | coverSize: coverInfo.size
299 | };
300 | } else {
301 | throw "Wrong params, please check and try again";
302 | }
303 | const requestStartTime = new Date();
304 |
305 | async function whenError(err?: vodError): Promise {
306 | if (err.code === 500) {
307 | Uploader.host = Uploader.host === HOST.MAIN ? HOST.BACKUP : HOST.MAIN;
308 | }
309 | self.emit(VodReportEvent.report_apply, {
310 | err: err,
311 | requestStartTime: requestStartTime
312 | });
313 | self.delStorage(self.sessionName);
314 | if (self.applyRequestRetryCount == retryCount) {
315 | if (err) {
316 | throw err;
317 | }
318 | throw new Error(`apply upload failed`);
319 | }
320 | await util.delay(self.retryDelay);
321 | return self.applyUploadUGC(retryCount + 1);
322 | }
323 |
324 | let response;
325 | try {
326 | response = await vodAxios.post(
327 | `https://${Uploader.host}/v3/index.php?Action=ApplyUploadUGC`,
328 | sendParams,
329 | {
330 | timeout: this.applyRequestTimeout,
331 | withCredentials: false
332 | }
333 | );
334 | } catch (e) {
335 | return whenError(e);
336 | }
337 |
338 | const applyResult = response.data;
339 |
340 | // all err code https://user-images.githubusercontent.com/1147375/51222454-bf6ef280-1978-11e9-8e33-1b0fdb2fe200.png
341 | if (applyResult.code == 0) {
342 | const applyData = applyResult.data as IApplyData;
343 | const vodSessionKey = applyData.vodSessionKey;
344 | this.setStorage(this.sessionName, vodSessionKey);
345 | this.vodSessionKey = vodSessionKey;
346 | this.appId = applyData.appId;
347 |
348 | this.emit(VodReportEvent.report_apply, {
349 | data: applyData,
350 | requestStartTime: requestStartTime
351 | });
352 | return applyData;
353 | } else {
354 | // return the apply result error info
355 | const err: vodError = new Error(applyResult.message);
356 | err.code = applyResult.code;
357 |
358 | return whenError(err);
359 | }
360 | }
361 |
362 | async uploadToCos(applyData: IApplyData) {
363 | const self = this;
364 |
365 | const cosParam = {
366 | bucket: applyData.storageBucket + "-" + applyData.storageAppId,
367 | region: applyData.storageRegionV5
368 | };
369 |
370 | const cos = new COS({
371 | getAuthorization: async function(options: object, callback: Function) {
372 | const currentTimeStamp = util.getUnix();
373 | const safeExpireTime =
374 | (applyData.tempCertificate.expiredTime - applyData.timestamp) * 0.9;
375 | if (self.cosAuthTime === 0) {
376 | self.cosAuthTime = currentTimeStamp;
377 | } else if (
378 | self.cosAuthTime &&
379 | currentTimeStamp - self.cosAuthTime >= safeExpireTime
380 | ) {
381 | applyData = await self.applyUploadUGC();
382 | self.cosAuthTime = util.getUnix();
383 | }
384 |
385 | callback({
386 | TmpSecretId: applyData.tempCertificate.secretId,
387 | TmpSecretKey: applyData.tempCertificate.secretKey,
388 | XCosSecurityToken: applyData.tempCertificate.token,
389 | StartTime: applyData.timestamp,
390 | ExpiredTime: applyData.tempCertificate.expiredTime
391 | });
392 | }
393 | });
394 | this.cos = cos;
395 |
396 | const uploadCosParams = [];
397 |
398 | if (this.videoFile) {
399 | const cosVideoParam = {
400 | ...cosParam,
401 | file: this.videoFile,
402 | key: applyData.video.storagePath,
403 | onProgress: function(data: any) {
404 | self.emit(UploaderEvent.video_progress, data);
405 | self.emit(UploaderEvent.media_progress, data);
406 | },
407 | onUpload: function(data: any) {
408 | self.emit(UploaderEvent.video_upload, data);
409 | self.emit(UploaderEvent.media_upload, data);
410 | },
411 | onTaskReady: function(taskId: string) {
412 | self.taskId = taskId;
413 | }
414 | };
415 | uploadCosParams.push(cosVideoParam);
416 | }
417 |
418 | if (this.coverFile) {
419 | const cosCoverParam = {
420 | ...cosParam,
421 | file: this.coverFile,
422 | key: applyData.cover.storagePath,
423 | onProgress: function(data: any) {
424 | self.emit(UploaderEvent.cover_progress, data);
425 | },
426 | onUpload: function(data: any) {
427 | self.emit(UploaderEvent.cover_upload, data);
428 | },
429 | onTaskReady: util.noop
430 | };
431 | uploadCosParams.push(cosCoverParam);
432 | }
433 | const requestStartTime = new Date();
434 | const uploadPromises = uploadCosParams.map(uploadCosParam => {
435 | return new Promise(function(resolve, reject) {
436 | cos.sliceUploadFile(
437 | {
438 | Bucket: uploadCosParam.bucket,
439 | Region: uploadCosParam.region,
440 | Key: uploadCosParam.key,
441 | Body: uploadCosParam.file,
442 | onTaskReady: uploadCosParam.onTaskReady,
443 | onProgress: uploadCosParam.onProgress
444 | },
445 | function(err: any, data: any) {
446 | // only report video file
447 | if (uploadCosParam.file === self.videoFile) {
448 | self.emit(VodReportEvent.report_cos_upload, {
449 | err: err,
450 | requestStartTime: requestStartTime
451 | });
452 | }
453 | if (!err) {
454 | uploadCosParam.onUpload(data);
455 | return resolve();
456 | }
457 | self.delStorage(self.sessionName);
458 | if (JSON.stringify(err) === '{"error":"error","headers":{}}') {
459 | return reject(new Error("cors error"));
460 | }
461 | reject(err);
462 | }
463 | );
464 | });
465 | });
466 |
467 | return await Promise.all(uploadPromises);
468 | }
469 |
470 | async commitUploadUGC(retryCount: number = 0) {
471 | const self = this;
472 |
473 | const signature = await this.getSignature();
474 | this.delStorage(this.sessionName);
475 | const vodSessionKey = this.vodSessionKey;
476 |
477 | const requestStartTime = new Date();
478 | async function whenError(err?: vodError): Promise {
479 | if (err.code === 500) {
480 | Uploader.host = Uploader.host === HOST.MAIN ? HOST.BACKUP : HOST.MAIN;
481 | }
482 | self.emit(VodReportEvent.report_commit, {
483 | err: err,
484 | requestStartTime: requestStartTime
485 | });
486 | if (self.commitRequestRetryCount == retryCount) {
487 | if (err) {
488 | throw err;
489 | }
490 | throw new Error("commit upload failed");
491 | }
492 | await util.delay(self.retryDelay);
493 | return self.commitUploadUGC(retryCount + 1);
494 | }
495 |
496 | let response;
497 | try {
498 | response = await vodAxios.post(
499 | `https://${Uploader.host}/v3/index.php?Action=CommitUploadUGC`,
500 | {
501 | signature: signature,
502 | vodSessionKey: vodSessionKey
503 | },
504 | {
505 | timeout: this.commitRequestTimeout,
506 | withCredentials: false
507 | }
508 | );
509 | } catch (e) {
510 | return whenError(e);
511 | }
512 |
513 | const commitResult = response.data;
514 |
515 | if (commitResult.code == 0) {
516 | this.emit(VodReportEvent.report_commit, {
517 | data: commitResult.data,
518 | requestStartTime: requestStartTime
519 | });
520 | return commitResult.data;
521 | } else {
522 | const err: vodError = new Error(commitResult.message);
523 | err.code = commitResult.code;
524 | return whenError(err);
525 | }
526 | }
527 |
528 | start() {
529 | const requestStartTime = new Date();
530 |
531 | this.donePromise = this._start()
532 | .then(doneResult => {
533 | this.emit(VodReportEvent.report_done, {
534 | err: { code: 0 },
535 | requestStartTime: requestStartTime
536 | });
537 | return doneResult;
538 | })
539 | .catch(err => {
540 | this.emit(VodReportEvent.report_done, {
541 | err: {
542 | code: (err && err.code) || util.CLIENT_ERROR_CODE.UPLOAD_FAIL
543 | },
544 | requestStartTime: requestStartTime
545 | });
546 | throw err;
547 | });
548 | }
549 |
550 | async _start() {
551 | const applyData = await this.applyUploadUGC();
552 |
553 | await this.uploadToCos(applyData);
554 |
555 | return await this.commitUploadUGC();
556 | }
557 |
558 | done() {
559 | return this.donePromise;
560 | }
561 |
562 | cancel() {
563 | this.cos.cancelTask(this.taskId);
564 | }
565 | }
566 |
567 | export default Uploader;
568 |
--------------------------------------------------------------------------------
/src/util.ts:
--------------------------------------------------------------------------------
1 | function isFile(v: any): boolean {
2 | return Object.prototype.toString.call(v) == "[object File]";
3 | }
4 |
5 | function isFunction(v: any): boolean {
6 | return typeof v === "function";
7 | }
8 |
9 | function isString(v: any): boolean {
10 | return typeof v === "string";
11 | }
12 |
13 | // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
14 | function noop() {}
15 |
16 | function delay(ms: number) {
17 | return new Promise(resolve => {
18 | setTimeout(() => {
19 | resolve();
20 | }, ms);
21 | });
22 | }
23 |
24 | function getUnix() {
25 | return Math.floor(Date.now() / 1000);
26 | }
27 |
28 | enum CLIENT_ERROR_CODE {
29 | UPLOAD_FAIL = 1
30 | }
31 |
32 | export enum HOST {
33 | MAIN = "vod2.qcloud.com",
34 | BACKUP = "vod2.dnsv1.com"
35 | }
36 |
37 | export default {
38 | isFile,
39 | isFunction,
40 | isString,
41 | noop,
42 | delay,
43 | getUnix,
44 | isTest: process.env.NODE_ENV === "test",
45 | isDev: process.env.NODE_ENV === "development",
46 | CLIENT_ERROR_CODE
47 | };
48 |
--------------------------------------------------------------------------------
/src/vod_reporter.ts:
--------------------------------------------------------------------------------
1 | import Uploader, { vodAxios } from "./uploader";
2 | import * as pkg from "../package.json";
3 | import util from "./util";
4 |
5 | // eslint-disable-next-line @typescript-eslint/no-empty-interface
6 | interface IVodReporter {}
7 |
8 | export enum VodReportEvent {
9 | report_apply = "report_apply",
10 | report_cos_upload = "report_cos_upload",
11 | report_commit = "report_commit",
12 | report_done = "report_done"
13 | }
14 |
15 | enum ReqType {
16 | apply = 10001,
17 | cos_upload = 20001,
18 | commit = 10002,
19 | done = 40001
20 | }
21 |
22 | interface ReportObj {
23 | err: any;
24 | requestStartTime: Date;
25 | data: any;
26 | }
27 |
28 | export class VodReporter {
29 | uploader: Uploader;
30 | options: IVodReporter;
31 |
32 | // only partial data when created
33 | baseReportData: any = {
34 | version: pkg.version,
35 | platform: 3000,
36 | device: navigator.userAgent
37 | };
38 |
39 | reportUrl = "https://vodreport.qcloud.com/ugcupload_new";
40 |
41 | constructor(uploader: Uploader, options?: IVodReporter) {
42 | this.uploader = uploader;
43 | this.options = options;
44 |
45 | this.init();
46 | }
47 |
48 | init() {
49 | this.uploader.on(VodReportEvent.report_apply, this.onApply.bind(this));
50 | this.uploader.on(
51 | VodReportEvent.report_cos_upload,
52 | this.onCosUpload.bind(this)
53 | );
54 | this.uploader.on(VodReportEvent.report_commit, this.onCommit.bind(this));
55 | this.uploader.on(VodReportEvent.report_done, this.onDone.bind(this));
56 | }
57 |
58 | // ApplyUploadUGC
59 | onApply(reportObj: ReportObj) {
60 | try {
61 | const uploader = this.uploader;
62 | if (!uploader.videoFile) {
63 | return;
64 | }
65 | Object.assign(this.baseReportData, {
66 | appId: uploader.appId,
67 | fileSize: uploader.videoFile.size,
68 | fileName: uploader.videoFile.name,
69 | fileType: uploader.videoFile.type,
70 | vodSessionKey: uploader.vodSessionKey,
71 | reqKey: uploader.reqKey,
72 | reportId: uploader.reportId
73 | });
74 |
75 | const customReportData = {
76 | reqType: ReqType.apply,
77 | errCode: 0,
78 | vodErrCode: 0,
79 | errMsg: "",
80 | reqTimeCost: Number(new Date()) - Number(reportObj.requestStartTime),
81 | reqTime: Number(reportObj.requestStartTime)
82 | };
83 | if (reportObj.err) {
84 | customReportData.errCode = 1;
85 | customReportData.vodErrCode = reportObj.err.code;
86 | customReportData.errMsg = reportObj.err.message;
87 | }
88 | if (reportObj.data) {
89 | this.baseReportData.cosRegion = reportObj.data.storageRegionV5;
90 | }
91 | this.report(customReportData);
92 | } catch (e) {
93 | console.error(`onApply`, e);
94 | if (util.isTest) {
95 | throw e;
96 | }
97 | }
98 | }
99 |
100 | // upload to cos
101 | onCosUpload(reportObj: ReportObj) {
102 | try {
103 | const customReportData = {
104 | reqType: ReqType.cos_upload,
105 | errCode: 0,
106 | cosErrCode: "",
107 | errMsg: "",
108 | reqTimeCost: Number(new Date()) - Number(reportObj.requestStartTime),
109 | reqTime: Number(reportObj.requestStartTime)
110 | };
111 | if (reportObj.err) {
112 | customReportData.errCode = 1;
113 | customReportData.cosErrCode = reportObj.err.error
114 | ? reportObj.err.error.Code
115 | : reportObj.err;
116 | if (reportObj.err && reportObj.err.error === "error") {
117 | customReportData.cosErrCode = "cors error";
118 | }
119 | customReportData.errMsg = JSON.stringify(reportObj.err);
120 | }
121 | this.report(customReportData);
122 | } catch (e) {
123 | console.error(`onCosUpload`, e);
124 | if (util.isTest) {
125 | throw e;
126 | }
127 | }
128 | }
129 |
130 | // CommitUploadUGC
131 | onCommit(reportObj: ReportObj) {
132 | try {
133 | const customReportData = {
134 | reqType: ReqType.commit,
135 | errCode: 0,
136 | vodErrCode: 0,
137 | errMsg: "",
138 | reqTimeCost: Number(new Date()) - Number(reportObj.requestStartTime),
139 | reqTime: Number(reportObj.requestStartTime)
140 | };
141 | if (reportObj.err) {
142 | customReportData.errCode = 1;
143 | customReportData.vodErrCode = reportObj.err.code;
144 | customReportData.errMsg = reportObj.err.message;
145 | }
146 | if (reportObj.data) {
147 | this.baseReportData.fileId = reportObj.data.fileId;
148 | }
149 | this.report(customReportData);
150 | } catch (e) {
151 | console.error(`onCommit`, e);
152 | if (util.isTest) {
153 | throw e;
154 | }
155 | }
156 | }
157 |
158 | onDone(reportObj: ReportObj) {
159 | try {
160 | const customReportData = {
161 | reqType: ReqType.done,
162 | errCode: reportObj.err && reportObj.err.code,
163 | reqTimeCost: Number(new Date()) - Number(reportObj.requestStartTime),
164 | reqTime: Number(reportObj.requestStartTime)
165 | };
166 | this.report(customReportData);
167 | } catch (e) {
168 | console.error(`onDone`, e);
169 | if (util.isTest) {
170 | throw e;
171 | }
172 | }
173 | }
174 |
175 | report(reportData: any) {
176 | reportData = { ...this.baseReportData, ...reportData };
177 | this.send(reportData);
178 | }
179 |
180 | send(reportData: any) {
181 | if (util.isDev || util.isTest) {
182 | console.log(`send reportData`, reportData);
183 | return;
184 | }
185 | vodAxios.post(this.reportUrl, reportData);
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/test/env.ts:
--------------------------------------------------------------------------------
1 | import util from "../src/util";
2 |
3 | // though implement `toString`, `Object.prototype.toString.call` would not use it.
4 | util.isFile = function(v: any) {
5 | return String(v) === "[object File]";
6 | };
7 |
--------------------------------------------------------------------------------
/test/tc_vod.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from "assert";
2 | import TcVod from "../src/tc_vod";
3 | import Uploader from "../src/uploader";
4 | import * as mm from "mm";
5 |
6 | describe("tc_vod.test.ts", () => {
7 | afterEach(function() {
8 | mm.restore();
9 | });
10 |
11 | describe("#upload", () => {
12 | it("should return a Promise", async () => {
13 | const tcVod = new TcVod({
14 | getSignature: (() => {}) as any
15 | });
16 | mm(Uploader.prototype, "_start", () => {
17 | return Promise.resolve(1);
18 | });
19 | const uploader = tcVod.upload({} as any);
20 | const doneResult = await uploader.done();
21 | assert(doneResult === 1);
22 | });
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/test/uploader.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from "assert";
2 | import Uploader, { UploaderEvent } from "../src/uploader";
3 | import util from "../src/util";
4 | import * as mm from "mm";
5 | import { vodAxios as axios } from "../src/uploader";
6 | const COS = require("cos-js-sdk-v5");
7 |
8 | const fakeGetSignature = async () => {
9 | return "fakeGetSignature";
10 | };
11 | const fakeMediaFile: File = ({
12 | lastModified: null,
13 | name: "vv.dd.mp4",
14 | size: 100,
15 | type: "video/mp4",
16 | slice: null,
17 | toString() {
18 | return "[object File]";
19 | }
20 | } as any) as File;
21 | describe("uploader.test.ts", () => {
22 | afterEach(function() {
23 | mm.restore();
24 | });
25 | describe("#new", function() {
26 | it("should accept getSignature and mediaFile", () => {
27 | const uploader = new Uploader({
28 | getSignature: fakeGetSignature,
29 | mediaFile: fakeMediaFile
30 | });
31 | });
32 |
33 | it("should fail when init params wrong", () => {
34 | // without signature
35 | assert.throws(() => {
36 | const uploader = new Uploader({
37 | getSignature: null
38 | });
39 | }, /getSignature must be a function/);
40 | });
41 | });
42 |
43 | describe("#genFileInfo", () => {
44 | it("should gen file info", () => {
45 | const uploader = new Uploader({
46 | getSignature: fakeGetSignature,
47 | mediaFile: fakeMediaFile
48 | });
49 | assert(uploader.videoInfo.name == "vv.dd");
50 | assert(uploader.videoInfo.type == "mp4");
51 | assert(uploader.videoInfo.size == 100);
52 | });
53 |
54 | it("should use `mediaName` param", () => {
55 | const uploader = new Uploader({
56 | getSignature: fakeGetSignature,
57 | mediaFile: fakeMediaFile,
58 | mediaName: "custom_video_name"
59 | });
60 | assert(uploader.videoName == "custom_video_name");
61 | });
62 |
63 | it("should throw when invalid `mediaName`", () => {
64 | assert.throws(() => {
65 | const uploader = new Uploader({
66 | getSignature: fakeGetSignature,
67 | mediaFile: fakeMediaFile,
68 | mediaName: 11 as any
69 | });
70 | }, /mediaName must be a string/);
71 |
72 | assert.throws(() => {
73 | const uploader = new Uploader({
74 | getSignature: fakeGetSignature,
75 | mediaFile: fakeMediaFile,
76 | mediaName: "*"
77 | });
78 | }, /Cant use these chars in filename/);
79 | });
80 | });
81 |
82 | describe("#start", () => {
83 | it("should start", async function() {
84 | // 各函数需要被调用的次数
85 | const shouldCalled: any = {
86 | getSignature: 2,
87 | applyUploadUGC: 1,
88 | cosSuccess: 1,
89 | cosCoverSuccess: 1
90 | };
91 |
92 | const uploader = new Uploader({
93 | getSignature: () => {
94 | shouldCalled.getSignature--;
95 | return fakeGetSignature();
96 | },
97 | mediaFile: fakeMediaFile,
98 | coverFile: fakeMediaFile
99 | });
100 | uploader.on(UploaderEvent.video_upload, () => {
101 | shouldCalled.cosSuccess--;
102 | });
103 | uploader.on(UploaderEvent.cover_upload, () => {
104 | shouldCalled.cosCoverSuccess--;
105 | });
106 |
107 | // 拦截 applyUploadUGC 中的post请求
108 | const old_applyUploadUGC = uploader.applyUploadUGC;
109 | mm(uploader, "applyUploadUGC", function() {
110 | shouldCalled.applyUploadUGC--;
111 | mm(axios, "post", () => {
112 | return {
113 | data: {
114 | code: 0,
115 | message: "成功",
116 | data: {
117 | video: {
118 | storageSignature:
119 | "bWcRMHMhwcaYQykMVNx0izvERAdhPTEwMDIyODUzJmI9ZmFlZWQ0NTZ2b2RjcTE0MDAxNzAwMzQmaz1BS0lESVdlN0F0STEwUFFrbThSRURsNFVPN0k2bXluNk5ERjcmZT0xNTQ3ODkyMTc1JnQ9MTU0NzcxOTM3NSZyPTI2NzAxNTYxODAmZj0vMTAwMjI4NTMvZmFlZWQ0NTZ2b2RjcTE0MDAxNzAwMzQvZmFlZWQ0NTZ2b2RjcTE0MDAxNzAwMzQvN2Y1MWQ5NmI1Mjg1ODkwNzg0NDE4NjA1MTIzL3gyZVdGWFBmdE1FQS5tcDQ=",
120 | storagePath:
121 | "/faeed456vodcq1400170034/7f51d96b5285890784418605123/x2eWFXPftMEA.mp4"
122 | },
123 | cover: {
124 | storageSignature:
125 | "VgnnV+kwG8p7LvME+Thc2aaiIO5hPTEwMDIyODUzJmI9ZmFlZWQ0NTZ2b2RjcTE0MDAxNzAwMzQmaz1BS0lESVdlN0F0STEwUFFrbThSRURsNFVPN0k2bXluNk5ERjcmZT0xNTQ3ODkyMTc1JnQ9MTU0NzcxOTM3NSZyPTE0NzAzNDkzNjkmZj0vMTAwMjI4NTMvZmFlZWQ0NTZ2b2RjcTE0MDAxNzAwMzQvZmFlZWQ0NTZ2b2RjcTE0MDAxNzAwMzQvN2Y1MWQ5NmI1Mjg1ODkwNzg0NDE4NjA1MTIzLzUyODU4OTA3ODQ0MTg2MDUxMjQucG5n",
126 | storagePath:
127 | "/faeed456vodcq1400170034/7f51d96b5285890784418605123/5285890784418605124.png"
128 | },
129 | storageAppId: 10022853,
130 | storageBucket: "faeed456vodcq1400170034",
131 | storageRegion: "cq",
132 | storageRegionV5: "ap-chongqing",
133 | domain: "vod2.qcloud.com",
134 | vodSessionKey:
135 | "3FEmq9DWHl1xF819mM6j0fyDQDSON8VtwN/RTrl/9m49AEEWV9jV5txk3AckBj1lkl3EkTMVx1ah/wOuKPElzHG4gHwRVPpge+UZ7sdmqvmQJ9bhLhiAZDTDDMVlSW6j2a4bIIUDI7erahcpKs/oh0koMLcoErCFBr+nHhFKT2qfIyc8b+izX5GBFIkXuLzDGMjTnYuQAomqeHYanuP5dns0+7CGkK26M4d9n0VU7DEQ4GEweORsIQCqsQT6+0DLnZ9qFO4mBeVOb6Ro5qGIi3uhq2AFmMQmrMXZfdSvcdnoLYPmDxvM8inrhri0CHBIq6UyJqsKmsYU0ufHkc2S3feaVRHxM9ahqRK2iNXtOche9wH2dFJ+eX7OQ/Vek75rKlpCUE68peHv9KeNf5/7y9buUXeguBYC74pU+oJ2ffu/INgkFkP9tdw4EgkkRyqsQPIWbuFrXXy5fyPzCoMgDnH0QgzUsHGgKTkk4UjvLdXZR21soD6pxcdXj1n/VHyljouY8uMz5nvg3KTAL9ze73+MJvuD4LUIMahagY5MhiHbMCGHXOVG6BDq6WQr9PjkOxH3PteeekyWvxdaxc/icVvQO+2ytIX2/P/V91eBs9qmxpYvD2Mnf1HkeANPCRBIpvLhBRHRGPKN9tVg1CFcBRr6Ruxr5rs2E0eDPhy6s/5RwRcf2CcfnOTKC+jamY/qhgc1Kl3sLh7JkhM3Onwxi+i5OIdaOvdS2NYst6Xn0tQFDT+vOK3n45k4HTYK6LdaJZAqjmtBHNBeohp/JM/7ZiAcNoCsR4FPaTH9Y1GAGYZHC0nw/E932tYrg26QsyFeAOWhW6xkdk+TwMtV92bQu8DmvxojyQZlDJgWjJPa+1B9B9C7OtbYeUZ5+SBC+Z23YYplFkKyBEWC4j+x52R+g463In9DFsZdRb2NCmBGBC8CARgQypTZ4Q==",
136 | // 测试参数tempCertificate需要从demo中的ApplyUploadUGC接口获取
137 | // demo地址https://tencentyun.github.io/vod-js-sdk-v6/
138 | tempCertificate: {
139 | secretId: "",
140 | secretKey: "",
141 | token: "",
142 | expiredTime: 1547719375,
143 | },
144 | appId: 1400170034,
145 | timestamp: 1547719375,
146 | StorageRegionV5: "ap-chongqing"
147 | }
148 | }
149 | };
150 | });
151 | return old_applyUploadUGC.apply(uploader, arguments);
152 | });
153 |
154 | // 拦截 uploadToCos 中的上传请求
155 | const old_uploadToCos = uploader.uploadToCos;
156 | mm(uploader, "uploadToCos", function() {
157 | mm(COS.prototype, "sliceUploadFile", function(
158 | sliceParams: any,
159 | callback: Function
160 | ) {
161 | // {
162 | // Bucket: uploadCosParam.bucket,
163 | // Region: uploadCosParam.region,
164 | // Key: uploadCosParam.key,
165 | // Body: uploadCosParam.file,
166 | // onTaskReady: uploadCosParam.onTaskReady,
167 | // onProgress: uploadCosParam.onProgress,
168 | // }
169 | assert(util.isString(sliceParams.Bucket));
170 | assert(util.isString(sliceParams.Region));
171 | assert(util.isString(sliceParams.Key));
172 | assert(util.isFile(sliceParams.Body));
173 | assert(util.isFunction(sliceParams.onTaskReady));
174 | assert(util.isFunction(sliceParams.onProgress));
175 | callback();
176 | });
177 | return old_uploadToCos.apply(uploader, arguments);
178 | });
179 |
180 | // 拦截 commitUploadUGC 中的post请求
181 | const old_commitUploadUGC = uploader.commitUploadUGC;
182 | mm(uploader, "commitUploadUGC", function() {
183 | mm(axios, "post", () => {
184 | return {
185 | data: {
186 | code: 0,
187 | message: "成功",
188 | data: {
189 | video: {
190 | url:
191 | "http://1400170034.vod2.myqcloud.com/faeed456vodcq1400170034/7f51d96b5285890784418605123/x2eWFXPftMEA.mp4",
192 | verify_content:
193 | "EmqHd4LLop2dL692wAoVl5FshQVFeHBUaW1lPTE1NDc3MjI5ODYmRmlsZUlkPTUyODU4OTA3ODQ0MTg2MDUxMjM="
194 | },
195 | cover: {
196 | url:
197 | "http://1400170034.vod2.myqcloud.com/faeed456vodcq1400170034/7f51d96b5285890784418605123/5285890784418605124.png",
198 | verify_content:
199 | "WIqkMGzIaOl8try34aPB+JklA4xFeHBUaW1lPTE1NDc3MjI5ODYmRmlsZUlkPTUyODU4OTA3ODQ0MTg2MDUxMjQ="
200 | },
201 | fileId: "5285890784418605123"
202 | }
203 | }
204 | };
205 | });
206 | return old_commitUploadUGC.call(uploader, arguments);
207 | });
208 |
209 | uploader.start();
210 | const doneResult = await uploader.done();
211 |
212 | // 开始校验各部分的工作情况
213 | assert(util.isString(doneResult.video.url));
214 |
215 | for (const key in shouldCalled) {
216 | assert(shouldCalled[key] == 0);
217 | }
218 | });
219 | });
220 |
221 | describe("#applyUploadUGC", () => {
222 | it("should retry", async () => {
223 | const uploader = new Uploader({
224 | getSignature: fakeGetSignature,
225 | mediaFile: fakeMediaFile
226 | });
227 | uploader.retryDelay = 100; // dont wait too long
228 |
229 | let applyUploadUGCCalled = 0;
230 |
231 | mm(axios, "post", () => {
232 | applyUploadUGCCalled++;
233 | throw new Error("fake post error");
234 | });
235 | await assert.rejects(async () => {
236 | await uploader.applyUploadUGC();
237 | }, /fake post error/);
238 | assert(applyUploadUGCCalled == 4);
239 | });
240 | });
241 | });
242 |
--------------------------------------------------------------------------------
/test/vod_reporter.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from "assert";
2 | import { VodReporter, VodReportEvent } from "../src/vod_reporter";
3 | import Uploader from "../src/uploader";
4 | import * as semver from "semver";
5 |
6 | const device = window.navigator.userAgent;
7 |
8 | function genUploader() {
9 | const fakeGetSignature = async () => {
10 | return "fakeGetSignature";
11 | };
12 | const fakeMediaFile: File = ({
13 | lastModified: null,
14 | name: "vv.dd.mp4",
15 | size: 100,
16 | type: "video/mp4",
17 | slice: null,
18 | toString() {
19 | return "[object File]";
20 | }
21 | } as any) as File;
22 | const uploader = new Uploader({
23 | getSignature: fakeGetSignature,
24 | mediaFile: fakeMediaFile,
25 | reportId: "12345"
26 | });
27 | return uploader;
28 | }
29 |
30 | function checkAndDelCommonProperty(reportData: any, requestStartTime: Date) {
31 | assert.strictEqual(reportData.reqTime, Number(requestStartTime));
32 | delete reportData.reqTime;
33 | assert.ok(reportData.reqTimeCost < 600);
34 | delete reportData.reqTimeCost;
35 | assert.ok(semver.valid(reportData.version));
36 | delete reportData.version;
37 |
38 | assert.ok(/\w+-\w+-\w+-\w+-\w+/.test(reportData.reqKey));
39 | delete reportData.reqKey;
40 | }
41 |
42 | describe("vod_reporter.test.ts", () => {
43 | const uploader = genUploader();
44 | const vodReporter = new VodReporter(uploader);
45 | describe("apply", () => {
46 | it("should report apply", () => {
47 | const requestStartTime = new Date(Number(new Date()) - 500);
48 |
49 | vodReporter.send = reportData => {
50 | checkAndDelCommonProperty(reportData, requestStartTime);
51 |
52 | assert.deepStrictEqual(reportData, {
53 | platform: 3000,
54 | reportId: "12345",
55 | device:
56 | device ||
57 | "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/13.2.0",
58 | errCode: 0,
59 | appId: 0,
60 | fileSize: 100,
61 | fileName: "vv.dd.mp4",
62 | fileType: "video/mp4",
63 | vodSessionKey: "",
64 | cosRegion: "ap-chongqing",
65 | reqType: 10001,
66 | vodErrCode: 0,
67 | errMsg: ""
68 | });
69 | };
70 | uploader.emit(VodReportEvent.report_apply, {
71 | data: {
72 | storageRegionV5: "ap-chongqing"
73 | },
74 | requestStartTime: requestStartTime
75 | });
76 | });
77 |
78 | it("should report apply error", () => {
79 | const uploader = genUploader();
80 | const vodReporter = new VodReporter(uploader);
81 | const requestStartTime = new Date(Number(new Date()) - 500);
82 |
83 | vodReporter.send = reportData => {
84 | checkAndDelCommonProperty(reportData, requestStartTime);
85 |
86 | assert.deepStrictEqual(reportData, {
87 | platform: 3000,
88 | reportId: "12345",
89 | device:
90 | device ||
91 | "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/13.2.0",
92 | errCode: 1,
93 | appId: 0,
94 | fileSize: 100,
95 | fileName: "vv.dd.mp4",
96 | fileType: "video/mp4",
97 | vodSessionKey: "",
98 | reqType: 10001,
99 | vodErrCode: 10004,
100 | errMsg: "ugc upload | invalid signature"
101 | });
102 | };
103 | uploader.emit(VodReportEvent.report_apply, {
104 | err: { code: 10004, message: "ugc upload | invalid signature" },
105 | requestStartTime: requestStartTime
106 | });
107 | });
108 | });
109 |
110 | describe("cos upload", () => {
111 | it("should report cos upload", () => {
112 | const requestStartTime = new Date(Number(new Date()) - 500);
113 |
114 | vodReporter.send = reportData => {
115 | checkAndDelCommonProperty(reportData, requestStartTime);
116 |
117 | assert.deepStrictEqual(reportData, {
118 | platform: 3000,
119 | reportId: "12345",
120 | device:
121 | device ||
122 | "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/13.2.0",
123 | errCode: 0,
124 | appId: 0,
125 | fileSize: 100,
126 | fileName: "vv.dd.mp4",
127 | fileType: "video/mp4",
128 | vodSessionKey: "",
129 | cosRegion: "ap-chongqing",
130 | reqType: 20001,
131 | cosErrCode: "",
132 | errMsg: ""
133 | });
134 | };
135 | uploader.emit(VodReportEvent.report_cos_upload, {
136 | err: null,
137 | requestStartTime: requestStartTime
138 | });
139 | });
140 | });
141 |
142 | describe("commit", () => {
143 | it("should report commit", () => {
144 | const requestStartTime = new Date(Number(new Date()) - 500);
145 |
146 | vodReporter.send = reportData => {
147 | checkAndDelCommonProperty(reportData, requestStartTime);
148 |
149 | assert.deepStrictEqual(reportData, {
150 | platform: 3000,
151 | reportId: "12345",
152 | device:
153 | device ||
154 | "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/13.2.0",
155 | errCode: 0,
156 | appId: 0,
157 | fileSize: 100,
158 | fileName: "vv.dd.mp4",
159 | fileType: "video/mp4",
160 | vodSessionKey: "",
161 | cosRegion: "ap-chongqing",
162 | reqType: 10002,
163 | vodErrCode: 0,
164 | errMsg: "",
165 | fileId: "20190606"
166 | });
167 | };
168 | uploader.emit(VodReportEvent.report_commit, {
169 | data: {
170 | fileId: "20190606"
171 | },
172 | requestStartTime: requestStartTime
173 | });
174 | });
175 |
176 | it("should report commit error", () => {
177 | const requestStartTime = new Date(Number(new Date()) - 500);
178 |
179 | vodReporter.send = reportData => {
180 | checkAndDelCommonProperty(reportData, requestStartTime);
181 |
182 | assert.deepStrictEqual(reportData, {
183 | platform: 3000,
184 | reportId: "12345",
185 | device:
186 | device ||
187 | "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/13.2.0",
188 | errCode: 1,
189 | appId: 0,
190 | fileSize: 100,
191 | fileName: "vv.dd.mp4",
192 | fileType: "video/mp4",
193 | vodSessionKey: "",
194 | reqType: 10002,
195 | vodErrCode: 10004,
196 | errMsg: "ugc upload | invalid signature",
197 | fileId: "20190606",
198 | cosRegion: "ap-chongqing"
199 | });
200 | };
201 | uploader.emit(VodReportEvent.report_commit, {
202 | err: { code: 10004, message: "ugc upload | invalid signature" },
203 | requestStartTime: requestStartTime
204 | });
205 | });
206 | });
207 | });
208 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "lib",
4 | "noImplicitAny": true,
5 | "noImplicitThis": true,
6 | "target": "es5",
7 | "sourceMap": true,
8 | "declaration": true,
9 | "resolveJsonModule": true,
10 | "lib": [
11 | "dom",
12 | "es2015",
13 | "scripthost",
14 | "es2015.promise"
15 | ]
16 | },
17 | "include": ["src"]
18 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | module.exports = {
4 | mode: "production",
5 | devtool: "source-map",
6 | entry: "./src/tc_vod.ts",
7 | module: {
8 | rules: [
9 | {
10 | test: /\.ts$/,
11 | use: "ts-loader",
12 | exclude: /node_modules/
13 | }
14 | ]
15 | },
16 | resolve: {
17 | extensions: [".ts", ".js"]
18 | },
19 | optimization: {
20 | // 这个选项开启后会影响 ts sourcemap 的生成,调试了半天也不懂是为什么。
21 | occurrenceOrder: false
22 | },
23 | output: {
24 | filename: "vod-js-sdk-v6.js",
25 | path: path.resolve(__dirname, "dist"),
26 | library: "TcVod",
27 | libraryTarget: "umd"
28 | },
29 | plugins: []
30 | };
31 |
--------------------------------------------------------------------------------
/webpack.dev.config.js:
--------------------------------------------------------------------------------
1 | const webpackProdConfig = require("./webpack.config");
2 |
3 | const webpackDevConfig = { ...webpackProdConfig, mode: "development" };
4 |
5 | module.exports = webpackDevConfig;
6 |
--------------------------------------------------------------------------------