xvai-loi 0.1.66 → 0.1.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/co.txt +1 -1
  2. package/package.json +1 -1
  3. package/xvai-loi.js +86 -72
package/co.txt CHANGED
@@ -1 +1 @@
1
- xvaiLoi111450
1
+ xvaiLoi111649
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xvai-loi",
3
- "version": "0.1.66",
3
+ "version": "0.1.68",
4
4
  "description": "Loi dung video (Edit Video Tu Dong) nap vao tool Google Flow qua o cam engine/oCam.ts",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
package/xvai-loi.js CHANGED
@@ -9817,6 +9817,64 @@ function datKhoiChu(g, kc, coThanh, coTach, vungTruoc, choThu = false, WH = 9 /
9817
9817
  return ra;
9818
9818
  }
9819
9819
 
9820
+ // flow-src/engine/khuon.ts
9821
+ var KHUON_TOPN = {
9822
+ ten: "Top N chi\u1EC1u s\xE2u (Captions)",
9823
+ tram: { phut: 18.3, tyLe: 0.7, phan: [0.83, 0.81, 0.46], daiTV: 2.1, video: 0.33, nhanVat: ["Vietnamese people in a real everyday setting.", "Close-up of an object, hands or a place that shows the idea, no faces."] },
9824
+ // cảnh trám / phút, % thời lượng, 3 phần đầu/giữa/cuối, độ dài trung vị (s), tỉ lệ clip động; nhanVat: xen kẽ ảnh có người / cận vật-tay-nơi (đối thủ trộn web, stock, 3D — B06-1027: toàn ảnh người → 'không thấy mặt' 12 % < 15)
9825
+ chu: { phut: [8, 18] },
9826
+ icon: { phut: 11.5 },
9827
+ cat: { moi10s: [4, 6] },
9828
+ nguoi: { phongToiDa: 1.8, matToiDa: 0.55 },
9829
+ // matToiDa: hộp đầu (tóc→cằm) cao hơn 0,55 H thì KHÔNG dùng ô người / chia (không vừa ô) // MỌI ô người (PIP, thẻ, chia) phóng khung gốc tối đa 1,8× (độ nét) — trước: PIP 1,6, thẻ 1,3 (B05-1027: thẻ hiện cả người nhỏ)
9830
+ bien: { dau: 3, cuoi: 2.5, ctaAnh: true }
9831
+ // không đặt ảnh trám ở 3 s đầu (móc) và 2,5 s cuối; vùng CTA VẪN có ảnh (đối thủ CTA 8,7 s vẫn trám)
9832
+ };
9833
+ var HU3 = /^(và|với|là|thì|mà|nhưng|rồi|cái|những|các|một|này|đó|chúng|ta|tôi|mình|bạn|em|anh|chị|của|cho|để|nên|vì|cũng|đã|đang|sẽ|có|không|được|rất|ạ|nhé|nha|à|ơi|lại|ra|vào|đi|nó|họ|hãy|chỉ|cần|phải|mới|khi|nếu|vậy|thế|như|từ|trong|về|bị|hết|luôn|sau|trước)$/i;
9834
+ var sach2 = (x) => String(x || "").replace(/[.,!?;:…"“”]/g, "");
9835
+ function lapAnhTheoKhuon(kb, ws, K = KHUON_TOPN, toiDa = 12) {
9836
+ const W4 = (ws || []).filter((w) => w && w.text && w.t1 > w.t0);
9837
+ if (!kb || !Array.isArray(kb.canh) || W4.length < 20) return 0;
9838
+ const lo = (x) => String(x || "").toLocaleLowerCase("vi").replace(/[^\p{L}\p{N}\s]/gu, "").trim(), wl = W4.map((w) => lo(w.text));
9839
+ const timTu = (tu) => {
9840
+ const q = lo(tu).split(/\s+/).filter(Boolean).slice(0, 3);
9841
+ if (!q.length) return -1;
9842
+ for (let i = 0; i + q.length <= wl.length; i++) {
9843
+ let ok = true;
9844
+ for (let j = 0; j < q.length; j++) if (wl[i + j] !== q[j]) {
9845
+ ok = false;
9846
+ break;
9847
+ }
9848
+ if (ok) return i;
9849
+ }
9850
+ return -1;
9851
+ };
9852
+ const g = 60 / K.tram.phut, t0 = W4[0].t0 + K.bien.dau, t1 = W4[W4.length - 1].t1 - K.bien.cuoi;
9853
+ const moc = kb.canh.filter(
9854
+ (c) => c && c.tu && /^(anh|ds)$/.test(String(c.kieu))
9855
+ /* 'so' vẽ thành chữ to trên người / ô tròn (cut/tron) — không phải trám */
9856
+ ).map((c) => timTu(c.tu)).filter((i) => i >= 0).map((i) => W4[i].t0).filter((t) => t > t0 && t < t1).sort((a, b) => a - b);
9857
+ const pts = [t0, ...moc, t1];
9858
+ let them = 0;
9859
+ for (let k = 0; k + 1 < pts.length && them < toiDa; k++) {
9860
+ const a0 = pts[k], b0 = pts[k + 1];
9861
+ if (b0 - a0 < 1.6 * g) continue;
9862
+ const n = Math.max(1, Math.round((b0 - a0) / g) - 1);
9863
+ for (let m = 1; m <= n && them < toiDa; m++) {
9864
+ const tm = a0 + (b0 - a0) * m / (n + 1), i0 = W4.findIndex((w) => w.t0 >= tm);
9865
+ if (i0 < 0) continue;
9866
+ const nd = [];
9867
+ for (let i2 = i0; i2 < Math.min(W4.length, i0 + 8) && nd.length < 3; i2++) if (!HU3.test(sach2(W4[i2].text))) nd.push(i2);
9868
+ if (nd.length < 2) continue;
9869
+ const i = nd[0], tu = W4.slice(i, i + 3).map((w) => sach2(w.text)).join(" "), cau = W4.slice(Math.max(0, i - 5), i + 10).map((w) => w.text).join(" ");
9870
+ if (timTu(tu) !== i) continue;
9871
+ kb.canh.push({ tu, kieu: "anh", chu: " ", chu2: "", khuon: 1, en: 'Cinematic photorealistic vertical photo that illustrates the meaning of this Vietnamese sentence: "' + cau + '". ' + (them % 2 ? K.tram.nhanVat[1] : K.tram.nhanVat[0]) + " Natural light, no text, no captions." });
9872
+ them++;
9873
+ }
9874
+ }
9875
+ return them;
9876
+ }
9877
+
9820
9878
  // flow-src/engine/veCuongMe.ts
9821
9879
  var luoiAnhCache = /* @__PURE__ */ new Map();
9822
9880
  var matAnhCache = /* @__PURE__ */ new Map();
@@ -10012,7 +10070,7 @@ function sNuaDuoi(F) {
10012
10070
  return F ? Math.max(0.5, Math.min(1, 0.26 / Math.max(0.08, F[2] - F[0]))) : 0.75;
10013
10071
  }
10014
10072
  function tfDau(g, W4, H2, D, yTop, kz = 1) {
10015
- const s = Math.max(1, Math.min(1.3, 0.21 / Math.max(0.08, D[3] - D[1]))) * kz, cx = (D[0] + D[2]) / 2;
10073
+ const s = Math.max(1, Math.min(KHUON_TOPN.nguoi.phongToiDa, 0.21 / Math.max(0.05, D[3] - D[1]))) * kz, cx = (D[0] + D[2]) / 2;
10016
10074
  const tx = Math.min(0, Math.max(W4 - W4 * s, W4 / 2 - cx * W4 * s)), ty = Math.min((yTop - 0.05) * H2, yTop * H2 - D[1] * H2 * s);
10017
10075
  g.translate(tx, ty);
10018
10076
  g.scale(s, s);
@@ -10515,7 +10573,7 @@ dangKy("cmNen", (g, d, tuoi, W4, H2, nen2, _s, dai2) => {
10515
10573
  bo(g, x, y, w, h, r);
10516
10574
  g.clip();
10517
10575
  {
10518
- const Dc = dauCanh(d, nen2, W4, H2);
10576
+ const Dc = (d.F && d.F[3] > d.F[1] ? d.F : null) || dauCanh(d, nen2, W4, H2);
10519
10577
  if (Dc) tfDau(g, W4, H2, Dc, y / H2 + 0.05);
10520
10578
  else tfTam(g, W4, H2, F, sNuaDuoi(F), NUA_DUOI_CY);
10521
10579
  }
@@ -10587,7 +10645,7 @@ dangKy("cmNen", (g, d, tuoi, W4, H2, nen2, _s, dai2) => {
10587
10645
  }, Math.round(0.012 * W4), "brightness(0.8)");
10588
10646
  const kz = eOut(Math.min(1, tuoi / 0.5));
10589
10647
  {
10590
- const Dc = dauCanh(d, nen2, W4, H2);
10648
+ const Dc = (d.F && d.F[3] > d.F[1] ? d.F : null) || dauCanh(d, nen2, W4, H2);
10591
10649
  if (Dc) tfDau(g, W4, H2, Dc, hT / H2 + 0.05, 1 + 0.12 * (1 - kz));
10592
10650
  else tfTam(g, W4, H2, F, sNuaDuoi(F) * (1 + 0.12 * (1 - kz)), NUA_DUOI_CY);
10593
10651
  }
@@ -10875,7 +10933,7 @@ dangKy("cmAnh", (g, d, tuoi, W4, H2, _n, _s, dai2) => {
10875
10933
  t++;
10876
10934
  n += LA[r * 36 + cc] * (r >= rT && r < rT + 16 ? 4 : 1) + (MA && r >= MA[1] * 64 && r <= MA[3] * 64 && cc >= MA[0] * 36 && cc <= MA[2] * 36 ? 20 : 0);
10877
10935
  }
10878
- return t ? n / t : 1;
10936
+ return (t ? n / t : 1) + (d.pip && _n && y0 < 0.8 && y0 + hK > 0.555 ? 5 : 0);
10879
10937
  };
10880
10938
  const yB = [0.6, 0.55, 0.14, 0.66, 0.5].filter((y) => y + hK <= 0.82).map((y) => [y, ph(y)]).sort((a2, b) => a2[1] - b[1])[0][0];
10881
10939
  yK = (yB + 0.575 * 112 / 1920) * H2;
@@ -10888,7 +10946,7 @@ dangKy("cmAnh", (g, d, tuoi, W4, H2, _n, _s, dai2) => {
10888
10946
  if (d.chu2) chu2(g, d.chu2, xK, yK + 125 * kK * H2 / 1920 + (1 - k) * 70 * H2 / 1920, 96 * kK * H2 / 1920, d.do2 ? "do" : "vang", kep12((tuoi - 0.35) / 0.15) * kc, wK2);
10889
10947
  }
10890
10948
  if (d.pip && _n) {
10891
- const bw = 0.36 * W4, bh = bw * 1.2, bx = 0.06 * W4, by = 0.555 * H2 + (1 - eOut(Math.min(1, tuoi / 0.35))) * 0.05 * H2, F = d.F, Dm = dauCanh(d, _n, W4, H2), Fd = F && F[3] - F[1] > 0.45 ? F : Dm || F || globalThis.__matNguon, top = Fd ? Fd[1] : 0.2, cam = Fd ? Math.max(Fd[3], top + 0.12) : 0.6, s = Math.max(bw / W4, bh / H2, Math.min(1.6, 0.54 * bh / (Math.max(0.08, cam - top) * H2))), cx0 = Fd ? (Fd[0] + Fd[2]) / 2 : 0.5, MK = globalThis.__matKhung, kd = d._goc || d, cx = MK ? kd.__pipCx = kd.__pipCx == null ? (MK[0] + MK[2]) / 2 : kd.__pipCx + ((MK[0] + MK[2]) / 2 - kd.__pipCx) * 0.12 : cx0;
10949
+ const bw = 0.36 * W4, bh = bw * 1.2, bx = 0.06 * W4, by = 0.555 * H2 + (1 - eOut(Math.min(1, tuoi / 0.35))) * 0.05 * H2, F = d.F, Dm = dauCanh(d, _n, W4, H2), Fd = F || globalThis.__matNguon || Dm, top = Fd ? Fd[1] : 0.2, cam = Fd ? Math.max(Fd[3], top + 0.12) : 0.6, s = Math.max(bw / W4, bh / H2, Math.min(KHUON_TOPN.nguoi.phongToiDa, 0.54 * bh / (Math.max(0.08, cam - top) * H2))), cx0 = Fd ? (Fd[0] + Fd[2]) / 2 : 0.5, MK = globalThis.__matKhung, kd = d._goc || d, cx = MK ? kd.__pipCx = kd.__pipCx == null ? (MK[0] + MK[2]) / 2 : kd.__pipCx + ((MK[0] + MK[2]) / 2 - kd.__pipCx) * 0.12 : cx0;
10892
10950
  hop3(g, "nguoi:pip", bx, by, bx + bw, by + bh);
10893
10951
  globalThis.__pipO = { k: globalThis.__khungSo, b: [bx, 0.555 * H2, bx + bw, 0.555 * H2 + bh] };
10894
10952
  g.save();
@@ -11293,62 +11351,6 @@ dangKy("cmSticker", (g, d, tuoi, W4, H2, _n, _s, dai2) => {
11293
11351
  }
11294
11352
  });
11295
11353
 
11296
- // flow-src/engine/khuon.ts
11297
- var KHUON_TOPN = {
11298
- ten: "Top N chi\u1EC1u s\xE2u (Captions)",
11299
- tram: { phut: 18.3, tyLe: 0.7, phan: [0.83, 0.81, 0.46], daiTV: 2.1, video: 0.33 },
11300
- // cảnh trám / phút, % thời lượng, 3 phần đầu/giữa/cuối, độ dài trung vị (s), tỉ lệ clip động
11301
- chu: { phut: [8, 18] },
11302
- icon: { phut: 11.5 },
11303
- cat: { moi10s: [4, 6] },
11304
- bien: { dau: 3, cuoi: 2.5, ctaAnh: true }
11305
- // không đặt ảnh trám ở 3 s đầu (móc) và 2,5 s cuối; vùng CTA VẪN có ảnh (đối thủ CTA 8,7 s vẫn trám)
11306
- };
11307
- var HU3 = /^(và|với|là|thì|mà|nhưng|rồi|cái|những|các|một|này|đó|chúng|ta|tôi|mình|bạn|em|anh|chị|của|cho|để|nên|vì|cũng|đã|đang|sẽ|có|không|được|rất|ạ|nhé|nha|à|ơi|lại|ra|vào|đi|nó|họ|hãy|chỉ|cần|phải|mới|khi|nếu|vậy|thế|như|từ|trong|về|bị|hết|luôn|sau|trước)$/i;
11308
- var sach2 = (x) => String(x || "").replace(/[.,!?;:…"“”]/g, "");
11309
- function lapAnhTheoKhuon(kb, ws, K = KHUON_TOPN, toiDa = 12) {
11310
- const W4 = (ws || []).filter((w) => w && w.text && w.t1 > w.t0);
11311
- if (!kb || !Array.isArray(kb.canh) || W4.length < 20) return 0;
11312
- const lo = (x) => String(x || "").toLocaleLowerCase("vi").replace(/[^\p{L}\p{N}\s]/gu, "").trim(), wl = W4.map((w) => lo(w.text));
11313
- const timTu = (tu) => {
11314
- const q = lo(tu).split(/\s+/).filter(Boolean).slice(0, 3);
11315
- if (!q.length) return -1;
11316
- for (let i = 0; i + q.length <= wl.length; i++) {
11317
- let ok = true;
11318
- for (let j = 0; j < q.length; j++) if (wl[i + j] !== q[j]) {
11319
- ok = false;
11320
- break;
11321
- }
11322
- if (ok) return i;
11323
- }
11324
- return -1;
11325
- };
11326
- const g = 60 / K.tram.phut, t0 = W4[0].t0 + K.bien.dau, t1 = W4[W4.length - 1].t1 - K.bien.cuoi;
11327
- const moc = kb.canh.filter(
11328
- (c) => c && c.tu && /^(anh|ds)$/.test(String(c.kieu))
11329
- /* 'so' vẽ thành chữ to trên người / ô tròn (cut/tron) — không phải trám */
11330
- ).map((c) => timTu(c.tu)).filter((i) => i >= 0).map((i) => W4[i].t0).filter((t) => t > t0 && t < t1).sort((a, b) => a - b);
11331
- const pts = [t0, ...moc, t1];
11332
- let them = 0;
11333
- for (let k = 0; k + 1 < pts.length && them < toiDa; k++) {
11334
- const a0 = pts[k], b0 = pts[k + 1];
11335
- if (b0 - a0 < 1.6 * g) continue;
11336
- const n = Math.max(1, Math.round((b0 - a0) / g) - 1);
11337
- for (let m = 1; m <= n && them < toiDa; m++) {
11338
- const tm = a0 + (b0 - a0) * m / (n + 1), i0 = W4.findIndex((w) => w.t0 >= tm);
11339
- if (i0 < 0) continue;
11340
- const nd = [];
11341
- for (let i2 = i0; i2 < Math.min(W4.length, i0 + 8) && nd.length < 3; i2++) if (!HU3.test(sach2(W4[i2].text))) nd.push(i2);
11342
- if (nd.length < 2) continue;
11343
- const i = nd[0], tu = W4.slice(i, i + 3).map((w) => sach2(w.text)).join(" "), cau = W4.slice(Math.max(0, i - 5), i + 10).map((w) => w.text).join(" ");
11344
- if (timTu(tu) !== i) continue;
11345
- kb.canh.push({ tu, kieu: "anh", chu: " ", chu2: "", khuon: 1, en: 'Cinematic photorealistic vertical photo that illustrates the meaning of this Vietnamese sentence: "' + cau + '". Vietnamese people, real everyday setting, natural light, no text, no captions.' });
11346
- them++;
11347
- }
11348
- }
11349
- return them;
11350
- }
11351
-
11352
11354
  // flow-src/engine/khoiCuongMe.ts
11353
11355
  napLogo();
11354
11356
  var DAU_MUC = /^(đầu tiên|thứ nhất|thứ (hai|ba|tư|năm|sáu|bảy|tám|\d+)|tiếp theo|kế tiếp|tiếp nữa|cuối cùng|và cuối cùng|số (một|hai|ba|\d+)|công cụ (thứ|số)|skill (thứ|số))/;
@@ -11862,7 +11864,7 @@ function lapCuongMe(o) {
11862
11864
  if (x.kieu === "anh" && dV) {
11863
11865
  de(f2, dV, { uuTien: UT.so + 5, bo: "anh", ten: ten2, chu: chuK, chu2: chu22, keu: "whoosh", video: 1 }, 3, datAnh);
11864
11866
  ghiL("video", { bo: "anh", f: f2, d: dV }, "kho video: ung vien clip " + dV.toFixed(1) + " s thay anh: " + String(x.tu || ""));
11865
- } else if (x.kieu === "anh" && (co || chuK)) de(f2, (f2 < f1 ? 2 : 2.4) * kTram(), { uuTien: UT.anh, ...co ? [{ bo: "anh", ten: ten2, chu: chuK, chu2: chu22, keu: "whoosh" }, { bo: "chia", ten: ten2, chu: chuK, keu: "whoosh" }, { bo: "anh", ten: ten2, chu: chuK, chu2: chu22, pip: 1, keu: "whoosh" }][nAnh++ % 3] : { bo: "kinh", dong: [chuK, chu22].filter(Boolean), keu: "whoosh" } }, 3, datAnh);
11867
+ } else if (x.kieu === "anh" && (co || chuK)) de(f2, (f2 < f1 ? 2 : 2.4) * kTram(), { uuTien: UT.anh, ...co ? nAnh++ % 3 === 0 || !((fb) => fb && fb[3] - fb[1] < KHUON_TOPN.nguoi.matToiDa)(F(f2, f2 + 2.4)) ? { bo: "anh", ten: ten2, chu: chuK, chu2: chu22, keu: "whoosh" } : (nAnh - 1) % 3 === 1 ? { bo: "chia", ten: ten2, chu: chuK, keu: "whoosh" } : { bo: "anh", ten: ten2, chu: chuK, chu2: chu22, pip: 1, keu: "whoosh" } : { bo: "kinh", dong: [chuK, chu22].filter(Boolean), keu: "whoosh" } }, 3, datAnh);
11866
11868
  else if (x.kieu === "vat") {
11867
11869
  const LG = timLogo(suaChu(chuK + " " + sach3(String(x.tu || ""))))[0];
11868
11870
  if (LG) napHinhLogo(LG.slug);
@@ -13004,7 +13006,7 @@ function lapCuongMe(o) {
13004
13006
  if (s.logoTo && !s.logoY && !s.anNguoi) s.logoY = thanhO(s.f) ? 0.12 : 0.1;
13005
13007
  if (s.logoTo) the(a, bT, { loai: "cmSticker", logo: s.logoTo.slug, hex: s.logoTo.hex, x: 0.5, y: s.logoY ?? 0.34, r: s.logoY ? 0.05 : 0.13, tre: 0.12 });
13006
13008
  {
13007
- const st = s.st === "none" || s.bo === "anh" && !s.stX ? "" : s.st || "";
13009
+ const st = s.st === "none" || s.bo === "anh" && !s.stX && /^(tich|sao|chuot)$/.test(String(s.st || "tich")) ? "" : s.st || "";
13008
13010
  if (st && !(stTr[st] > s.f - 6)) {
13009
13011
  stTr[st] = s.f;
13010
13012
  the(a, bT, {
@@ -13484,9 +13486,10 @@ function veTrangTu(g, c, T, W4, H2, nen2, mo4) {
13484
13486
  P3.neK = coPip ? 1 : 0;
13485
13487
  }
13486
13488
  [dx, dy] = P3.ne;
13489
+ if (P3.dich && phat(P3.dich[1]) > 0) P3.dich = [dx, dy];
13487
13490
  }
13488
13491
  }
13489
- P3.dich = P3.dich || [0, 0];
13492
+ P3.dich = P3.dich || [dx, dy];
13490
13493
  P3.dich[0] += (dx - P3.dich[0]) * 0.35;
13491
13494
  P3.dich[1] += (dy - P3.dich[1]) * 0.35;
13492
13495
  g.save();
@@ -18134,7 +18137,9 @@ async function themKho(files) {
18134
18137
  if (n) {
18135
18138
  try {
18136
18139
  const ds2 = await layKho();
18137
- hoiNgoai("luu", "khoVideo", ds2.map((m) => ({ id: m.id, ten: m.ten, blob: m.blob, loai: m.loai, dai: m.dai || 0 })));
18140
+ const L = ds2.map((m) => ({ id: m.id, ten: m.ten, blob: m.blob, loai: m.loai, dai: m.dai || 0 }));
18141
+ globalThis.__khoNgoai = L;
18142
+ hoiNgoai("luu", "khoVideo", L);
18138
18143
  } catch (e) {
18139
18144
  }
18140
18145
  }
@@ -18169,11 +18174,16 @@ async function layKho() {
18169
18174
  ok();
18170
18175
  }
18171
18176
  });
18172
- if (!ds2.length) {
18173
- const ng = await hoiNgoai("lay", "khoVideo");
18177
+ {
18178
+ const G3 = globalThis, rong = !ds2.length;
18179
+ if (!G3.__khoNgoai) {
18180
+ const ng0 = await hoiNgoai("lay", "khoVideo");
18181
+ G3.__khoNgoai = Array.isArray(ng0) ? ng0 : [];
18182
+ }
18183
+ const ng = G3.__khoNgoai, coS = new Set(ds2.map((x) => x.id));
18174
18184
  if (Array.isArray(ng)) for (const m of ng) {
18175
- if (!m || !m.blob) continue;
18176
- if (d) {
18185
+ if (!m || !m.blob || coS.has(String(m.id))) continue;
18186
+ if (d && rong) {
18177
18187
  try {
18178
18188
  d.transaction("kho", "readwrite").objectStore("kho").put({ ten: m.ten, blob: m.blob, loai: m.loai, dai: m.dai }, m.id);
18179
18189
  } catch (e) {
@@ -18379,7 +18389,7 @@ async function chuanBiKho(kb, words, bao) {
18379
18389
  return !im || coVid && !im.laVideo && c.khoa.indexOf("anh:") === 0;
18380
18390
  });
18381
18391
  if (!can.length) return 0;
18382
- const mo4 = await moTaKho(kho6, bao), co = kho6.filter((a) => mo4[a.id]).map((a) => ({ id: a.id, ten: a.ten, mo: mo4[a.id], blob: a.blob, loai: a.loai, dai: a.dai }));
18392
+ const mo4 = await moTaKho(kho6, bao), co = kho6.map((a) => ({ id: a.id, ten: a.ten, mo: mo4[a.id] || "", blob: a.blob, loai: a.loai, dai: a.dai }));
18383
18393
  bao?.("AI gh\xE9p " + co.length + " \u1EA3nh / clip c\xF3 s\u1EB5n v\xE0o " + can.length + " c\u1EA3nh theo ngh\u0129a...");
18384
18394
  const chuan = (x) => String(x || "").toLowerCase().normalize("NFD").replace(/[^a-z0-9]/g, "");
18385
18395
  const gTay = {};
@@ -18393,7 +18403,7 @@ async function chuanBiKho(kb, words, bao) {
18393
18403
  });
18394
18404
  if (a) gTay[c.khoa] = a.id;
18395
18405
  }
18396
- const gAI = can.some((c) => !gTay[c.khoa]) ? await ghepKho(can.filter((c) => !gTay[c.khoa]), co) : {};
18406
+ const gAI = can.some((c) => !gTay[c.khoa]) ? await ghepKho(can.filter((c) => !gTay[c.khoa]), co.filter((x) => x.mo)) : {};
18397
18407
  const g = { ...gAI, ...gTay };
18398
18408
  globalThis.__ghepTay = Object.keys(gTay).length;
18399
18409
  let n = 0;
@@ -18871,6 +18881,10 @@ function ghepKichBan(words, kichBan) {
18871
18881
  // flow-src/services/exportFlow.ts
18872
18882
  async function handleExport(currentProject, setExporting, setExportedBlob, addLog, khung) {
18873
18883
  if (!currentProject || currentProject.timeline.length === 0) return;
18884
+ try {
18885
+ await loadFaceLandmarker();
18886
+ } catch (e) {
18887
+ }
18874
18888
  try {
18875
18889
  await napPhongViet();
18876
18890
  {
@@ -20692,7 +20706,7 @@ function datCauLenh(a) {
20692
20706
  on2 = true;
20693
20707
  window.addEventListener("message", async (ev) => {
20694
20708
  const d = ev.data;
20695
- if (!d || d.xvaiLoi111450 !== true) return;
20709
+ if (!d || d.xvaiLoi111649 !== true) return;
20696
20710
  const o = String(ev.origin || "");
20697
20711
  if (!(o.indexOf("https://flow.google.com") === 0 || o.indexOf("https://labs.google") === 0)) return;
20698
20712
  const tra = (kq) => {