Description: ბრაუზერში მუშაობადი AI, WASM ნაკადები, სამიზნე ზომაზე შეკუმშვა, inpainting და 3D LUT-ები ერთ HTML ფაილში...

შენ ვებ დეველოპერი ხარ თუ ბრაუზერის ექსპერტი? 7 ტესტი, რომელიც ჩავიჭერი ფოტო რედაქტორის აგებისას, რომელიც შენს ფოტოებს არასდროს ტვირთავს

აღწერა: მოწყობილობაზე მუშაობადი AI, WASM ნაკადები, სამიზნე ზომაზე შეკუმშვა, inpainting და 3D LUT-ები ერთ HTML ფაილში. 7 რეალური გაკვეთილი APIC Web-ის აგებიდან.

ქართველი ვებ დეველოპერების უმეტესობას შეუძლია ფორმის აწყობა, API-დან მონაცემის წამოღება და div-ის ცენტრში მოთავსება.

ბრაუზერის ექსპერტები კი იციან, რის კეთებაზე უარს ამბობს ბრაუზერი, რა ხდება ტელეფონზე შენი ლეპტოპის ნაცვლად და როგორ გამოუშვა ნამდვილი პროგრამა სერვერის გარეშე.

მე ეს APIC Web-ის აგებისას გავიგე: უფასო ფოტო რედაქტორი, ფონის მომხსნელი, ობიექტის მომხსნელი, კონვერტორი და კომპრესორი, სადაც შენი ფოტოები შენს მოწყობილობას არასდროს ტოვებს. ატვირთვის რიგი არ არის, backend არ არის, და ყველაფერი ერთი HTML ფაილია, რომელიც GitHub Pages-ზეა განთავსებული.

ქვემოთ ყველა ტესტი ამ აგების რეალური ბაგი ან დიზაინის გადაწყვეტილებაა. შეაფასე საკუთარი თავი გულწრფელად. 👇


ტესტი 1: რატომ არასდროს სრულდებოდა ჩემი AI ნაბიჯი ტელეფონებზე უხმოდ?

APIC აშვებს AI მოდელებს ბრაუზერში ONNX Runtime Web-ით (WebAssembly). Multi-threaded WASM-ს სჭირდება SharedArrayBuffer, ხოლო ამისთვის საჭიროა სპეციალური response headers (COOP/COEP). ჩვეულებრივი სტატიკური ჰოსტი, როგორიცაა GitHub Pages, მათ არ აგზავნის, ამიტომ crossOriginIsolated არის false.

დესკტოპზე runtime ჩვეულებრივ მშვიდად ეშვება ალტერნატიულ რეჟიმში. ტელეფონებზე ასე ხშირად არ ხდება, და AI ნაბიჯი უბრალოდ ჩერდება შეცდომის გარეშე. გამოსავალი იყო, რომ აღარ დავყრდნობოდი fallback-ს:

// Static hosts can't send COOP/COEP, so threads aren't available.
// Force the one configuration that behaves the same everywhere.
ort.env.wasm.numThreads = 1;
ort.env.wasm.proxy = false;

const session = await ort.InferenceSession.create(modelBytes, {
  executionProviders: ['wasm'],
  enableCpuMemArena: false,
  enableMemPattern: false,
});

სადაც headers ხელმისაწვდომია, APIC ამოწმებს self.crossOriginIsolated-ს, სანამ ერთზე მეტ ნაკადს მოითხოვს.

დეველოპერი: "ჩემს ლეპტოპზე მუშაობს."
ექსპერტი: იცის, რომ "მშვიდად ეშვება fallback-ით" არის მტკიცება, რომელიც რეალურ ტელეფონზე უნდა შემოწმდეს, და არა დაპირება.


ტესტი 2: შეგიძლია ნელი ჩამოტვირთვა ჩამოხსნილისგან განასხვაო?

APIC-ის AI მოდელები დიდია: 5 MB (Lite), 44 MB (Fast), 176 MB (Maximum) ფონის მოსაშორებლად და დაახლოებით 208 MB უმაღლესი ხარისხის ობიექტის მომხსნელისთვის. ფიქსირებულმა 30-წამიანმა timeout-მა ყოველი ნელი ტელეფონის კავშირი გაწყვიტა.

