xvai-loi 0.1.79 → 0.1.80

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 +114 -88
package/co.txt CHANGED
@@ -1 +1 @@
1
- xvaiLoi120008
1
+ xvaiLoi120014
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xvai-loi",
3
- "version": "0.1.79",
3
+ "version": "0.1.80",
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
@@ -9681,6 +9681,91 @@ function moNhanh(g, W4, H2, ve, r, them = "") {
9681
9681
  g.restore();
9682
9682
  }
9683
9683
 
9684
+ // flow-src/engine/khuon.ts
9685
+ var KHUON_TOPN = {
9686
+ ten: "Top N chi\u1EC1u s\xE2u (Captions)",
9687
+ 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."] },
9688
+ // 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)
9689
+ chu: { phut: [8, 18], caoMin: 0.042 },
9690
+ // caoMin: nét chữ nhấn (kể cả dấu) / H — đối thủ trung vị 0,042 (đo tay 23 dòng); chữ bị ép ngang thấp hơn → 2 dòng
9691
+ icon: { phut: 11.5 },
9692
+ cat: { moi10s: [4, 6], manhNguoi: 1.2, heChu: 0 },
9693
+ // manhNguoi: mẩu người nói kẹp giữa 2 cảnh ngắn hơn thì lấp (trước 0,6 — VD-236); heChu: khe giữa 2 cảnh liền cùng có chữ (trước 0,06 → chớp 2 khung người nói = 2 cú cắt thừa; bàn thử 13 video 12/10 00:0x: 0,06 → 0 cắt TB 5,44 → 4,39/10 s, chồng chữ 0/13 — cảnh trước đã hết theo giờ PHIM nhờ bT)
9694
+ nguoi: { phongToiDa: 1.8, matToiDa: 0.55 },
9695
+ // 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ỏ)
9696
+ lietKe: { xenKe: 2 },
9697
+ // video liệt kê: cứ thẻ bước thứ 2 → ảnh toàn khung + tiêu đề (đối thủ đổi kiểu, không lặp 1 khuôn thẻ)
9698
+ soTrenAnh: { phanDau: 1 / 3, toiDa: 2 },
9699
+ // cảnh CON SỐ ở 1/3 đầu → số đè lên ẢNH minh hoạ (đối thủ 1/3 đầu 83 % trám; số trên người nói không tính trám)
9700
+ bien: { dau: 1.5, cuoi: 2.5, ctaAnh: true }
9701
+ // không đặt ảnh trám ở 1,5 s đầu (móc; bàn thử 13 video: 3 → 1,5 s nâng 1/3 đầu T2 63→87, B05 23→42, B08 25→45, không video nào tụt) và 2,5 s cuối; vùng CTA VẪN có ảnh (đối thủ CTA 8,7 s vẫn trám)
9702
+ };
9703
+ 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;
9704
+ var sach2 = (x) => String(x || "").replace(/[.,!?;:…"“”]/g, "");
9705
+ function lapAnhTheoKhuon(kb, ws, K = KHUON_TOPN, toiDa = 12) {
9706
+ const W4 = (ws || []).filter((w) => w && w.text && w.t1 > w.t0);
9707
+ if (!kb || !Array.isArray(kb.canh) || W4.length < 20) return 0;
9708
+ const lo = (x) => String(x || "").toLocaleLowerCase("vi").replace(/[^\p{L}\p{N}\s]/gu, "").trim(), wl = W4.map((w) => lo(w.text));
9709
+ const timTu = (tu) => {
9710
+ const q = lo(tu).split(/\s+/).filter(Boolean).slice(0, 3);
9711
+ if (!q.length) return -1;
9712
+ for (let i = 0; i + q.length <= wl.length; i++) {
9713
+ let ok = true;
9714
+ for (let j = 0; j < q.length; j++) if (wl[i + j] !== q[j]) {
9715
+ ok = false;
9716
+ break;
9717
+ }
9718
+ if (ok) return i;
9719
+ }
9720
+ return -1;
9721
+ };
9722
+ const g = 60 / K.tram.phut, t0 = W4[0].t0 + K.bien.dau, t1 = W4[W4.length - 1].t1 - K.bien.cuoi;
9723
+ {
9724
+ let doi = 0;
9725
+ const tDau = t0 + (t1 - t0) * K.soTrenAnh.phanDau;
9726
+ for (const c of kb.canh) {
9727
+ if (doi >= K.soTrenAnh.toiDa || !c || c.kieu !== "so" || !c.tu) continue;
9728
+ const i = timTu(c.tu);
9729
+ if (i < 0 || W4[i].t0 < t0 || W4[i].t0 > tDau) continue;
9730
+ const cau = W4.slice(Math.max(0, i - 5), i + 10).map((w) => w.text).join(" ");
9731
+ c.kieu = "anh";
9732
+ c.soAnh = 1;
9733
+ c.en = 'Cinematic photorealistic vertical photo that illustrates the meaning of this Vietnamese sentence: "' + cau + '". ' + K.tram.nhanVat[doi % 2] + " Natural light, no text, no captions.";
9734
+ doi++;
9735
+ }
9736
+ }
9737
+ const moc = kb.canh.filter(
9738
+ (c) => c && c.tu && /^(anh|ds)$/.test(String(c.kieu))
9739
+ /* 'so' vẽ thành chữ to trên người / ô tròn (cut/tron) — không phải trám */
9740
+ ).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);
9741
+ let noi2 = 0;
9742
+ for (let i = 0; i < W4.length; i++) {
9743
+ if (W4[i].t0 < t0 || W4[i].t1 > t1) continue;
9744
+ noi2 += W4[i].t1 - W4[i].t0 + (i + 1 < W4.length ? Math.min(0.4, Math.max(0, W4[i + 1].t0 - W4[i].t1)) : 0);
9745
+ }
9746
+ const mocDu = kb.canh.filter((c) => c && c.tu && /^(anh|ds|vat)$/.test(String(c.kieu))).map((c) => timTu(c.tu)).filter((i) => i >= 0 && W4[i].t0 > t0 && W4[i].t0 < t1).length;
9747
+ if (mocDu / Math.max(1e-6, noi2 / 60) >= 0.9 * K.tram.phut) return 0;
9748
+ const pts = [t0, ...moc, t1];
9749
+ let them = 0;
9750
+ for (let k = 0; k + 1 < pts.length && them < toiDa; k++) {
9751
+ const a0 = pts[k], b0 = pts[k + 1];
9752
+ if (b0 - a0 < 1.6 * g) continue;
9753
+ const n = Math.max(1, Math.round((b0 - a0) / g) - 1);
9754
+ for (let m = 1; m <= n && them < toiDa; m++) {
9755
+ const tm = a0 + (b0 - a0) * m / (n + 1), i0 = W4.findIndex((w) => w.t0 >= tm);
9756
+ if (i0 < 0) continue;
9757
+ const nd = [];
9758
+ 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);
9759
+ if (nd.length < 2) continue;
9760
+ 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(" ");
9761
+ if (timTu(tu) !== i) continue;
9762
+ 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." });
9763
+ them++;
9764
+ }
9765
+ }
9766
+ return them;
9767
+ }
9768
+
9684
9769
  // flow-src/engine/boCuc.ts
