Nest می‌تواند آرشیوکنندهٔ کارت‌های Magic باشد

از Brenner Cruvinel • زمان مطالعه 6 دقیقه

دوستم فلیپه ناوارو دارد pasta.cards را می‌سازد، یک اپ متن‌باز برای مدیریت کلکسیون و دک‌های Commander. محلی اجرا می‌شود، همه‌چیز را در SQLite نگه می‌دارد، و برای اینکه آفلاین کار کند تصویر هر کارت Magic را که تا حالا چاپ شده دانلود می‌کند، در دو نسخه: کل کارت و فقط تصویرسازی. روی مک من این شد ۸۳ هزار JPG و ۷ گیگابایت. هر کارتی که وجود دارد، دو بار، روی دیسک من، و Finder که برای باز کردن پوشه کند می‌شود.

چیزی که در این عدد توجهم را گرفت حجم نبود، دیسک ارزان است. ساختار بود. کارت‌ها قاب، کادر متن، تایپوگرافی و نماد مانا را با هم شریک‌اند. و پایگاه داده‌ای که کنارش است نشان می‌دهد تقریباً نیمی از چاپ‌ها تصویری را دوباره به کار می‌برند که قبلاً روی کارت دیگری آمده. یک JPG تنها از هیچ‌کدام از این‌ها خبر ندارد. یک کاتالوگ خوب به جای کپی کردن ارجاع می‌دهد، و یک کدک خوب برای پیکسلی که از همسایه‌اش قابل پیش‌بینی است بیت خرج نمی‌کند. من هر دو را به یک دلیل دوست دارم.

Nest را کنار دستم داشتم، پایگاه دادهٔ برداری تک‌فایلی که امسال دارم می‌سازم، و از ماه اوت تصویر هم نگه می‌دارد. سؤالی که آن صبح پرسیدم خیلی ساده‌لوحانه‌تر از همهٔ چیزهایی بود که بعدش آمد: چطور کار می‌کند، آن را به ویدیو تبدیل می‌کند؟ من ۳۸ هزار تصویر و یک پایگاه داده دارم، با این‌ها چه می‌کند؟

آن را به ویدیو تبدیل می‌کند؟

واقعاً به ویدیو تبدیلش می‌کند. هر تصویر یک فریم از یک جریان AV1 درون فایل می‌شود، و جست‌وجو روی بردارهایی اجرا می‌شود که از فریم‌های رمزگشایی‌شده گرفته شده‌اند، نه از JPEG اصلی. این عمدی است: ایندکس باید چیزی را توصیف کند که فایل ارائه می‌دهد، و چیزی که فایل ارائه می‌دهد فریمِ بعد از کدک است. کدک ویدیو بهینه‌ترین فناوری فشرده‌سازی تصویری است که وجود دارد، پس چیزی که شبیه وصله‌پینه به نظر می‌رسد فقط استفاده از چند دهه کار دیگران است.

این را قبلاً روی پوست اندازه گرفته بودم. درماتوسکوپی، لام‌های بیوپسی، صفحه‌های کتاب‌های قدیمی، دیتاست‌هایی که به خاطر کارم در Hoff دم دستم بود. چیزی که آن عددها به من یاد دادند این بود که میزان فشرده‌سازی ویژگی حوزه است، نه کدک. همان انکودر، همان تنظیم: درماتوسکوپی ۱۵۱ برابر فشرده شد و صفحهٔ کتاب ۴ برابر. پوست صاف خوب فشرده می‌شود چون جزئیات کمی برای نگه‌داشتن دارد. حروف ریز برعکس است، هر لبه بیت خرج دارد.

کارت Magic حروف ریز دارد. قابی دارد که در همهٔ کارت‌ها یکی است و کدک ممکن است از آن استفاده کند یا نکند. چاپ‌های مجدد از همان تصویر دارد، چیزی که درماتوسکوپی ندارد. و یک الزام محصولی دارد که هیچ معیار جست‌وجویی آن را نمی‌سنجد: کاشی دک باید روی صفحهٔ اپ زیبا دیده شود. فکر می‌کردم سؤال این است که چقدر فشرده می‌شود. بود، اما برای مدت کوتاهی.

پیش از اجرای هر چیزی، با آرامش بیشتری به پوشهٔ خام نگاه کردم و پوشه غافلگیری‌های خودش را داشت. نیمی از حجم، نسخهٔ بُرش‌خوردهٔ تصویر بود، و اولین فکرم این بود که دورش بریزم و هر وقت لازم شد از کارت کامل برش بزنم. یک ایجنت کد اپ را خواند و با خبر بد برگشت: پایگاه داده هیچ مختصات برشی نگه نمی‌دارد و اپ مستقیماً از نسخهٔ بُرش‌خورده در کاشی‌های دک استفاده می‌کند. تصویر برش‌خورده یک کلاس مستقل است، نه مشتق. و کنار پوشهٔ تصاویر یک دایرکتوری به اسم _redundant بود، با هفت گیگ دیگر کپی از چیزهایی که از قبل آنجا بودند. آن یکی را بی‌رحمانه پاک کردم.

