WebP: пора отправить ваш сайт в XXI век

Интернет - безумно интересное, но очень странное место, в котором мы прикасаемся, сами того не замечая, то к будущему, то к далёкому прошлому. Высокие технологии, находящиеся на самом bleeding edge науки соседствуют здесь с окаменелыми трилобитами середины прошлого века. И тем не менее - оно работает!

Несмотря на свою децентрализованную и гибкую суть, по-настоящему глобальные изменения всемирная паутина принимает далеко не всегда охотно и благосклонно. Особенно хорошо это заметно, конечно же, на самых низких уровнях - железа и наиболее близких к нему протоколов: Ethernet, IP, TCP/UDP... Трогать что-либо там - практически невозможно, как невозможно перебрать двигатель автомобиля на полном ходу. Но и гораздо более близкие к пользователю технологии упрямо сопротивляются наступлению светлого будущего.

В этот раз я хочу поговорить о медиа-ресурсах - картинках, аудио и видео.

Кажется, что интернет меняется с огромной скоростью, вместе с потоками информации, передаваемой через него. Но приглядевшись внимательнее, мы увидим, что "киты", на которых зиждется всё это великолепие, все покрыты старческими морщинами и плывут, потрясая длинными седыми бородами под звонкий треск артритных суставов. Встречайте:

Чувствуете, как запахло нафталином?

Разумеется, нельзя сказать, что современный интернет безропотно продолжает нести у себя на горбу эти мамонтячьи технологии, никак не пытаясь от них избавиться. Дело обстоит скорее совсем наоборот - но тут нас подстерегает совсем другая опасность, отлично выраженная в известнейшем комиксе xkcd:

В самом деле - если начать изыскания и погуглить альтернативы всем этим форматам из прошлого века, то легко находится целая пачка более новых вариантов, один другого краше. Нюанс заключается в общедоступности, а именно - поддержке со стороны операционных систем и особенно браузеров. Усугубляет ситуацию склонность "Корпорации Добра" периодически вставать в третью позицию и заявлять нечто вроде - "задолбали вы со своим старьём, мы сделаем свою %название_технологии%, с блэкджеком и оптимизациями". А поскольку Chrome занимает больше половины рынка браузеров, остальным игрокам приходится грустно вздыхать - и либо добавлять то же самое у себя, либо вставать в достойную уважения, но заведомо невыгодную позу.

При переезде на собственный standalone-сайт мне захотелось провести хотя бы частичное освобождение от оков прошлого века, перейдя на более современные технологии.

Первым - и наиболее логичным кандидатом стали картинки. Их довольно много, они очень разные - как по размеру, так и по назначению - небольшие миниатюры, среднего размера изображения, используемые в текстах, полноразмерные оригиналы, открываемые по клику, анимированные гифки... Всё это хотелось привести к какому-то общему знаменателю и одновременно, если получится, уменьшить занимаемый на диске объём.

Какие методы обычно применяются (или применялись в прошлом) для хранения изображений на сайте?

Тут никаких секретов нет: для мелких картинок с небольшим количеством цветов (например, элементов интерфейса), а также анимации - GIF; для обычных растровых изображений - JPEG; в случае, когда недопустима потеря качества - PNG. Все эти форматы неплохо справляются со своими функциями, но, в том числе из-за древности времён создания, каждый из них обладает и существенными недостатками:

Однако, существует формат, сочетающий в себе все достоинства предыдущих участников: возможность кодирования как с потерей, так и без потери качества, поддержку прозрачности и анимации, и, в качестве приятного бонуса - меньший размер файла при, как минимум, не худшем качестве изображения.

Встречайте, WebP!

Это, по иронии судьбы, то самое "детище третьей позиции Гугла", представленное в 2010 году и являющееся близким родственником видеокодека VP8. WebP совершенно бесплатен и открыт, что, может быть, и не так важно конечному пользователю - но довольно приятно для производителей оборудования и ПО, которым не нужно для поддержки этого формата платить никаких отчислений.

Но просто сказать - "теперь все картинки будут в webp!" для меня недостаточно, нужно какое-то более осязаемое подтверждение его превосходства. Иначе говоря - я решил провести некоторые натурные изыскания. Изыскания, совершенно не претендующие на академическую полноту и точность (научные работы по кодированию изображений - это обычно целая гора высшей математики), а скорее должные в наглядной форме показать принципиальные отличия. В том числе для того, чтобы я мог поделиться информацией с вами, уважаемые читатели. На уровне домохозяйки, то есть - владельца небольшого сайтика.

Для своих тестов я нашёл на просторах интернета пять здоровенных (3840х2160) и, на мой пристальный взгляд, максимально качественных PNG-изображений разного типа - кадр из фильма, векторный рисунок, рисунок кистью, 3D-сцену и нечто среднее. Здоровые картинки я с помощью графического пакета imagemagick уменьшил до 1000px по ширине (стандартный размер изображения в моём блоге), а также - до эскиза шириной в 400px, получив таким образом 15 файлов, соответствующих наиболее распространённым профилям использования изображений на сайтах - эскиз в списке материалов, средний размер непосредственно в тексте, большой исходник - по клику на картинку.