9685
9770
  var BC = {
9686
9771
  tren: 0.1,
@@ -9782,7 +9867,7 @@ function datKhoiChu(g, kc, coThanh, coTach, vungTruoc, choThu = false, WH = 9 /
9782
9867
  }
9783
9868
  const yc = y0 + h / 2, vung2 = !mat ? "tu-do" : hop4[3] <= dinh ? "tren-dau" : lop === "sau" ? "sau-dau" : hop4[2] < mat[0] || hop4[0] > mat[2] ? cx < tam2 ? "canh-trai" : "canh-phai" : yc > 0.6 ? "duoi" : "nguc";
9784
9869
  const uu = { "tren-dau": 0, "sau-dau": 0.12, "canh-trai": 0.1, "canh-phai": 0.1, nguc: 0.22, duoi: 0.3, "tu-do": 0.1 };
9785
- const diem2 = 100 * (1 - (uu[vung2] ?? 0.2)) * (0.35 + 0.65 * k) - 25 * (lop === "truoc" ? Math.max(0, p - 0.6) : p);
9870
+ const diem2 = (100 * (1 - (uu[vung2] ?? 0.2)) * (0.35 + 0.65 * k) - 25 * (lop === "truoc" ? Math.max(0, p - 0.6) : p)) * (kc.px && 0.92 * kc.px * k < KHUON_TOPN.chu.caoMin ? 0.6 : 1);
9786
9871
  ung.push({ x: cx, y: yc, k, lop, vung: vung2, diem: diem2 });
9787
9872
  };