ამიტომ timeout არის დაყენებაზე დაფუძნებული (stall-based): ვწყვეტ მხოლოდ მაშინ, თუ 40 წამის განმავლობაში არცერთი ბაიტი არ მოდის. დიდ მოდელს ცუდ Wi-Fi-ზე შეუძლია იმდენი იმუშაოს, რამდენიც სჭირდება. მკვდარ ბმულს კი არა. ამის შემდეგ მოდელი Cache API-ში ხვდება, რათა მეორე გაშვება მყისიერი იყოს:

const CACHE = 'apic-models-v1';
const cache = await caches.open(CACHE);

let hit = await cache.match(url);
if (hit) return hit.arrayBuffer();           // cached: no download

const bytes = await downloadWithStallTimeout(url);   // abort only if the stream goes quiet
await cache.put(url, new Response(bytes));   // wrapped in try/catch: private mode & quota can fail
return bytes;

და თუ მოდელი საერთოდ ვერ ჩაიტვირთება, ინსტრუმენტი ეშვება უფრო მარტივ ვარიანტზე და არ ბრუნდება შეცდომით: Ultra (LaMa) → MI-GAN → სწრაფი შევსება.

დეველოპერი: fetch() timeout-ით.
ექსპერტი: ზომავს პროგრესს, ინახავს შედეგს და ყოველთვის აქვს გეგმა B.


ტესტი 3: შეუძლია შენს აპს "200 KB-ზე ნაკლები" მიაღწიოს გამოცნობის გარეშე?

ატვირთვის ფორმები წერენ "მაქსიმუმ 200 KB" და მომხმარებლები ხარისხის სლაიდერით თამაშობენ რულეტკას. APIC-ის Compress ინსტრუმენტი ამის ნაცვლად JPEG ხარისხზე binary search-ს ატარებს:

async function findQualityForTarget(canvas, targetBytes) {
  let lo = 0.05, hi = 0.98, best = null;
  for (let i = 0; i < 7; i++) {
    const mid = (lo + hi) / 2;
    const blob = await toBlob(canvas, 'image/jpeg', mid);
    if (blob.size <= targetBytes) { best = { blob, q: mid }; lo = mid; }  // fits: try higher quality
    else { hi = mid; }                                                   // too big: go lower
  }
  return best;
}

შვიდი ენკოდირება პოულობს უმაღლეს ხარისხს, რომელიც მაინც ეტევა. თუ უმცირესი ხარისხიც კი ძალიან დიდია, APIC სურათს დაახლოებით 20%-ით ამცირებს და ისევ ეძებს, მაქსიმუმ 8-ჯერ. თუ მაინც ვერ მიაღწევს, ის გიჩვენებს რეალურ ზომას და არ ათამაშებს.

დეველოპერი: quality = 0.7 და იმედი.
ექსპერტი: გამოცნობას ძიებად აქცევს და გულწრფელია, როცა პასუხია "ვერ ვახერხებ".


ტესტი 4: რატომ გახდა ჩემი გამჭვირვალე PNG JPEG-ად შავი?

JPEG-ს alpha არხი არ აქვს. როცა გამჭვირვალე პიქსელების მქონე canvas JPEG-ად იკუმშება, ეს პიქსელები შავად გამოდის. ფონის მოშორების შემდეგ (რომელიც ბევრ გამჭვირვალობას ქმნის) ეს უსიამოვნო სიურპრიზია.

გამოსავალი არის ჯერ თეთრად შეღებვა და შემდეგ სურათის ზემოდან დახატვა:

function flattenToWhite(src) {
  const out = document.createElement('canvas');
  out.width = src.width; out.height = src.height;
  const ctx = out.getContext('2d');
  ctx.fillStyle = '#fff';
  ctx.fillRect(0, 0, out.width, out.height);
  ctx.drawImage(src, 0, 0);
  return out;
}

APIC ასევე გეუბნება, რომელი ფორმატები ინახავს გამჭვირვალობას (PNG, WebP) და რომელი არა, პირდაპირ Convert პანელში.

დეველოპერი: ივარაუდებს, რომ canvas მხოლოდ პიქსელებია.
ექსპერტი: იცის, რომ ყოველ გამოსატან ფორმატს აქვს თავისი წესები alpha-ზე.


ტესტი 5: ამუშავებ მთელ სურათს, თუ მხოლოდ შეცვლილ ნაწილს?