Эти изображения я обработал утилитой optipng, которая без какой-либо потери качества оптимизирует параметры сжатия - дабы убедиться, что из формата PNG "выжато" всё возможное.

Получившиеся на этом этапе картинки назовём оригиналами и основные расчёты будет проводить, сравнивая с ними. Все участвующие в доморощенном эксперименте изображения, кстати, можно скачать по ссылке.

bytes / codec PNG JPG-100 WEBP-lossless JPG-90 WEBP-90 JPG-80 WEBP-default
1-4k-orig.png 8183889 5948440 6141218 1533501 728470 778422 245354
2-4k-orig.png 9280094 6256244 6174494 1200950 466356 576420 223058
3-4k-orig.png 4902046 3504954 3158200 946374 408496 513311 196664
4-4k-orig.png 14937573 12170137 12213642 3414340 2170026 1682660 1047936
5-4k-orig.png 10799384 9076438 9563128 1946884 957728 987032 430262
1-1k.png 685317 553781 571616 129015 64152 64082 26234
2-1k.png 660169 557745 466888 163654 84378 85938 43732
3-1k.png 501204 425930 361790 118387 59694 64473 29154
4-1k.png 1050204 988547 882538 315808 190264 147376 102714
5-1k.png 958353 800036 759624 221770 154036 113895 72744
1-400.png 117036 99764 95858 26600 15274 14966 7890
2-400.png 145627 128657 101606 42362 25210 22633 13882
3-400.png 107909 91554 78768 26273 15014 14457 7754
4-400.png 177572 173124 154350 59949 36048 28338 21394
5-400.png 170102 144030 133820 43049 31684 22309 15486

Немного поразмыслив, я решил организовать сравнение следующим образом: разделив на три условных этапа, каждый из которых представляет собой разные варианты сжатия:

  1. Lossless - с минимальным или полным (если таковое поддерживает формат) отсутствием потерь. В этом случае мы сравниваем оригинальные PNG, JPEG с качеством 100 и WebP в режиме lossless.
  2. Quality - высококачественный lossy-режим, практически неотличимый на глаз от оригинала. JPEG-90 сравнивается с WebP-90.
  3. Default - стандартный режим, представляющий собой хорошее качество изображения и высокую степерь сжатия, дефолтные параметры энкодеров. JPEG-80 сравнивается с WebP-75.

Нужно заметить, что, например, JPEG с качеством 100 (по понятным причинам) не используется в реальной жизни примерно никогда - и я оставил его исключительно в качестве "спарринг-партнёра" WebP. Приведённые названия режимов довольно условны - тот же Quality вполне может использоваться для полноразмерных изображений наряду с PNG, а визуальную разницу между WebP-90 и WebP-75 на картинках среднего или небольшого размера вы, скорее всего, вообще не заметите.

Итак, я взял все пятнадцать картинок - и поочерёдно закодировал их с соответствующими параметрами.

Вот, что получилось в результате:

Таблица, демонстрирующая уменьшение размера файлов относительно PNG.

Хорошо видно, что даже lossless-режим даёт относительно небольшое, но стабильное уменьшение размера картинки, в среднем 20-25%. Что это значит на практике? А то, что при экспорте высококачественных изображений (например, из Фотошопа или RAW-формата фотокамер) имеет смысл делать это не в PNG, а сразу в Lossless-WebP - получите то же самое, но с экономией места на диске.

Однако, подавляющее большинство отображаемых на веб-сайтах картинок вовсе не требует сжатия без потерь - чаще всего их геометрические размеры не настолько велики, чтобы человеческий глаз мог заметить даже достаточно сильные искажения, а в случае даже с JPEG-90 они не так уж и велики, не говоря уж о WebP-90.

С другой стороны - вы только посмотрите на степень сжатия!

Даже старичок JPEG показывает 70-80% экономии относительно PNG, а WebP, при "более лучшем" качестве картинки идёт ещё дальше - показывая от 80% у небольших картинок до 90% у полноразмерных. Иначе говоря - размер получившихся файлов в 5-10 раз меньше оригиналов. Можно было бы на этом закончить - но мятежная душа исследователя погнала меня за буйки.

Посмотрим, что получится при настройках WebP по умолчанию. Аналогом такого режима у JPEG обычно считается качество 80, при котором начинают чётко проявляться артефакты кодирования - то есть для крупных изображений это чересчур, но оно вполне подойдёт для, например, эскизов предпросмотра и других небольших картинок, а также в других случаях, когда скорость загрузки существенно важнее безупречного качества.