9788
9873
  for (let k = 1; k >= BC.kMin - 1e-6; k -= 0.05) for (let y0 = top; y0 <= BC.duoi; y0 += 0.01) {
@@ -9817,91 +9902,6 @@ function datKhoiChu(g, kc, coThanh, coTach, vungTruoc, choThu = false, WH = 9 /
9817
9902
  return ra;
9818
9903
  }
9819
9904
 
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], caoMin: 0.042 },
9826
- // caoMin: nét chữ nhấn (kể cả dấu) / H — đối thủ trung vị 0,042 (đo tay 23 dòng); chữ bị ép ngang thấp hơn → 2 dòng
9827
- icon: { phut: 11.5 },
9828
- cat: { moi10s: [4, 6], manhNguoi: 1.2, heChu: 0 },
9829
- // manhNguoi: mẩu người nói kẹp giữa 2 cảnh ngắn hơn thì lấp (trước 0,6 — VD-236); heChu: khe giữa 2 cảnh liền cùng có chữ (trước 0,06 → chớp 2 khung người nói = 2 cú cắt thừa; bàn thử 13 video 12/10 00:0x: 0,06 → 0 cắt TB 5,44 → 4,39/10 s, chồng chữ 0/13 — cảnh trước đã hết theo giờ PHIM nhờ bT)
9830
- nguoi: { phongToiDa: 1.8, matToiDa: 0.55 },
9831
- // 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ỏ)
9832
- lietKe: { xenKe: 2 },
9833
- // video liệt kê: cứ thẻ bước thứ 2 → ảnh toàn khung + tiêu đề (đối thủ đổi kiểu, không lặp 1 khuôn thẻ)
9834
- soTrenAnh: { phanDau: 1 / 3, toiDa: 2 },
9835
- // cảnh CON SỐ ở 1/3 đầu → số đè lên ẢNH minh hoạ (đối thủ 1/3 đầu 83 % trám; số trên người nói không tính trám)
9836
- bien: { dau: 1.5, cuoi: 2.5, ctaAnh: true }
9837
- // không đặt ảnh trám ở 1,5 s đầu (móc; bàn thử 13 video: 3 → 1,5 s nâng 1/3 đầu T2 63→87, B05 23→42, B08 25→45, không video nào tụt) và 2,5 s cuối; vùng CTA VẪN có ảnh (đối thủ CTA 8,7 s vẫn trám)
9838
- };
9839
- 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;
9840
- var sach2 = (x) => String(x || "").replace(/[.,!?;:…"“”]/g, "");
9841
- function lapAnhTheoKhuon(kb, ws, K = KHUON_TOPN, toiDa = 12) {
9842
- const W4 = (ws || []).filter((w) => w && w.text && w.t1 > w.t0);
9843
- if (!kb || !Array.isArray(kb.canh) || W4.length < 20) return 0;
9844
- const lo = (x) => String(x || "").toLocaleLowerCase("vi").replace(/[^\p{L}\p{N}\s]/gu, "").trim(), wl = W4.map((w) => lo(w.text));
9845
- const timTu = (tu) => {
9846
- const q = lo(tu).split(/\s+/).filter(Boolean).slice(0, 3);
9847
- if (!q.length) return -1;
9848
- for (let i = 0; i + q.length <= wl.length; i++) {
9849
- let ok = true;
9850
- for (let j = 0; j < q.length; j++) if (wl[i + j] !== q[j]) {
9851
- ok = false;
9852
- break;
9853
- }
9854
- if (ok) return i;
9855
- }
9856
- return -1;
9857
- };
9858
- const g = 60 / K.tram.phut, t0 = W4[0].t0 + K.bien.dau, t1 = W4[W4.length - 1].t1 - K.bien.cuoi;
9859
- {
9860
- let doi = 0;
9861
- const tDau = t0 + (t1 - t0) * K.soTrenAnh.phanDau;
9862
- for (const c of kb.canh) {
9863
- if (doi >= K.soTrenAnh.toiDa || !c || c.kieu !== "so" || !c.tu) continue;
9864
- const i = timTu(c.tu);
9865
- if (i < 0 || W4[i].t0 < t0 || W4[i].t0 > tDau) continue;
9866
- const cau = W4.slice(Math.max(0, i - 5), i + 10).map((w) => w.text).join(" ");
9867
- c.kieu = "anh";
9868
- c.soAnh = 1;
9869
- c.en = 'Cinematic photorealistic vertical photo that illustrates the meaning of this Vietnamese sentence: "' + cau + '". ' + K.tram.nhanVat[doi % 2] + " Natural light, no text, no captions.";
9870
- doi++;
9871
- }
9872
- }
9873
- const moc = kb.canh.filter(
9874
- (c) => c && c.tu && /^(anh|ds)$/.test(String(c.kieu))
9875
- /* 'so' vẽ thành chữ to trên người / ô tròn (cut/tron) — không phải trám */
9876
- ).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);
9877
- let noi2 = 0;
9878
- for (let i = 0; i < W4.length; i++) {
9879
- if (W4[i].t0 < t0 || W4[i].t1 > t1) continue;
9880
- noi2 += W4[i].t1 - W4[i].t0 + (i + 1 < W4.length ? Math.min(0.4, Math.max(0, W4[i + 1].t0 - W4[i].t1)) : 0);
9881
- }
9882
- const mocDu = kb.canh.filter((c) => c && c.tu && /^(anh|ds|vat)$/.test(String(c.kieu))).map((c) => timTu(c.tu)).filter((i) => i >= 0 && W4[i].t0 > t0 && W4[i].t0 < t1).length;
9883
- if (mocDu / Math.max(1e-6, noi2 / 60) >= 0.9 * K.tram.phut) return 0;
9884
- const pts = [t0, ...moc, t1];
9885
- let them = 0;
9886
- for (let k = 0; k + 1 < pts.length && them < toiDa; k++) {
9887
- const a0 = pts[k], b0 = pts[k + 1];
9888
- if (b0 - a0 < 1.6 * g) continue;
9889
- const n = Math.max(1, Math.round((b0 - a0) / g) - 1);
9890
- for (let m = 1; m <= n && them < toiDa; m++) {
9891
- const tm = a0 + (b0 - a0) * m / (n + 1), i0 = W4.findIndex((w) => w.t0 >= tm);
9892
- if (i0 < 0) continue;
9893
- const nd = [];
9894
- 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);
9895
- if (nd.length < 2) continue;
9896
- 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(" ");
9897
- if (timTu(tu) !== i) continue;
9898
- 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." });
9899
- them++;
9900
- }
9901
- }
9902
- return them;
9903
- }
9904
-
9905
9905
  // flow-src/engine/veCuongMe.ts