ობიექტის მოსაშორებლად ვუშვებ inpainting მოდელს (LaMa, Fourier-convolution ქსელი, ან უფრო მსუბუქი MI-GAN). LaMa მუშაობს ფიქსირებულ 512×512 ფანჯარაზე, ამიტომ 12-მეგაპიქსელიან ფოტოზე მისი გამოყენება ნელი და ბუნდოვანი იქნებოდა.

APIC ამუშავებს მხოლოდ იმ არეს, რომელიც შენი ფუნჯის გარშემოა:

  1. აიღე არე маска-ს გარშემო (მინიმუმ 512 ნატიური პიქსელი, თუ ფოტო იძლევა).
  2. გაუშვი მოდელი მხოლოდ ამ ამონაჭერზე.
  3. დაასწორე კიდე box blur-ით, მოარგე შევსების ფერი გარემოს და დაუბრუნე film grain, რათა არ ჩანდეს "ზედმეტად სუფთა".
  4. ჩასვი უკან.

პატარა რედაქტირება, პატარა გამოთვლა, და ფოტოს დანარჩენი ნაწილი შეუხებელი რჩება.

დეველოპერი: მოდელს მთელ სურათზე უშვებს.
ექსპერტი: ჯერ ამცირებს ამოცანას, შემდეგ შედეგს ისე ურევს უკან, რომ ხაზი არავის არ ეტყობა.


ტესტი 6: შეგიძლია მთელი ფერადი გრейდინგი .cube LUT-ად ექსპორტირო?

APIC-ს აქვს curves, 8-ზოლიანი HSL მიქსერი და 3-way ფერადი გრейდინგი. ხალხს სურდა ეს გრейდები DaVinci Resolve-ში ან Premiere-ში გამოეყენებინა. .cube ფაილი არის 3D lookup table: ყოველი შესასვლელი ფერისთვის ნათქვამია, რა ფერი გამოდის.

ხრიკი ასეთია: არ გჭირდება შენი pipeline-ის უკუინჟინერია. გაატარე identity grid ფერებიდან იმავე პიქსელურ ფუნქციაში და ჩაწერე, რა გამოდის:

const N = 33;                       // 33×33×33 lattice
const buf = new Uint8ClampedArray(N * N * N * 4);
let i = 0;
for (let b = 0; b < N; b++)
  for (let g = 0; g < N; g++)
    for (let r = 0; r < N; r++) {   // red changes fastest, as .cube requires
      buf[i++] = Math.round(r / (N - 1) * 255);
      buf[i++] = Math.round(g / (N - 1) * 255);
      buf[i++] = Math.round(b / (N - 1) * 255);
      buf[i++] = 255;
    }

processPixels(buf, gradeWithoutSpatialEffects);   // same code that edits your photo

const lines = ['TITLE "APIC grade"', 'LUT_3D_SIZE 33',
               'DOMAIN_MIN 0.0 0.0 0.0', 'DOMAIN_MAX 1.0 1.0 1.0', ''];
for (let j = 0; j < buf.length; j += 4)
  lines.push(`${(buf[j]/255).toFixed(6)}${(buf[j+1]/255).toFixed(6)}${(buf[j+2]/255).toFixed(6)}`);

ერთი დაჭერა: LUT-ს შეუძლია მხოლოდ ფერის ოპერაციების შენახვა. Clarity, sharpen, vignette და grain დამოკიდებულია მეზობელ პიქსელებზე, ამიტომ ისინი გამოირიცხება და ინტერფეისი ამას ამბობს.

დეველოპერი: ექსპორტირებს ეკრანის ანაბეჭდს სტილზე.
ექსპერტი: თავად ფუნქციას უსინჯავს.


ტესტი 7: რატომ გამოიყურება შენი გადიდებული ან შემცირებული სურათი რბილად?

ctx.drawImage(img, 0, 0, smallW, smallH);   // one big jump: soft, aliased

დიდი სურათის ერთი drawImage გამოძახებით შემცირება ბურუსიანად გამოიყურება. APIC-ის Resize ინსტრუმენტი სურათს ნაბიჯ-ნაბიჯ ანახევრებს, სანამ სამიზნედან 2×-ში არ მოხვდება, და შემდეგ ერთ საბოლოო გავლას აკეთებს:

