@scienjoy/sj-ai-plus 1.0.6 → 1.0.8

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.
@@ -1,8 +1,8 @@
1
- import { ref as h } from "vue";
2
- function E() {
3
- const d = h(null), r = h(null);
4
- let u = null, t = null, l = null, p = null, f = null, n = null, s = null;
5
- const b = `
1
+ import { ref as x } from "vue";
2
+ function B() {
3
+ const g = x(null), o = x(null), u = x(!1), a = x(!1);
4
+ let c = null, e = null, l = null, p = null, v = null, s = null, d = null;
5
+ const y = `
6
6
  struct Uniforms {
7
7
  targetColor1: vec3f,
8
8
  threshold: f32,
@@ -23,7 +23,6 @@ function E() {
23
23
 
24
24
  @vertex
25
25
  fn vertexMain(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
26
- // 全屏四边形顶点
27
26
  var pos = array<vec2f, 6>(
28
27
  vec2f(-1.0, -1.0),
29
28
  vec2f(1.0, -1.0),
@@ -35,7 +34,6 @@ function E() {
35
34
 
36
35
  var output: VertexOutput;
37
36
  output.position = vec4f(pos[vertexIndex], 0.0, 1.0);
38
- // 翻转Y坐标以修正视频倒置问题
39
37
  output.texCoord = vec2f(
40
38
  pos[vertexIndex].x * 0.5 + 0.5,
41
39
  1.0 - (pos[vertexIndex].y * 0.5 + 0.5)
@@ -56,12 +54,12 @@ function E() {
56
54
  let rgb = color.rgb;
57
55
  let pixelSize = 1.0 / uniforms.resolution;
58
56
 
59
- // 检查当前像素是否匹配目标色
57
+ // 主颜色匹配:直接透明
60
58
  if (matchesTargetColor(rgb)) {
61
59
  return vec4f(0.0, 0.0, 0.0, 0.0);
62
60
  }
63
61
 
64
- // 检查8个邻居(包括对角线)
62
+ // 8邻域检测:边缘像素透明(第一层侵蚀)
65
63
  let left = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(-pixelSize.x, 0.0)).rgb;
66
64
  let right = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(pixelSize.x, 0.0)).rgb;
67
65
  let top = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(0.0, -pixelSize.y)).rgb;
@@ -71,7 +69,6 @@ function E() {
71
69
  let bottomLeft = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(-pixelSize.x, pixelSize.y)).rgb;
72
70
  let bottomRight = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(pixelSize.x, pixelSize.y)).rgb;
73
71
 
74
- // 第一层侵蚀:如果任意邻居匹配背景色,当前像素也变透明
75
72
  if (matchesTargetColor(left) || matchesTargetColor(right) ||
76
73
  matchesTargetColor(top) || matchesTargetColor(bottom) ||
77
74
  matchesTargetColor(topLeft) || matchesTargetColor(topRight) ||
@@ -79,147 +76,123 @@ function E() {
79
76
  return vec4f(0.0, 0.0, 0.0, 0.0);
80
77
  }
81
78
 
82
- // 第二层侵蚀:检查2像素距离的邻居
83
- let left2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(-pixelSize.x * 2.0, 0.0)).rgb;
84
- let right2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(pixelSize.x * 2.0, 0.0)).rgb;
85
- let top2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(0.0, -pixelSize.y * 2.0)).rgb;
86
- let bottom2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(0.0, pixelSize.y * 2.0)).rgb;
79
+ // 2像素邻域检测:第二层侵蚀,优化边缘
80
+ let left2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(-pixelSize.x * 4.0, 0.0)).rgb;
81
+ let right2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(pixelSize.x * 4.0, 0.0)).rgb;
82
+ let top2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(0.0, -pixelSize.y * 4.0)).rgb;
83
+ let bottom2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(0.0, pixelSize.y * 4.0)).rgb;
87
84
 
88
85
  if (matchesTargetColor(left2) || matchesTargetColor(right2) ||
89
86
  matchesTargetColor(top2) || matchesTargetColor(bottom2)) {
90
87
  return vec4f(0.0, 0.0, 0.0, 0.0);
91
88
  }
