roy-image-repository 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +4 -2
- package/dist/roy-image-repository.iife.js +1 -1
- package/dist/roy-image-repository.js +148 -57
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export declare class ImageRepository {
|
|
|
24
24
|
private readonly videoUrl;
|
|
25
25
|
private static _repositories;
|
|
26
26
|
private _isInited;
|
|
27
|
+
private _isPlaying;
|
|
27
28
|
private _videoElement?;
|
|
28
29
|
/**
|
|
29
30
|
* 视频DOM元素,使用它来渲染画布
|
|
@@ -35,11 +36,12 @@ export declare class ImageRepository {
|
|
|
35
36
|
static getRepository(videoUrl: string): Promise<ImageRepository>;
|
|
36
37
|
init(): Promise<void>;
|
|
37
38
|
uninit(): void;
|
|
39
|
+
private _taskQueue;
|
|
38
40
|
/**
|
|
39
|
-
*
|
|
41
|
+
* 根据传入的微秒时间戳,获取指定位置的帧图片,直接返回切换到对应帧的视频对象,在并发调用的情况下,内部通过统一的串行队列,将调用的结果按照顺序返回
|
|
40
42
|
* @param timstampInMicroseconds 微秒时间戳
|
|
41
43
|
*/
|
|
42
|
-
getImage(timstampInMicroseconds: number): Promise<
|
|
44
|
+
getImage(timstampInMicroseconds: number): Promise<HTMLVideoElement>;
|
|
43
45
|
/**
|
|
44
46
|
* 开始播放连续帧图片
|
|
45
47
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var royImageRepository=(function(
|
|
1
|
+
var royImageRepository=(function(o){"use strict";async function u(r){return new Promise((e,t)=>{const i=document.createElement("video");i.muted=!0,i.crossOrigin="anonymous",i.preload="metadata",i.onloadedmetadata=()=>{i.width=i.videoWidth,i.height=i.videoHeight,e(i)},i.onerror=s=>{console.log("video load error",s),t(s)},i.src=r})}function l(r){return{all:r=r||new Map,on:function(e,t){var i=r.get(e);i?i.push(t):r.set(e,[t])},off:function(e,t){var i=r.get(e);i&&(t?i.splice(i.indexOf(t)>>>0,1):r.set(e,[]))},emit:function(e,t){var i=r.get(e);i&&i.slice().map(function(s){s(t)}),(i=r.get("*"))&&i.slice().map(function(s){s(e,t)})}}}function a(r){return r/1e6}function h(r){return r*1e6}class d{queue=[];running=!1;taskId=0;stopped=!1;enqueue(e){return this.stopped?Promise.reject(new Error("Queue has been stopped")):new Promise((t,i)=>{const s={id:++this.taskId,task:e,resolve:t,reject:i};this.queue.push(s),this.process()})}async process(){if(!this.running&&this.queue.length!==0){for(this.running=!0;this.queue.length>0;){const e=this.queue.shift();if(!e)break;try{const t=await e.task();e.resolve(t)}catch(t){e.reject(t)}}this.running=!1}}clear(e="Task cleared"){for(const t of this.queue)t.reject(new Error(e));this.queue=[]}stop(){this.stopped=!0,this.clear("Queue stopped")}isRunning(){return this.running}size(){return this.queue.length}}class n{constructor(e){this.videoUrl=e}static _repositories={};_isInited=!1;_isPlaying=!1;_videoElement;get videoElement(){if(!this._videoElement)throw new Error("image repository is not inited!");return this._videoElement}_requestVideoFrameCallbackId;_emitter=l();static getRepository(e){const t=e.toLowerCase().trim();return this._repositories[t]||(this._repositories[t]=(async()=>{const i=new n(t);return await i.init(),i})()),this._repositories[t]}async init(){this._isInited||(this._isInited=!0,this._videoElement=await u(this.videoUrl))}uninit(){this._isInited&&(this._isInited=!1,this._isPlaying&&this.stop(),this._taskQueue.stop(),this._videoElement=void 0,this._emitter.all.clear())}_taskQueue=new d;async getImage(e){return await this._taskQueue.enqueue(()=>new Promise((t,i)=>{if(!this._videoElement){i(new Error("image repository is not inited!"));return}if(this._isPlaying){i(new Error("image repository is playing!"));return}this._videoElement.requestVideoFrameCallback(()=>{t(this.videoElement)}),this._videoElement.currentTime=a(e)}))}async play(){if(!this._videoElement)throw new Error("image repository is not inited!");if(this._isPlaying)throw new Error("image repository is playing!");try{this._isPlaying=!0;const e=(t,i)=>{this._emitter.emit("requestFrame",{frameTimestampInMicroseconds:h(i.mediaTime),originalEvent:{now:t,metadata:i}}),this._requestVideoFrameCallbackId=this._videoElement.requestVideoFrameCallback(e)};return this._requestVideoFrameCallbackId=this._videoElement.requestVideoFrameCallback(e),await this._videoElement.play()}catch(e){throw this._isPlaying=!1,e}}stop(){if(!this._videoElement)throw new Error("image repository is not inited!");if(!this._isPlaying)throw new Error("image repository is not playing");this.pause(),this._videoElement.currentTime=a(0)}pause(){if(!this._videoElement)throw new Error("image repository is not inited!");if(!this._isPlaying)throw new Error("image repository is not playing");try{this._isPlaying=!1,this._requestVideoFrameCallbackId&&(this._videoElement.cancelVideoFrameCallback(this._requestVideoFrameCallbackId),this._requestVideoFrameCallbackId=void 0),this._videoElement.pause()}catch(e){throw this._isPlaying=!0,e}}on(e,t){return this._emitter.on(e,t),{off:()=>{this._emitter.off(e,t)}}}}return o.ImageRepository=n,Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}),o})({});
|
|
@@ -1,41 +1,106 @@
|
|
|
1
|
-
async function a(
|
|
2
|
-
return new Promise((
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
},
|
|
7
|
-
console.log("video load error",
|
|
8
|
-
},
|
|
1
|
+
async function a(r) {
|
|
2
|
+
return new Promise((e, t) => {
|
|
3
|
+
const i = document.createElement("video");
|
|
4
|
+
i.muted = !0, i.crossOrigin = "anonymous", i.preload = "metadata", i.onloadedmetadata = () => {
|
|
5
|
+
i.width = i.videoWidth, i.height = i.videoHeight, e(i);
|
|
6
|
+
}, i.onerror = (s) => {
|
|
7
|
+
console.log("video load error", s), t(s);
|
|
8
|
+
}, i.src = r;
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
|
-
function
|
|
12
|
-
return { all:
|
|
13
|
-
var
|
|
14
|
-
|
|
15
|
-
}, off: function(
|
|
16
|
-
var
|
|
17
|
-
|
|
18
|
-
}, emit: function(
|
|
19
|
-
var
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}), (
|
|
23
|
-
|
|
11
|
+
function u(r) {
|
|
12
|
+
return { all: r = r || /* @__PURE__ */ new Map(), on: function(e, t) {
|
|
13
|
+
var i = r.get(e);
|
|
14
|
+
i ? i.push(t) : r.set(e, [t]);
|
|
15
|
+
}, off: function(e, t) {
|
|
16
|
+
var i = r.get(e);
|
|
17
|
+
i && (t ? i.splice(i.indexOf(t) >>> 0, 1) : r.set(e, []));
|
|
18
|
+
}, emit: function(e, t) {
|
|
19
|
+
var i = r.get(e);
|
|
20
|
+
i && i.slice().map(function(s) {
|
|
21
|
+
s(t);
|
|
22
|
+
}), (i = r.get("*")) && i.slice().map(function(s) {
|
|
23
|
+
s(e, t);
|
|
24
24
|
});
|
|
25
25
|
} };
|
|
26
26
|
}
|
|
27
|
-
function
|
|
28
|
-
return
|
|
27
|
+
function n(r) {
|
|
28
|
+
return r / 1e6;
|
|
29
29
|
}
|
|
30
|
-
function l(
|
|
31
|
-
return
|
|
30
|
+
function l(r) {
|
|
31
|
+
return r * 1e6;
|
|
32
32
|
}
|
|
33
|
-
class
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
class h {
|
|
34
|
+
queue = [];
|
|
35
|
+
running = !1;
|
|
36
|
+
taskId = 0;
|
|
37
|
+
stopped = !1;
|
|
38
|
+
/**
|
|
39
|
+
* 添加任务(泛型自动推导)
|
|
40
|
+
*/
|
|
41
|
+
enqueue(e) {
|
|
42
|
+
return this.stopped ? Promise.reject(new Error("Queue has been stopped")) : new Promise((t, i) => {
|
|
43
|
+
const s = {
|
|
44
|
+
id: ++this.taskId,
|
|
45
|
+
task: e,
|
|
46
|
+
resolve: t,
|
|
47
|
+
reject: i
|
|
48
|
+
};
|
|
49
|
+
this.queue.push(s), this.process();
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 串行执行核心逻辑
|
|
54
|
+
*/
|
|
55
|
+
async process() {
|
|
56
|
+
if (!this.running && this.queue.length !== 0) {
|
|
57
|
+
for (this.running = !0; this.queue.length > 0; ) {
|
|
58
|
+
const e = this.queue.shift();
|
|
59
|
+
if (!e) break;
|
|
60
|
+
try {
|
|
61
|
+
const t = await e.task();
|
|
62
|
+
e.resolve(t);
|
|
63
|
+
} catch (t) {
|
|
64
|
+
e.reject(t);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
this.running = !1;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 清空未执行任务
|
|
72
|
+
*/
|
|
73
|
+
clear(e = "Task cleared") {
|
|
74
|
+
for (const t of this.queue)
|
|
75
|
+
t.reject(new Error(e));
|
|
76
|
+
this.queue = [];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* 停止队列(不可恢复)
|
|
80
|
+
*/
|
|
81
|
+
stop() {
|
|
82
|
+
this.stopped = !0, this.clear("Queue stopped");
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 当前是否正在执行
|
|
86
|
+
*/
|
|
87
|
+
isRunning() {
|
|
88
|
+
return this.running;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* 当前等待数量
|
|
92
|
+
*/
|
|
93
|
+
size() {
|
|
94
|
+
return this.queue.length;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
class o {
|
|
98
|
+
constructor(e) {
|
|
99
|
+
this.videoUrl = e;
|
|
36
100
|
}
|
|
37
101
|
static _repositories = {};
|
|
38
102
|
_isInited = !1;
|
|
103
|
+
_isPlaying = !1;
|
|
39
104
|
_videoElement;
|
|
40
105
|
/**
|
|
41
106
|
* 视频DOM元素,使用它来渲染画布
|
|
@@ -46,36 +111,39 @@ class n {
|
|
|
46
111
|
return this._videoElement;
|
|
47
112
|
}
|
|
48
113
|
_requestVideoFrameCallbackId;
|
|
49
|
-
_emitter =
|
|
50
|
-
static
|
|
51
|
-
const t =
|
|
52
|
-
return this._repositories[t] || (this._repositories[t] =
|
|
114
|
+
_emitter = u();
|
|
115
|
+
static getRepository(e) {
|
|
116
|
+
const t = e.toLowerCase().trim();
|
|
117
|
+
return this._repositories[t] || (this._repositories[t] = (async () => {
|
|
118
|
+
const i = new o(t);
|
|
119
|
+
return await i.init(), i;
|
|
120
|
+
})()), this._repositories[t];
|
|
53
121
|
}
|
|
54
122
|
async init() {
|
|
55
|
-
|
|
56
|
-
return;
|
|
57
|
-
this._isInited = !0, this._videoElement = await a(this.videoUrl);
|
|
58
|
-
const i = (t, e) => {
|
|
59
|
-
this._emitter.emit("requestFrame", {
|
|
60
|
-
frameTimestampInMicroseconds: l(e.mediaTime),
|
|
61
|
-
originalEvent: { now: t, metadata: e }
|
|
62
|
-
}), this._requestVideoFrameCallbackId = this._videoElement.requestVideoFrameCallback(i);
|
|
63
|
-
};
|
|
64
|
-
this._requestVideoFrameCallbackId = this._videoElement.requestVideoFrameCallback(i);
|
|
123
|
+
this._isInited || (this._isInited = !0, this._videoElement = await a(this.videoUrl));
|
|
65
124
|
}
|
|
66
125
|
uninit() {
|
|
67
|
-
this._isInited && (this._isInited = !1, this.
|
|
68
|
-
this._requestVideoFrameCallbackId
|
|
69
|
-
), this._requestVideoFrameCallbackId = void 0), this._videoElement = void 0, this._emitter.all.clear());
|
|
126
|
+
this._isInited && (this._isInited = !1, this._isPlaying && this.stop(), this._taskQueue.stop(), this._videoElement = void 0, this._emitter.all.clear());
|
|
70
127
|
}
|
|
128
|
+
_taskQueue = new h();
|
|
71
129
|
/**
|
|
72
|
-
*
|
|
130
|
+
* 根据传入的微秒时间戳,获取指定位置的帧图片,直接返回切换到对应帧的视频对象,在并发调用的情况下,内部通过统一的串行队列,将调用的结果按照顺序返回
|
|
73
131
|
* @param timstampInMicroseconds 微秒时间戳
|
|
74
132
|
*/
|
|
75
|
-
async getImage(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
133
|
+
async getImage(e) {
|
|
134
|
+
return await this._taskQueue.enqueue(() => new Promise((t, i) => {
|
|
135
|
+
if (!this._videoElement) {
|
|
136
|
+
i(new Error("image repository is not inited!"));
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (this._isPlaying) {
|
|
140
|
+
i(new Error("image repository is playing!"));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
this._videoElement.requestVideoFrameCallback(() => {
|
|
144
|
+
t(this.videoElement);
|
|
145
|
+
}), this._videoElement.currentTime = n(e);
|
|
146
|
+
}));
|
|
79
147
|
}
|
|
80
148
|
/**
|
|
81
149
|
* 开始播放连续帧图片
|
|
@@ -83,7 +151,20 @@ class n {
|
|
|
83
151
|
async play() {
|
|
84
152
|
if (!this._videoElement)
|
|
85
153
|
throw new Error("image repository is not inited!");
|
|
86
|
-
|
|
154
|
+
if (this._isPlaying)
|
|
155
|
+
throw new Error("image repository is playing!");
|
|
156
|
+
try {
|
|
157
|
+
this._isPlaying = !0;
|
|
158
|
+
const e = (t, i) => {
|
|
159
|
+
this._emitter.emit("requestFrame", {
|
|
160
|
+
frameTimestampInMicroseconds: l(i.mediaTime),
|
|
161
|
+
originalEvent: { now: t, metadata: i }
|
|
162
|
+
}), this._requestVideoFrameCallbackId = this._videoElement.requestVideoFrameCallback(e);
|
|
163
|
+
};
|
|
164
|
+
return this._requestVideoFrameCallbackId = this._videoElement.requestVideoFrameCallback(e), await this._videoElement.play();
|
|
165
|
+
} catch (e) {
|
|
166
|
+
throw this._isPlaying = !1, e;
|
|
167
|
+
}
|
|
87
168
|
}
|
|
88
169
|
/**
|
|
89
170
|
* 停止播放
|
|
@@ -91,7 +172,9 @@ class n {
|
|
|
91
172
|
stop() {
|
|
92
173
|
if (!this._videoElement)
|
|
93
174
|
throw new Error("image repository is not inited!");
|
|
94
|
-
|
|
175
|
+
if (!this._isPlaying)
|
|
176
|
+
throw new Error("image repository is not playing");
|
|
177
|
+
this.pause(), this._videoElement.currentTime = n(0);
|
|
95
178
|
}
|
|
96
179
|
/**
|
|
97
180
|
* 暂停播放
|
|
@@ -99,16 +182,24 @@ class n {
|
|
|
99
182
|
pause() {
|
|
100
183
|
if (!this._videoElement)
|
|
101
184
|
throw new Error("image repository is not inited!");
|
|
102
|
-
this.
|
|
185
|
+
if (!this._isPlaying)
|
|
186
|
+
throw new Error("image repository is not playing");
|
|
187
|
+
try {
|
|
188
|
+
this._isPlaying = !1, this._requestVideoFrameCallbackId && (this._videoElement.cancelVideoFrameCallback(
|
|
189
|
+
this._requestVideoFrameCallbackId
|
|
190
|
+
), this._requestVideoFrameCallbackId = void 0), this._videoElement.pause();
|
|
191
|
+
} catch (e) {
|
|
192
|
+
throw this._isPlaying = !0, e;
|
|
193
|
+
}
|
|
103
194
|
}
|
|
104
|
-
on(
|
|
105
|
-
return this._emitter.on(
|
|
195
|
+
on(e, t) {
|
|
196
|
+
return this._emitter.on(e, t), {
|
|
106
197
|
off: () => {
|
|
107
|
-
this._emitter.off(
|
|
198
|
+
this._emitter.off(e, t);
|
|
108
199
|
}
|
|
109
200
|
};
|
|
110
201
|
}
|
|
111
202
|
}
|
|
112
203
|
export {
|
|
113
|
-
|
|
204
|
+
o as ImageRepository
|
|
114
205
|
};
|