function highQualityResize(src, targetW, targetH) {
  let cur = src, w = src.width, h = src.height;
  while (w > targetW * 2 || h > targetH * 2) {
    const nw = Math.max(targetW, Math.round(w / 2));
    const nh = Math.max(targetH, Math.round(h / 2));
    const step = document.createElement('canvas');
    step.width = nw; step.height = nh;
    const c = step.getContext('2d');
    c.imageSmoothingEnabled = true;
    c.imageSmoothingQuality = 'high';
    c.drawImage(cur, 0, 0, nw, nh);
    cur = step; w = nw; h = nh;
  }
  // ...then one last high-quality pass onto the exact target size
}

დეველოპერი: drawImage ერთხელ და წინ.
ექსპერტი: იცის, რომ ოპერაციების თანმიმდევრობა ცვლის შედეგს.


ბონუსი: როგორ გამოუშვა Web Worker ერთ HTML ფაილში?

build ნაბიჯი არ არის, ცალკე worker.js არ არის. APIC worker-ის კოდს სტრინგად ინახავს, აქცევს Blob-ად და უშვებს Blob URL-იდან:

const SRC = `/* worker code as a string */`;
const worker = new Worker(
  URL.createObjectURL(new Blob([SRC], { type: 'application/javascript' }))
);

მძიმე inpainting მუშაობს მთავარი ნაკადის გარეთ, და მთელი აპი მაინც ერთი ფაილია, რომელიც ყველგან შეიძლება განთავსდეს.


სცადე თავად

APIC აგებულია კომპანიის Akhouri Systems-ის მიერ. ის ბრაუზერში მუშაობს, და შენი სურათები არასდროს იტვირთება. ბრაუზერი მხოლოდ AI მოდელის ფაილებს ჩამოტვირთავს (Hugging Face-იდან), რომლებიც პირველი გაშვების შემდეგ ინახება ქეშში. გულწრფელად ვიტყვი კომპრომისებზე: რედაქტირებისთვის ანგარიში არ არის საჭირო, Google-ით შესვლა ერთი შეხებით მხოლოდ ექსპორტისას გჭირდება, ხოლო ვებ ვერსიაში ერთი პატარა banner რეკლამა ჩანს, რომ უფასო დარჩეს. ოფლაინ PC აპს რეკლამა არ აქვს.

აპი რა არის რას ამტკიცებს მიიღე
🖼️ APIC Web რედაქტირება, პროფესიონალური ფერის ინსტრუმენტები, ობიექტების მოშორება, ფონის მოშორება AI-ით, ზომის შეცვლა, კონვერტაცია, შეკუმშვა, 15 სოციალური ქსელის პრესეტი, batch ZIP ტესტები 1-7 APIC Web-ის გახსნა
💻 APIC for PC Windows ვერსია, მუშაობს სრულად ოფლაინ, ანგარიშის გარეშე დესკტოპის ტყუპი ჩამოტვირთვა (zip)

თუ სწავლობ, როგორ მუშაობს ბრაუზერი ტუტორიალის მიღმა, გახსენი, ჩააგდე ფოტო, შემდეგ გახსენი DevTools და ნახე, რა ხდება შიგნით. ეს ყველაზე სწრაფი გზაა, რომელიც ვიცი დონის ასამაღლებლად.


შენი ქულა

  • 0-2 ტესტი იცი: შენ ვებ დეველოპერი ხარ. კარგი დასაწყისია, ახლა გატეხე რამე რეალურ ტელეფონზე.
  • 3-5: მყარი. რაღაც რეალური უკვე გამოუშვი.
  • 6-7: შენ ბრაუზერის ექსპერტი ხარ. მოდი კომენტარებში მეკამათე.

რომელი ტესტი ჩაიჭერი პირველად? ჩემი იყო [AI ნაბიჯი, რომელიც დესკტოპზე მუშაობდა და ტელეფონებზე უხმოდ ჩერდებოდა]. დაწერე შენი ქვემოთ 👇

ორიგინალი: DEV Community · ავტორი: Akhouri Anmol Kumar

ყველა სტატია
სიახლეები

მიიღეთ ახალი სტატიები

თვეში ერთხელ - რჩევები ვებ დიზაინზე, ახალი პროექტები და სტუდიის სიახლეები.

დარეკვა შეკვეთა