92
89
 
93
- // 不匹配且不在边缘 - 完全保留
90
+ // 非背景/非边缘像素:完全保留
94
91
  return vec4f(rgb, 1.0);
95
92
  }
96
93
  `;
97
- function v(o) {
98
- const e = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(o);
99
- return e ? {
100
- r: parseInt(e[1], 16),
101
- g: parseInt(e[2], 16),
102
- b: parseInt(e[3], 16)
94
+ function S(t) {
95
+ const r = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);
96
+ return r ? {
97
+ r: parseInt(r[1], 16),
98
+ g: parseInt(r[2], 16),
99
+ b: parseInt(r[3], 16)
103
100
  } : { r: 0, g: 0, b: 0 };
104
101
  }
105
- async function C(o) {
106
- if (!navigator.gpu)
107
- return console.error("WebGPU不受支持。请使用Chrome 113+或Edge 113+,或在chrome://flags中启用WebGPU"), !1;
102
+ const T = () => {
103
+ if (c && (cancelAnimationFrame(c), c = null), s && (s.destroy(), s = null), p && (p = null), d && (d = null), v && (v = null), l) {
104
+ try {
105
+ l.unconfigure();
106
+ } catch {
107
+ }
108
+ l = null;
109
+ }
110
+ e && (e.destroy(), e = null), u.value = !1, a.value = !1, console.log("✅ WebGPU资源已彻底销毁,可重新初始化");
111
+ };
112
+ async function h(t, r = 3) {
113
+ if (T(), !navigator.gpu)
114
+ return console.error("❌ WebGPU不受支持:请使用Chrome113+/Edge113+,或在chrome://flags中启用WebGPU"), !1;
115
+ if (!t)
116
+ return console.error("❌ WebGPU初始化失败:canvas节点不存在"), !1;
108
117
  try {
109
- const e = await navigator.gpu.requestAdapter();
110
- if (!e)
111
- return console.error("无法获取WebGPU适配器"), !1;
112
- if (t = await e.requestDevice(), l = o.getContext("webgpu"), !l)
113
- return console.error("无法获取WebGPU上下文"), !1;
114
- const i = navigator.gpu.getPreferredCanvasFormat();
118
+ const i = await navigator.gpu.requestAdapter({ powerPreference: "low-power" });
119
+ if (!i) throw new Error("获取GPU适配器失败");
120
+ if (e = await i.requestDevice(), !e) throw new Error("获取GPU设备失败");
121
+ if (l = t.getContext("webgpu"), !l) throw new Error("获取canvas的WebGPU上下文失败");
122
+ const n = navigator.gpu.getPreferredCanvasFormat();
115
123
  l.configure({
116
- device: t,
117
- format: i,
124
+ device: e,
125
+ format: n,
118
126
  alphaMode: "premultiplied"
127
+ // 透明背景核心配置
119
128
  });
120
- const a = t.createShaderModule({
121
- code: b
122
- });
123
- f = t.createSampler({
124
- magFilter: "linear",
125
- minFilter: "linear"
126
- }), n = t.createBuffer({
129
+ const f = e.createShaderModule({ code: y });
130
+ v = e.createSampler({ magFilter: "linear", minFilter: "linear" }), s = e.createBuffer({
127
131
  size: 48,
128
132
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
129
- }), s = t.createBindGroupLayout({
133
+ }), d = e.createBindGroupLayout({
130
134
  entries: [
131
- {
132
- binding: 0,
133
- visibility: GPUShaderStage.FRAGMENT,
134
- sampler: {}
135
- },
136
- {
137
- binding: 1,
138
- visibility: GPUShaderStage.FRAGMENT,
139
- externalTexture: {}
140
- },
141
- {
142
- binding: 2,
143
- visibility: GPUShaderStage.FRAGMENT,
144
- buffer: { type: "uniform" }
145
- }
135
+ { binding: 0, visibility: GPUShaderStage.FRAGMENT, sampler: {} },
136
+ { binding: 1, visibility: GPUShaderStage.FRAGMENT, externalTexture: {} },
137
+ { binding: 2, visibility: GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } }
146
138
  ]
147
139
  });
148
- const c = t.createPipelineLayout({
149
- bindGroupLayouts: [s]
150
- });
151
- return p = t.createRenderPipeline({
152
- layout: c,
153
- vertex: {
154
- module: a,
155
- entryPoint: "vertexMain"
156
- },
140
+ const C = e.createPipelineLayout({ bindGroupLayouts: [d] });
141
+ return p = e.createRenderPipeline({
142
+ layout: C,
143
+ vertex: { module: f, entryPoint: "vertexMain" },
157
144
  fragment: {
158
- module: a,
145
+ module: f,
159
146
  entryPoint: "fragmentMain",
160
147
  targets: [{
161
- format: i,
148
+ format: n,
162
149
  blend: {
163
- color: {
164
- srcFactor: "src-alpha",
165
- dstFactor: "one-minus-src-alpha"
166
- },
167
- alpha: {
168
- srcFactor: "one",
169
- dstFactor: "one-minus-src-alpha"
170
- }
150
+ color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" },
151
+ alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha" }
171
152
  }
172
153
  }]
173
154
  },
174
- primitive: {
175
- topology: "triangle-list"
176
- }
177
- }), console.log("WebGPU初始化成功"), !0;
178
- } catch (e) {
179
- return console.error("WebGPU初始化失败:", e), !1;
155
+ primitive: { topology: "triangle-list" }
156
+ }), u.value = !0, console.log("✅ WebGPU初始化成功"), !0;
157
+ } catch (i) {
158
+ return console.error(`❌ WebGPU初始化失败(剩余重试${r - 1}次):`, i), r > 1 ? (await new Promise((n) => setTimeout(n, 500)), h(t, r - 1)) : (u.value = !1, !1);
180
159
  }
181
160
  }
182
- function m() {
183
- if (!d.value || !r.value || !t || !l || !p || !f || !n || !s)
161
+ function b() {
162
+ if (!u.value || !g.value || !o.value || !e || !l || !p || !v || !s || !d) {
163
+ a.value = !1;
184
164
  return;
185
- const o = d.value, e = r.value;
186
- if (o.readyState < o.HAVE_CURRENT_DATA) {
187
- u = requestAnimationFrame(m);
165
+ }
166
+ const t = g.value, r = o.value;
167
+ if (t.readyState < t.HAVE_CURRENT_DATA) {
168
+ c = requestAnimationFrame(b);
188
169
  return;
189
170
  }
190
- (e.width !== o.videoWidth || e.height !== o.videoHeight) && (e.width = o.videoWidth, e.height = o.videoHeight);
171
+ (r.width !== t.videoWidth || r.height !== t.videoHeight) && (r.width = t.videoWidth, r.height = t.videoHeight);
191
172
  try {
192
- const i = t.importExternalTexture({
193
- source: o
194
- }), a = v("#0AFFFF"), c = v("#0AFFFF"), y = new Float32Array([
195
- a.r / 255,
196
- a.g / 255,
197
- a.b / 255,
198
- // targetColor1
173
+ const i = e.importExternalTexture({ source: t }), n = S("#0AFFFF"), f = S("#0AFFFF"), C = new Float32Array([
174
+ n.r / 255,
175
+ n.g / 255,
176
+ n.b / 255,
199
177
  0.4,
200
- // threshold - 颜色相似度阈值
201
- c.r / 255,
202
- c.g / 255,
203
- c.b / 255,
204
- // targetColor2
178
+ f.r / 255,
179
+ f.g / 255,
180
+ f.b / 255,
205
181
  0,
206
- // padding
207
- e.width,
208
- e.height,
209
- // resolution
182
+ r.width,
183
+ r.height,
210
184
  0,
211
185
  0
212
- // padding2
213
186
  ]);
214
- t.queue.writeBuffer(n, 0, y);
215
- const P = t.createBindGroup({
216
- layout: s,
187
+ e.queue.writeBuffer(s, 0, C);
188
+ const U = e.createBindGroup({
189
+ layout: d,
217
190
  entries: [
218
- { binding: 0, resource: f },
191
+ { binding: 0, resource: v },
219
192
  { binding: 1, resource: i },
220
- { binding: 2, resource: { buffer: n } }
193
+ { binding: 2, resource: { buffer: s } }
221
194
  ]
222
- }), x = t.createCommandEncoder(), g = x.beginRenderPass({
195
+ }), P = e.createCommandEncoder(), m = P.beginRenderPass({
223
196
  colorAttachments: [{
224
197
  view: l.getCurrentTexture().createView(),
225
198
  clearValue: { r: 0, g: 0, b: 0, a: 0 },
@@ -227,49 +200,48 @@ function E() {
227
200
  storeOp: "store"
228
201
  }]
229
202
  });
230
- g.setPipeline(p), g.setBindGroup(0, P), g.draw(6), g.end(), t.queue.submit([x.finish()]);
203
+ m.setPipeline(p), m.setBindGroup(0, U), m.draw(6), m.end(), e.queue.submit([P.finish()]);
231
204
  } catch (i) {
232
- console.error("WebGPU渲染帧错误:", i);
205
+ console.error("WebGPU渲染帧错误:", i), a.value = !1;
206
+ return;
233
207
  }
234
- u = requestAnimationFrame(m);
208
+ c = requestAnimationFrame(b);
235
209
  }
236
- async function S() {
237
- if (!d.value || !r.value) return;
238
- if (!await C(r.value)) {
239
- console.error("WebGPU初始化失败,请确保浏览器支持WebGPU");
210
+ async function G() {
211
+ if (!g.value || !o.value) {
212
+ console.error("❌ processVideo失败:video/canvas节点未绑定");
213
+ return;
214
+ }
215
+ if (a.value) return;
216
+ if (a.value = !0, !await h(o.value)) {
217
+ console.error("❌ WebGPU初始化重试耗尽,无法处理视频"), a.value = !1, u.value = !1;
240
218
  return;
241
219
  }
242
- u = requestAnimationFrame(m);
220
+ c = requestAnimationFrame(b);
243
221
  }
244
- function T() {
245
- if (u !== null && (cancelAnimationFrame(u), u = null), r.value && (r.value.getContext("2d") || r.value.getContext("webgpu"))) {
246
- if (l && t) {
247
- const i = t.createCommandEncoder();
248
- i.beginRenderPass({
249
- colorAttachments: [{
250
- view: l.getCurrentTexture().createView(),
251
- clearValue: { r: 0, g: 0, b: 0, a: 0 },
252
- loadOp: "clear",
253
- storeOp: "store"
254
- }]
255
- }).end(), t.queue.submit([i.finish()]);
256
- }
257
- const e = r.value.getContext("2d");
258
- if (e) {
259
- e.clearRect(0, 0, r.value.width, r.value.height);
260
- const i = r.value.width, a = r.value.height;
261
- r.value.width = i, r.value.height = a;
222
+ function w() {
223
+ if (a.value = !1, u.value = !1, T(), o.value) {
224
+ const t = o.value.getContext("2d");
225
+ if (t) {
226
+ t.clearRect(0, 0, o.value.width, o.value.height);
227
+ const r = o.value.width, i = o.value.height;
228
+ o.value.width = r, o.value.height = i;
262
229
  }
263
230
  }
264
- n && (n.destroy(), n = null), t = null, l = null, p = null, f = null, s = null;
231
+ }
232
+ async function F() {
233
+ return o.value ? await h(o.value, 3) : (console.error("❌ reInitWebGPU失败:canvas节点未绑定"), !1);
265
234
  }
266
235
  return {
267
- videoRef: d,
268
- canvasRef: r,
269
- processVideo: S,
270
- stopProcessing: T
236
+ videoRef: g,
237
+ canvasRef: o,
238
+ isInitSuccess: u,
239
+ isProcessing: a,
240
+ processVideo: G,
241
+ stopProcessing: w,
242
+ reInitWebGPU: F
271
243
  };
272
244
  }
273
245
  export {
274
- E as default
246
+ B as default
275
247
  };