Тренд, заключающийся в том, что большие картинки жмутся лучше мелких сохранился у всех кодеков, но на 85-90% сжатия у JPEG, WebP ответил поразительными цифрами от 90 до 97%, в последнем случае, на минуточку, сжав оригинальный кадр из "Матрицы" аж в тридцать три (!) раза без особого, на мой взгляд, ухудшения качества.

Подводя промежуточный итог - WebP во всех случаях на голову лучше и JPEG, и PNG.

В режиме Lossless этого практически не видно, но во всех остальных случаях, если сравнивать только JPEG vs WebP, размер файла последнего в среднем в полтора-два раза меньше:

Перейдём к следующей части исследования, относящейся к анимированным изображениям. Это достаточно узкая ниша, повсеместно вытесняемая сейчас HTML5-вариантом (тэг <video>), но, например, если вам по какой-то причине нужна движущаяся картинка нестандартных пропорций или по какой-то другой причине нет возможности (или желания) использовать полноценное видео - гифки уже очень давно помогают справиться с подобными потребностями.

Хорошо ли они это делают - другой вопрос.

Как я уже говорил, максимальное число цветов в GIF-палитре - 256. Это существенно ограничивает сферу применения формата, превращая плавные переходы тонов в хорошо заметные "лесенки". Если сцена не пестрит многообразием цветов - всё не так плохо, но в противном случае приходится жертвовать качеством, причём существенно. Второй недостаток - отсутствие алгоритмов предсказания движения, аналоги которых используются в видеокодеках. Это не позволяет эффективно использовать предыдущие кадры для построения следующих, а следовательно - вес получившегося файла зачастую превосходит все возможные рамки.

Формат WebP лишён обоих этих недостатков - у него нет ограничения по количеству цветов и есть в наличии механизмы предсказания, похожие на таковые у своего "старшего брата" VP8, хоть, конечно, не столь же изощрённые.

Посмотрим, что получится на практике. Для этого я взял парочку коротких видюшек с относительно небольшим количеством цветов, чтобы не усложнять работу GIF-энкодеру, слегка уменьшил и сконвертировал в GIF и WebP.

Первое видео, GIF, 14349 KB (1244% от оригинала)

Первое видео, WebP, 2290 KB (198% от оригинала)

Второе видео, GIF, 15881 KB (2454% от оригинала)

Второе видео, WebP, 4369 KB (675% от оригинала)

Хорошо заметно, особенно на втором видео, как сильно не хватает цветов в палитре гифке - для компенсации этого энкодер пытается чередовать цвета, используя дизеринг - и выглядит это, честно говоря, ужасненько. WebP без проблем справляется с задачей - результат, фактически, не так уж и сильно отличается от исходного видео. С размером файлов тоже никаких неожиданностей - гифки огромны, WebP - тоже в несколько раз тяжелее исходников, но хотя бы с неплохим качеством.

В общем - WebP занял весь пьедестал почёта. Переходить на него или нет - разумеется, каждый решает самостоятельно. Меня вот результаты более чем убедили - перехожу :)

Что ещё можно сделать для освобождения от тяжкого наследия XX века?

С картинками разобрались, на очереди - видео и аудио. Тут всё немного сложнее, поскольку владельцы небольших сайтов издавна и очень прочно привыкли делегировать всё это посторонним площадкам - Ютубу и всяким другим.

С одной стороны кажется, что это вполне конструктивный шаг - не нужно заморачиваться с кодированием, хранением и бэкапированием. С другой - каждое встроенное в страницу сайта видео с ютуба, это мамонтячий iframe с кучей обвеса, пусть немного, но тормозящий загрузку обращениями к внешним ресурсам. Это дополнительная пачка javascript`ов. Это контроль Гугла над тем, что можно выкладывать, а что нельзя. В некоторых случаях - это реклама. Это, в конце концов - полное отсутствие контроля.

Какова альтернатива? Альтернатива очень проста - всё хостить у себя.

Соответствующие HTML-тэги появились уже очень давно и поддерживаются чуть менее, чем везде. Параметры позволяют очень гибко настроить поведение - подложить несколько вариантов файлов (у каждого браузера свой набор поддерживаемых форматов), отобразить или скрыть элементы управления, включить автовоспроизведение, закольцевать и т. д. В коде страницы это будет занимать всего несколько строчек (просто кликните ПКМ рядом с плеером и загляните в код страницы):

Попробуйте без приседаний скачать аудиотрек с Ютуба. А тут - пожалуйста!

Понятно, что заморачиваться с выбором кодеков, настройками конвертации и прочими, иногда довольно нетривиальными низкоуровневыми штуками захочет не каждый. Но лично для меня возможность самостоятельного выбора - качества изображения, содержания видео, способов хранения, доставки и бэкапа - важнее удобства, которое в один прекрасный момент может обернуться непредсказуемыми последствиями.

Будьте как древние греки - носите всё своё с собой.