Halo, Habr!
Saya membuat situs web untuk proyek saya. Di situs ini Anda harus menunjukkan banyak gif sekaligus, masing-masing memiliki berat yang cukup baik. Jika Anda menampilkan semuanya sekaligus, maka halaman dimuat untuk waktu yang sangat lama. Pada saat yang sama, memberikan halaman tanpa GIF (sehingga dapat diunduh di sana) juga tidak mungkin.
Siapa pun yang tertarik dengan cara saya menangani masalah ini, saya minta kucing.
Sebenarnya masalahnya
Seperti yang saya katakan, ada SANGAT banyak gif di situs, bagus dan berbeda. Anda dapat melihat sendiri berapa banyak dari mereka:
reface.tech
Segera setelah saya melihat versi beta dari pendaratan, saya langsung memiliki masalah dengan memuat: untuk beberapa pengguna halaman memuat untuk waktu yang lama. Untuk bisnis yang serius, ini tentu saja bukan masalahnya.
Itu perlu untuk menyelesaikan ini entah bagaimana. Mustahil untuk bertahan dengan kompresi lossless sederhana, karena pada saat itu semua konten media telah didorong melalui
kompresor.io . Oleh karena itu, perlu mengompres dengan kerugian dan memberikan GIF dengan kualitas yang lebih buruk.
Tetapi untuk membagikan konten media yang buruk kepada pengguna dengan internet yang baik adalah semacam penghinaan. Karena itu, diputuskan untuk entah bagaimana menentukan kecepatan Internet Anda ini, dan tergantung pada kecepatan untuk menghilangkan kualitas yang sesuai.
Kami membuat sketsa kasar
Kami akan memiliki array dengan deskripsi konten media yang akan dimuat.
Contoh:
[ { "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" } } ]
Di sini, di elemen untuk tingkat kualitas yang sesuai terletak url dan ukuran file.
Kami hanya akan:
- Pergi melalui array (saat memuat halaman)
- Baca ukuran total yang dimuat untuk setiap tingkat kualitas
- Tentukan apakah akan memuat semua dalam 4 detik (ini adalah periode yang secara pribadi mengganggu saya)
Karena itu, perlu:
- Melihat beberapa hal yang akan membuat array sedemikian rupa sehingga semuanya tidak dihitung dengan pena (dengan python)
- Melihat kecepatan internet
Menggergaji pengukur kecepatan
Ini akan relatif sederhana. Kami mengetik di bilah alamat browser Anda
eu.httpbin.org/stream-bytes/51200 . File dengan panjang 51200 byte diunduh. Kami mendorongnya untuk diri kami di depan umum (untuk mengukur kecepatan ke hosting).
Sekarang kita perlu memeriksa berapa banyak ayunan file. Kami akan mengajukan fungsi sederhana untuk ini, yang akan mengembalikan kecepatan dalam megabita per detik kepada kami.
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); }); }
Artinya, kami mencatat waktu mulai mengunduh, waktu selesai, mengukur perbedaannya, dan, karena kami tahu ukuran file, kami hanya membaginya.
Sekarang kita akan menulis fungsi yang akan melakukan sesuatu dengan kecepatan khusus ini:
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; } }
Secara umum, ada masalah dengan kode ini: itu adalah bahwa kecepatan koneksi yang tepat tidak ditentukan karena ukuran file yang kecil. Tetapi mengunduh sesuatu yang lebih terlalu mahal bagi kami, jadi kami hanya mengalikan kecepatan yang dihasilkan dengan 5. Bahkan dengan margin, kami mengambilnya, karena dalam kenyataannya kecepatan akan lebih tinggi.
Sekarang kami akan mengajukan fungsi yang, tergantung pada kecepatannya, akan menghilangkan kualitas yang sesuai:
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"; } }
Karena fungsi yang menghitung kecepatan tidak sinkron dengan kami, SpeedMeasure.speed mungkin nol. Secara default, kami percaya bahwa kecepatan koneksi adalah 1 megabyte per detik. Ketika fungsi menghitung kecepatan, kami hanya merender ulang wadah.
Kami melewatkan array array ke fungsi getResolution. Mengapa Karena jika kita memiliki beberapa wadah pada halaman, lebih mudah bagi kita untuk mentransfer konten yang sesuai untuk masing-masing dari mereka dalam sebuah array, tetapi kita perlu mempertimbangkan kecepatan unduh untuk semuanya sekaligus.
Contoh penggunaan
Berikut ini adalah contoh penggunaan (saat Bereaksi):
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> ); }
Karena itu, ketika penentuan kecepatan kami dimuat, kontainer akan diberikan lagi.
Di dalam wadah (misalnya, di dalam Kontrol) Anda hanya mengambil GIF yang sesuai dari array (berdasarkan indeks), kemudian Anda mendapatkan objek dengan kualitas dan Anda mendapatkan tautan dengan url. Semuanya sederhana.
Menulis Skrip Python
Sekarang kita perlu mengompres gif dan output array dengan deskripsi konten secara otomatis.
Untuk memulai, mari menulis skrip untuk kompresi. Kami akan menggunakan gifsicle. Untuk konten kompresi menengah, level kompresi akan menjadi 80 (dari 200), untuk fitur yang sangat kuat akan 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))
Untuk membuat jalur ke file dapat dimengerti, berikut adalah deskripsi direktori file dengan gifs:
- NOT_OPTIMIZED_DIR - GIF yang tidak dioptimalkan
- GIF_RESIZED_DIR - GIF yang tidak dioptimalkan, tetapi diubah ukurannya sesuai dengan ukuran wadahnya
- GIF_COMPRESSED_DIR - GIF terkompresi
Di dalam folder ada folder dengan nama kategori GIF. Di dalam folder dengan folder tertentu berisi "besar", "tengah" dan "kecil" (di bawah jenis file terkompresi).
Dalam skrip, kita pergi melalui direktori dengan gif dan untuk setiap file kita melakukan dua jenis kompresi, memanggil perintah baris perintah yang sesuai.
Sekarang mari kita beralih ke skrip untuk membuat array dengan informasi.
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))
Di sini kita pergi melalui folder dengan file, menentukan ukuran file, mencari tahu jenis kompresi dan memasukkan informasi umum ke dalam array OUTPUT. Dan kemudian kami dengan indah menampilkan array ini ke konsol untuk menyalinnya.
Kesimpulan
Saya harap artikel ini membantu Anda dengan sesuatu. Selamat coding, kawan.