9906
9906
  var luoiAnhCache = /* @__PURE__ */ new Map();
9907
9907
  var matAnhCache = /* @__PURE__ */ new Map();
@@ -10271,7 +10271,7 @@ function datChuNhan(g, W4, H2, F, giant, chu22, pxG, pxC, kieuG, maxW, tren = 0.
10271
10271
  g.restore();
10272
10272
  return w;
10273
10273
  })));
10274
- return { nd, c: datKhoiChu(nc, { h: nd / H2, w: wb / W4 }, tren >= 0.1, coTach, vungCu, choThu, W4 / H2) };
10274
+ return { nd, c: datKhoiChu(nc, { h: nd / H2, w: wb / W4, px: aa2.px / H2 }, tren >= 0.1, coTach, vungCu, choThu, W4 / H2) };
10275
10275
  };
10276
10276
  let A2 = thu2(a, giant), txtA = giant, aa = a;
10277
10277
  if (String(giant || "").indexOf(String.fromCharCode(10)) >= 0 && A2.c.k < 0.85) {
@@ -10282,6 +10282,32 @@ function datChuNhan(g, W4, H2, F, giant, chu22, pxG, pxC, kieuG, maxW, tren = 0.
10282
10282
  aa = a1;
10283
10283
  }
10284
10284
  }
10285
+ {
10286
+ const ws3 = String(txtA || "").split(/\s+/).filter(Boolean);
10287
+ if (0.92 * aa.px * A2.c.k / H2 < KHUON_TOPN.chu.caoMin && ws3.length >= 4) {
10288
+ g.save();
10289
+ g.font = "900 " + pxG.toFixed(1) + "px " + FBc;
10290
+ const tw = (x) => g.measureText(x).width, mt = tw(ws3.join(" ")) / 3, d3 = [];
10291
+ let cur = "";
10292
+ for (const w of ws3) {
10293
+ const nx = cur ? cur + " " + w : w;
10294
+ if (cur && tw(nx) > mt * 1.15 && d3.length < 2) {
10295
+ d3.push(cur);
10296
+ cur = w;
10297
+ } else cur = nx;
10298
+ }
10299
+ d3.push(cur);
10300
+ g.restore();
10301
+ if (d3.length === 3) {
10302
+ const g3 = d3.join(String.fromCharCode(10)), a3 = do1(g3, pxG, kieuG), B3 = thu2(a3, g3);
10303
+ if (B3.c.k * a3.px > A2.c.k * aa.px * 1.05) {
10304
+ A2 = B3;
10305
+ txtA = g3;
10306
+ aa = a3;
10307
+ }
10308
+ }
10309
+ }
10310
+ }
10285
10311
  const c = A2.c, k2 = c.k, hG2 = aa.h * k2, hC2 = b.h * k2, y02 = c.y * H2 - A2.nd * k2 / 2;
10286
10312
  if (k2 <= 0) return ghiCho({ yG: 0.5, yC: 0.5, pxG: 0.01, pxC: 0.01, truoc: true, txt: " ", vung: c.vung });
10287
10313
  vungCu = { x: c.x, y: c.y };
@@ -20887,7 +20913,7 @@ function datCauLenh(a) {
20887
20913
  on2 = true;
20888
20914
  window.addEventListener("message", async (ev) => {
20889
20915
  const d = ev.data;
20890
- if (!d || d.xvaiLoi120008 !== true) return;
20916
+ if (!d || d.xvaiLoi120014 !== true) return;
20891
20917
  const o = String(ev.origin || "");
20892
20918
  if (!(o.indexOf("https://flow.google.com") === 0 || o.indexOf("https://labs.google") === 0)) return;
20893
20919
  const tra = (kq) => {