اولین build

نسخهٔ آزمایشی با چند صد کارت پیش از اینکه کاری بکند با segfault مرد. بایندینگ پایتون Nest بدون فلگی کامپایل شده بود که می‌گوید «از پایتونِ همین پروسه استفاده کن، پایتون خودت را نیاور»، و پایتونی که من استفاده می‌کنم استاتیک است، پس دو مفسر سر یک حافظه دعوا می‌کردند. یک فلگ و تمام. باگی کوچک، و از آن نوعی که مرا بدگمان می‌کند: build چند پیش‌فرض محیطی دیگر را بی‌آنکه اعلام کند با خودش حمل می‌کند؟

با آن فلگ، build کامل در پس‌زمینه اجرا شد و یکی از ویدیوها را در پلیر باز کردم. کارت‌ها می‌گذشتند، هر ثانیه یکی، چهل دقیقه کارت. اولین فرضیه‌ام این بود که انکودر فریم‌ها را تکرار می‌کند تا هر کارت روی صفحه بماند، و می‌شود این را حذف کرد. یک خط ffprobe فرضیه را کشت: یک فریم برای هر کارت، و مدت زمان فقط یک برچسب زمانی در کانتینر است و بایتی هزینه ندارد.

۷ گیگابایت شد ۱٫۹ گیگابایت، با جست‌وجوی تصویری که رویش کار می‌کرد. از همان بار اول اجرا شد، و این در پروژه‌های من آن‌قدر نادر است که بدگمان شوم. بعد پوشهٔ خروجی را باز کردم.

آرشیوکننده‌ای که ۳۸ فایل MP4 کنارش است آرشیوکننده نیست

۳۸ فایل ویدیو، یک .nest با ایندکس‌ها، یک manifest به صورت JSON و یک دایرکتوری کش. چهار نوع فایل برای ارائهٔ یک چیز. Nest وجود دارد تا پایگاه داده در یک فایل باشد، و چیزی که بیرون آمد پایگاه داده‌ای بود با چهل چیز کنارش. کار می‌کرد، همان‌طور که کمدی که با پیچ اضافه سوار شده کار می‌کند. هدف Nest آنجا گم می‌شد، و فشرده‌سازی اصلاً مسئله نبود. Nest می‌تواند آرشیوکنندهٔ کارت‌های Magic باشد، نقشه‌ها، هر دیتاست تصویری که پایگاه داده‌ای کنارش دارد. اما آرشیوکننده یک فایل است، نه یک پوشه.

سؤال دوم از مدل آمد. اسکریپت از CLIP استفاده می‌کرد چون همان چیزی بود که forge داشت، و من حتی درست نمی‌دانستم CLIP با یک کارت چه می‌کند. رفتم سراغش: به تصویر نگاه می‌کند و متن چاپ‌شده را نادیده می‌گیرد. برای کارت Magic یعنی نگاه کردن به نیمهٔ کم‌فایده‌تر، چون چیزی که کارت را مشخص می‌کند اسمی است که بالایش نوشته شده. خواستم در Hugging Face و GitHub جست‌وجو شود که آن ماه چه مدل‌های چندوجهی بازی وجود دارد، و جواب خانواده‌ای از Tencent به اسم WeMM بود که متن داخل تصویر را می‌خواند، به‌علاوهٔ SigLIP و Jina. نسخهٔ دو میلیارد پارامتری WeMM را به دلیل دیگری از قبل دانلود کرده بودم.

در مقایسه‌ای با ۱۵۰۰ کارت و شصت جست‌وجو از نوع «تصویر فلان کارت»، CLIP از هر چهار بار یک بار کارت درست را پیدا کرد. WeMM نُه از ده، SigLIP نزدیک به آن، Jina وسط. بهای WeMM این است که حدود سی برابر کندتر از CLIP است و اجرایش روی کل مجموعه روی دستگاه من تقریباً یک روز طول می‌کشید. پس مقایسه روی نمونه ماند و مجموعهٔ کامل فعلاً با CLIP ماند.

نتیجه «برو سراغ WeMM» نبود. نتیجه این بود که مدل نمی‌تواند یک ثابت در بالای یک اسکریپت باشد. باید فهرستی از پیش‌تنظیم‌ها داخل موتور باشد و کسی که build می‌گیرد همان موقع انتخاب کند کدام، یا کدام‌ها. و ویدیو باید داخل فایل جا شود، نه کنارش. پیش از هر کدام از این دو، می‌خواستم بدانم چقدر می‌شود بدون از دست دادن هیچ چیز فشرده کرد. حتی اگر مجبور می‌شدیم اختراعش کنیم.