مرحبا يا هبر!
أقوم بإنشاء موقع ويب لمشروعي. تحتاج إلى عرض الكثير من صور متحركة في الموقع في نفس الوقت ، كل منها يزن جيدًا. إذا عرضت كل شيء دفعة واحدة ، فسيتم تحميل الصفحة لفترة طويلة جدًا. في الوقت نفسه ، من المستحيل أيضًا إعطاء الصفحة بدون صور GIF (بحيث يمكن تنزيلها هناك).
أي شخص مهتم بكيفية التعامل مع هذه المشكلة ، أطلب قطة.
في الواقع ، المشكلة
كما قلت ، هناك العديد من صور متحركة على الموقع ، جيدة ومختلفة. يمكنك أن ترى بنفسك كم منهم:
reface.tech
بمجرد رؤية الإصدار التجريبي من الهبوط ، واجهت على الفور مشكلة في التحميل: بالنسبة لبعض المستخدمين ، كانت الصفحات يتم تحميلها لفترة طويلة. بالنسبة للعمل الجاد ، هذا ، بالطبع ، ليس هو الحال.
كان من الضروري حل هذا بطريقة أو بأخرى. كان من المستحيل الحصول على ضغط بسيط بلا ضياع ، كما هو الحال بالفعل في ذلك الوقت ، تم نقل جميع محتويات الوسائط من خلال
compressor.io . لذلك ، كان من الضروري الضغط بخسائر وإعطاء صور GIF بجودة أسوأ.
ولكن إعطاء محتوى سيء للوسائط للمستخدمين ذوي الإنترنت الجيد هو نوع من التضحية بالنفس. لذلك ، تقرر تحديد سرعة هذه الإنترنت الخاص بك بطريقة أو بأخرى ، واعتمادًا على السرعة اللازمة لجودة الجودة المناسبة.
نصنع رسمًا تقريبيًا
سيكون لدينا صفيف مع وصف لمحتوى الوسائط المراد تحميلها.
مثال:
[ { "large": { "size": 0.6211118698120117, "url": "gifs/control/large/control_1.gif" }, "middle": { "size": 0.5330495834350586, "url": "gifs/control/middle/control_1.gif" }, "small": { "size": 0.4901447296142578, "url": "gifs/control/small/control_1.gif" } } ]
هنا في المواد الأساسية للحصول على درجة مناسبة من الجودة يكمن عنوان url وحجم الملف.
سنقوم ببساطة:
- تصفح الصفيف (عند تحميل الصفحة)
- قراءة الحجم الكلي تحميل لكل درجة من الجودة
- تحديد ما إذا كان سيتم تحميل كل شيء في 4 ثوان (هذه هي الفترة التي يزعجني شخصيا)
وفقًا لذلك ، من الضروري:
- رأيت شيئًا ما من شأنه أن يصنع مثل هذا الصفيف بحيث لا يتم احتساب كل شيء مع الأقلام (في الثعبان)
- رأى سرعة الإنترنت
نشر مقياس السرعة
سيكون بسيطا نسبيا.
نكتب في شريط العنوان في متصفحك
eu.httpbin.org/stream-bytes/51200 . يتم تنزيل ملف بطول 51200 بايت. نحن نشقها على أنفسنا في الأماكن العامة (لقياس السرعة لاستضافة).
الآن نحن بحاجة إلى التحقق من مقدار تقلبات الملف. سنقدم وظيفة بسيطة لهذا الأمر ، والتي ستعيد إلينا السرعة بالميغابايت في الثانية.
async checkDownloadSpeed(baseUrl, fileSizeInBytes) { return new Promise((resolve, _) => { let startTime = new Date().getTime(); return axios.get(baseUrl).then( response => { const endTime = new Date().getTime(); const duration = (endTime - startTime) / 1000; const bytesPerSecond = (fileSizeInBytes / duration); const megabytesPerSecond = (bytesPerSecond / 1000 / 1000); resolve(megabytesPerSecond); }); }).catch(error => { throw new Error(error); }); }
أي أننا سجلنا وقت بدء التنزيل ، ووقت الانتهاء ، وقاسنا الفرق ، وبما أننا نعرف حجم الملف ، فقد قمنا ببساطة بتقسيمه.
سنقوم الآن بكتابة وظيفة ستفعل شيئًا بهذه السرعة المحددة:
async getNetworkDownloadSpeed() { const baseUrl = process.env.PUBLIC_URL + '/51200'; const fileSize = 51200; const speed = await this.checkDownloadSpeed(baseUrl, fileSize); console.log("Network speed: " + speed); if (speed.mbps === "Infinity") { SpeedMeasure.speed = 1; } else { SpeedMeasure.speed = speed * 5; } }
بشكل عام ، توجد مشكلة في هذا الرمز: إنه لم يتم تحديد سرعة الاتصال الدقيقة نظرًا لصغر حجم الملف. لكن تنزيل شيء أكثر تكلفة أمرًا باهظًا بالنسبة لنا ، لذلك ببساطة نقوم بضرب السرعة الناتجة بمقدار 5. حتى مع وجود هامش ، فإننا نأخذها لأن السرعة ستكون في الواقع أعلى.
الآن ، دعنا نوفر وظيفة ، تبعا للسرعة ، ستهدئ الجودة المطابقة:
static getResolution(gifsArray) { let totalSizeLevel1 = 0; let totalSizeLevel2 = 0; let totalSizeLevel3 = 0; for (let i = 0; i < gifsArray.length; i++) { for (let a = 0; a < gifsArray[i].length; a++) { let element = gifsArray[i][a]; totalSizeLevel1 += element.small.size; totalSizeLevel2 += element.middle.size; totalSizeLevel3 += element.large.size; } } if (isNaN(SpeedMeasure.speed)) { SpeedMeasure.speed = 1; } let timeLevel1 = totalSizeLevel1 / SpeedMeasure.speed; let timeLevel2 = totalSizeLevel2 / SpeedMeasure.speed; let timeLevel3 = totalSizeLevel3 / SpeedMeasure.speed; if (timeLevel3 < APPROPRIATE_TIME_LIMIT) { return "large"; } else if (timeLevel2 < APPROPRIATE_TIME_LIMIT) { return "middle"; } else { return "small"; } }
نظرًا لأن الوظيفة التي تعد السرعة غير متزامنة بالنسبة إلينا ، فقد يكون SpeedMeasure.speed صفرًا. بشكل افتراضي ، نعتقد أن سرعة الاتصال هي 1 ميغا بايت في الثانية. عندما تقوم الوظيفة بحساب السرعة ، نعيد تقديم الحاوية.
نمرر مجموعة من المصفوفات إلى وظيفة getResolution. لماذا؟ لأنه إذا كان لدينا عدة حاويات على الصفحة ، فمن الملائم لنا نقل المحتوى المقابل لكل منها في صفيف ، لكننا بحاجة إلى مراعاة سرعة التنزيل للجميع مرة واحدة.
مثال للاستخدام
فيما يلي مثال للاستخدام (على React):
async runFunction() { let speedMeasure = new SpeedMeasure(); await speedMeasure.getNetworkDownloadSpeed(); this.forceUpdate() } componentDidMount() { this.runFunction(); } render() { let quality = SpeedMeasure.getResolution([ Control.getControlArray(), Health.getHealthArray() ]); return ( <div className="app"> <Presentation /> <Control quality={quality} /> <Health quality={quality} /> </div> ); }
وفقا لذلك ، عندما يتم تحميل تحديد السرعة لدينا ، سيتم تقديم الحاوية مرة أخرى.
داخل الحاوية (على سبيل المثال ، داخل التحكم) ، يمكنك ببساطة الحصول على GIF المطابق من الصفيف (حسب الفهرس) ، ثم تحصل على كائن حسب الجودة وتحصل على مرجع بواسطة عنوان url. كل شيء بسيط.
كتابة سيناريو بيثون
الآن نحن بحاجة إلى ضغط ملفات GIF تلقائيًا وإخراج الصفيف مع وصف المحتوى.
للبدء ، دعنا نكتب سكريبت للضغط. سوف نستخدم gifsicle. بالنسبة لمحتوى الضغط المتوسط ، سيكون مستوى الضغط 80 (من 200) ، أما بالنسبة للميزة القوية للغاية ، فستكون 160.
import os GIFS_DIR = "/home/mixeden//Landingv2/" COMPRESSOR_DIR = "/home/mixeden//gifsicle-static" NOT_OPTIMIZED_DIR = "not_optimized" OPTIMIZED_DIR = "optimized" GIF_RESIZED_DIR = "gif_not_optimized_resized" GIF_COMPRESSED_DIR = "gif_compressed" COMPRESSION_TYPE = ["middle", "small"] for (root, dirs, files) in os.walk(GIFS_DIR, topdown=True): if len(files) > 0 and GIF_RESIZED_DIR in root: for file in files: path = root + "/" + file for compression in COMPRESSION_TYPE: final_path = path.replace(GIF_RESIZED_DIR, GIF_COMPRESSED_DIR + "/" + compression + "/" + OPTIMIZED_DIR) print(path, final_path) if compression == COMPRESSION_TYPE[0]: rate = 80 else: rate = 160 os.system("echo 0 > " + final_path) os.system(COMPRESSOR_DIR + " -O3 --lossy={} -o {} {}".format(rate, final_path, path))
لجعل المسارات إلى الملفات مفهومة ، إليك وصف دليل الملفات باستخدام gifs:
- NOT_OPTIMIZED_DIR - صور GIF غير المحسنة
- GIF_RESIZED_DIR - صور GIF غير محسنة ، ولكن تم تغيير حجمها وفقًا لحجم الحاوية الخاصة بهم
- GIF_COMPRESSED_DIR - صور GIF مضغوطة
داخل المجلدات توجد مجلدات بأسماء فئات GIF. داخل مجلد يحتوي على مجلد معين يحتوي على "كبير" و "متوسط" و "صغير" (تحت أنواع الملفات المضغوطة).
في البرنامج النصي ، نذهب إلى الدليل باستخدام gifs ولكل ملف نقوم بنوعين من الضغط ، ندعو أمر سطر الأوامر المقابل.
الآن دعنا ننتقل إلى البرنامج النصي لإنشاء مجموعة تحتوي على معلومات.
import json import os GIFS_DIR = "/home/mixeden//Landingv2/" COMPRESSOR_DIR = "/home/mixeden//gifsicle-static" NOT_OPTIMIZED_DIR = "not_optimized" OPTIMIZED_DIR = "optimized" GIF_RESIZED_DIR = "gif_not_optimized_resized" GIF_COMPRESSED_DIR = "gif_compressed" COMPRESSION_TYPE = ["large", "middle", "small"] OUTPUT = {} for (root, dirs, files) in os.walk(GIFS_DIR, topdown=True): if len(files) > 0 and GIF_COMPRESSED_DIR in root and NOT_OPTIMIZED_DIR not in root: files.sort() type = root.split(GIFS_DIR)[1].split(GIF_COMPRESSED_DIR)[0].replace("/", "") print(type) if type not in OUTPUT: OUTPUT[type] = [] if len(OUTPUT[type]) == 0: for file in files: OUTPUT[type].append( { "large": { "url": "", "size": 0 }, "middle": { "url": "", "size": 0 }, "small": { "url": "", "size": 0 } }) for file in files: full_path = root + "/" + file bytes_size = os.path.getsize(full_path) kilobytes_size = bytes_size / 1000 megabytes_size = kilobytes_size / 1000 index = int(file.split("_")[1].replace(".gif", "")) - 1 for typer in COMPRESSION_TYPE: if typer in root: local_type = typer new_url = "gifs/" + full_path.replace(GIFS_DIR, "").replace("/" + GIF_COMPRESSED_DIR, "").replace("/" + OPTIMIZED_DIR, "") OUTPUT[type][index][local_type]['url'] = new_url OUTPUT[type][index][local_type]['size'] = megabytes_size print(OUTPUT) print(json.dumps(OUTPUT, indent=4, sort_keys=True))
ننتقل هنا إلى المجلدات التي تحتوي على الملفات ، ونحدد حجم الملف ، ونعرف نوع الضغط ونضع المعلومات العامة في صفيف OUTPUT. ثم نقوم بإخراج هذا الصفيف بشكل جميل إلى وحدة التحكم لنسخه.
استنتاج
آمل أن يساعدك هذا المقال في شيء ما. هل لديك الترميز لطيفة ، والرجال.