В течение последнего полугода команда Discord по обслуживанию медиа-инфраструктуры модернизировала конвейер обработки изображений, добавив поддержку анимированных форматов WebP и AVIF. Теперь на платформе можно делиться анимированными картинками WebP и AVIF как в виде прикреплённых файлов, так и в виде вставок. При этом все эмодзи выдаются в виде анимированных WebP — и бесшовно отображаются на любой платформе Discord. Эти изменения были реализованы для того, чтобы повысить качество анимации и воспроизведения роликов на всех платформах. При этом одновременно резко уменьшается размер файлов, и поэтому их загрузка ускоряется!

Эволюция форматов изображений
Вспомните, как переход от видео стандартного разрешения к видео высокого разрешения преобразил визуальный контент. Точно так современные форматы изображений радикально повлияют на онлайновый обмен картинками. В Discord миллионы пользователей ежедневно обмениваются миллиардами изображений, и компания постоянно взвешивает, как обеспечивать максимально качественное обращение с картинками, поддерживая при этом высокую производительность и эффективность.
Прославленный формат GIF не одно десятилетие исправно служил Интернету. Сейчас GIF – синоним коротких цикличных анимаций, на которых основано множество мемов. Всё это время также не утихает спор, как правильно произносить «GIF». Но у GIF есть свои недостатки, в частности, 256-цветовая палитра, отсутствие подлинной альфа-прозрачности, неэффективное сжатие. Эти огрехи постепенно становились всё явственнее по мере совершенствования дисплеев и расширения возможностей передачи данных по сети.
Современные форматы изображений, такие как WebP и AVIF позволяют совершить настоящий квантовый скачок в технологии работы с изображениями и предоставляют спектр возможностей, гораздо полнее отвечающих потребностям Discord:
Полноценная альфа-прозрачность
В картинках GIF прозрачность является двоичной величиной — каждый пиксель либо видимый, либо совершенно невидимый. В форматах WebP и AVIF поддерживаются переменные уровни прозрачности (также называемые альфа-каналами). Благодаря ним можно запрограммировать частичную прозрачность и плавные контуры, что очень важно для создания высококачественных анимированных стикеров и эмотиконов. В Discord есть светлая и тёмная тема, и именно такие анимации совершенно естественно смотрятся на любом фоне.
Фон на следующем изображении выполнен в виде градиента, изменяющегося по диагонали с синего на красный. Этот пример демонстрирует, как в изображениях различных форматов обрабатывается прозрачность. Слева показаны гладкие альфа-переходы, а справа – двоичная прозрачность (любой пиксель может быть только прозрачным или непрозрачным). Из этого сравнения понятно, что, пусть WebP и AVIF отлично реализуют гладкое перетекание градиентов прозрачности, простой двоичный подход к прозрачности не менее качественно выполняется и во всех прочих форматах.

Улучшенная глубина цвета
Информационная ёмкость GIF ограничена 8 разрядами на пиксель, а палитра включает всего 256 цветов. В свою очередь, в WebP предоставляется 8 разрядов на цветовой канал, что в сумме даёт ошеломительную цифру в 16 миллионов оттенков. Для AVIF и это не предел, поскольку в этом формате выделяется до 12 разрядов на канал. Вот что мы получаем благодаря такому радикальному увеличению точности цветопередачи:
-
Более плавные градиенты без видимой чересполосицы
-
Более осязаемые и точные цвета
-
Более качественное представление фотографий
-
Более плавные градиенты без видимой чересполосицы
-
Более осязаемые и точные цвета
-
Более качественное представление фотографий
-
Поддержка HDR-контента на совместимых с ним дисплеях

Эффективная кодировка информации
В форматах WebP и AVIF при работе с анимацией используются современные методы сжатия видео, благодаря чему эти файлы получаются принципиально компактнее, чем их аналоги в формате GIF:
-
Межкадровое сжатие, при котором кодируются лишь изменения пикселей, происходящие между кадрами
-
Усовершенствованные режимы прогнозирования, при работе с которыми нужно не так много избыточных данных
-
Возможность конфигурировать уровни качества и тем самым сбалансировать размер изображения и его визуальную достоверность
-
Поддержка переменного хронометража кадров с точностью до миллисекунд


Форматы WebP и AVIF всё активнее берутся на вооружение, в особенности на мобильных устройствах, где каждый килобайт на счету. Поэтому всё больше и больше таких пользователей, которые могут насладиться их достоинству. Но с технической точки зрения внедрять поддержку этих форматов – значит решать целую цепочку нетривиальных задач, от эффективного декодирования до аккуратного отката к старым форматам на тех платформах, где новые пока не поддерживаются. В следующих разделах мы подробно разберём, как в Discord справились с этими вызовами, чтобы пользователи платформы могли свободно обращаться с картинками нового поколения.
Технический подвиг
Модернизация конвейера обработки изображений в Discord не сводилась просто к добавлению поддержки нового формата, а требовала тщательно скоординировать эти изменения в масштабах всей инфраструктуры, отвечающей на платформе за обслуживание медиа. Ежедневно на платформе действуют сотни миллионов пользователей, которые обмениваются миллиардами картинок. Для такой аудитории требовалось обеспечивать бесшовную совместимость, в то же время позаботившись о гладком переходе к работе с новыми форматами изображений.
Сложность кроссплатформенности
Поддерживать новые форматы изображений в таком масштабе, как требуется в Discord — значит гарантировать, что они будут надёжно обрабатываться везде. Речь о таких разных платформах, как всевозможные браузеры, операционные системы для ПК (Windows, macOS, Linux), iOS и Android. На каждой из этих платформ действуют собственные уникальные требования и ограничения. Discord должен проверять и конвертировать все прикреплённые изображения (которые при этом остаются анимированными) и при этом динамически подбирать для них размер и правильно их встраивать. Всё это нужно для согласованного отображения картинок, так, чтобы они примерно одинаково выглядели у всех пользователей, работающих с разнообразными поддерживаемыми платформами. Вот основная причина, почему внедрять поддержку новых форматов настолько непросто.
Притом, что и у WebP, и у AVIF есть замечательные сильные стороны, требовалось выработать чёткие критерии, чтобы выбрать, какой из двух форматов поддерживать. Всё обдумав, предпочли WebP как основной целевой формат для преобразования. На это было несколько причин:
-
Почти универсальная поддержка на разнообразных платформах
-
Кодирование/декодирование происходит быстрее, чем при работе с форматом AVIF
-
Зрелый инструментарий и обширная поддержка в разных экосистемах
-
Предсказуемые показатели производительности
Однако, останавливаясь на этом формате, кое-с-чем пришлось смириться:
-
Доступна всего лишь 8-разрядная глубина цвета по сравнению с поддержкой 10/12-разрядов, имеющейся в AVIF. Эта разница особенно важна при работе с HDR-контентом, в котором обычно используются 10-разрядные цвета
-
Файлы получаются крупнее, чем эквивалентные файлы AVIF
-
Определённые типы содержимого не слишком эффективно поддаются сжатию
Для обеспечения максимальной совместимости было решено преобразовывать AVIF-содержимое в WebP, при этом стараясь поддерживать наивысшее возможное качество картинки. Исходные изображения HDR AVIF тонально отображаются в SDR. Это делается для максимально полного сохранения цветовых характеристик от оригинального изображения.
Производительность под iOS
Оказалось, что отображать анимированные WebP-картинки под iOS донельзя сложно. В Discord прибегли к библиотеке SDWebImage, предназначенной для эффективного показа всевозможных изображений в iOS. В SDWebImage есть встроенный механизм для показа WebP с применением фреймворка ImageIO от Apple. Такое решение напрашивалось само собой, поскольку полагает пользоваться возможностями, реализованными в iOS 14+.
Но при тестировании производительности была выявлена проблема с нестабильной длительностью кадров. Оказалось, что анимированные WebP итерация за итерацией воспроизводятся всё медленнее, и этот эффект постепенно нарастает. Проблема особенно заметна с теми анимациями, в которых повышено разрешение или содержится сравнительно много кадров.
На следующем видео для сравнения продемонстрировано декодирование анимированного WebP с применением ImageIO (слева) и libwebp (справа). Для демонстрации был выбран 10-секундный анимированный 480p30-файл в формате WebP. Декодирование с применением libwebp происходит в режиме реального времени и, как и ожидалось, завершается за 10 секунд. Но, если выполнять декодирование с применением ImageIO, то наблюдается запаздывание более чем на 3 секунды, и со временем эта задержка усугубляется.

После тщательного исследования и профилирования команда стала декодировать WebP при помощи libwebp, в которую устанавливался аддон SDWebImageWebPCoder для взаимодействия с SDWebImage
. Притом, насколько невелико было это изменение, эффект от него оказался драматическим — все проблемы с анимированными WebP полностью исчезли.
Было
// Используем декодер WebP, встроенный в ImageIO — он доступен в iOS 14+ [[SDImageCodersManager sharedManager] addCoder:[SDImageAWebPCoder sharedCoder]];
Стало
#import <SDWebImageWebPCoder/SDImageWebPCoder.h> ... // Используем инструмент SDWebImageWebPCoder для декодирования WebP с применением libwebp. [[SDImageCodersManager sharedManager] addCoder:[SDImageWebPCoder sharedCoder]];
Обнаружение и обработка анимации
Одна из сложнейших задач заключалась в том, как организовать надёжное обнаружение и сохранение анимации. Ранее в Discord для обнаружения анимированного содержимого просто проверялось, есть ли у файла расширение GIF. Но файлы WebP и AVIF могут быть как статическими, так и анимированными, и в расширении файла это никак не отражается. Поэтому потребовалось внести в инфраструктуру ряд ключевых изменений:
-
Анализ файлов WebP и AVIF в процессе загрузки, чтобы в это время обнаруживать статус анимации
-
Хранение метаданных об анимации и распространение их через API и прочие системы Discord
-
Учёт настроек Discord, связанных с доступностью, в частности, опции минимизации движения (Reduced Motion). Благодаря этому анимированные файлы WebP и AVIF могут отображаться как статическими, так и динамическими, в зависимости от того, какие настройки выбрал пользователь

Удаление данных EXIF из файлов WebP
Исторически Discord полагался на использование Python-библиотеки piexif, при помощи которой EXIF-данные извлекаются из медиа-файлов. Правда, выяснилось, что из-за багов piexif метаданные WebP повреждаются именно в процессе удаления EXIF. Из-за этого становится невозможно воспроизводить анимированные WebP-файлы, ранее сохранённые на платформе — даже если вынести их за пределы Discord. Эта проблема сохранялась годами и касалась абсолютно всех анимированных WebP-файлов, загруженных на Discord. Отдельное спасибо nico с Github за то, что сообщил об этой проблеме!
Чтобы решить её, были заведены пул-реквесты, направленные в вышестоящий репозиторий библиотеки piexif:
https://github.com/hMatoba/Piexif/issues/145
https://github.com/hMatoba/Piexif/issues/144
Реализация
В основе — опенсорс
Путь к выстраиванию поддержки для современных форматов изображений начался с библиотеки Lilliput с открытым исходным кодом, предназначенной для обработки изображений. Притом, что Lilliput уже давно обслуживает GIF-анимации, работа с WebP и AVIF оказалась для неё очень нетривиальной. Дело в том, что в каждом из таких изображений может содержаться как один, так и несколько кадров, а статус анимации определяется в зависимости от метаданных, выставленных на уровне файла. Таким образом, потребовалось существенно скорректировать, как Lilliput обнаруживает анимацию, сообщает о ней и преобразует такие файлы.
Первым делом было решено организовать поддержку анимированных WebP. Кульминацией этой работы стал выпуск Lilliput v1.3.1. Этот релиз был тепло воспринят сторонними пользователями Lilliput, породив всплеск активности в сообществе. Добавились, в частности, GitHub Actions CI и нативная поддержка этой библиотеки в Apple.
Поэтапный ввод поддержки
Поддержку всех этих возможностей пришлось вводить поэтапно, поскольку всю работу было нужно тщательно координировать сразу на множестве платформ:
Этап 1: Преобразования анимированных WebP для веб-версии и ПК
Для начала в поддержка анимированных WebP была добавлена в Lilliput и в сервис Media Proxy самого Discord. Для этого пришлось внести ряд ключевых изменений. В частности, требовалось обнаруживать анимированные изображения на этапе проверки метаданных у новых прикреплённых файлов и на лету активировать возможность преобразования динамического варианта в статический и обратно. Такой процесс проверки метаданных применяется как при прямой загрузке через Discord API, так и при встраивании ссылок через Discord Unfurler.
Чтобы отслеживать статус анимации, к метаданным сообщения был добавлен флаг is_animated, который долговременно сохраняется на Discord API. Ориентируясь на этот флаг, клиент Discord может правильно обрабатывать анимированные изображения — ведь к ним нужен иной подход, нежели к статическим.
Далее потребовалось обновить написанный на React клиент Discord для веб-версии и версии для ПК, чтобы он корректно обрабатывал новый флаг is_animated. Поскольку файлы WebP и AVIF нельзя однозначно идентифицировать как анимированные только по их расширениям или MIME-типам, сквозь всю логику обработки картинок в приложении пришлось наладить проверку флагов анимированности.
Оказалось, что клиенты для веб-версии и ПК идеально подошли в качестве тестовых площадок для проверки этих изменений на бэкенде. Эти платформы располагают к быстрым итерациям, быстрому развёртыванию. Кроме того, на них не составляет труда выкатить что-нибудь в качестве эксперимента — в том числе, и рассматриваемую здесь систему флагов. В мобильной версии это тоже возможно, но циклы обратной связи получаются более длительными.
Этап 2: Мобильные анимированные WebP
Далее была добавлена поддержка для прикреплённых анимированных WebP-картинок и вставок на мобильных платформах. Реализовать это в Android получилось без труда, поскольку поддержка WebP глубоко интегрирована в операционную систему Android. В свою очередь, с iOS пришлось попотеть, так как предусмотренная в этой операционной системе поддержка WebP не удовлетворяет требованиям Discord по производительности. В качестве эксперимента эта фича поступательно выкатывалась на обеих платформах.
В ходе тестирования производительности WebP на мобильных устройствах в Discord также запустили параллельную инициативу, призванную повысить производительность: решили выдавать все анимированные эмодзи не в GIF, а в WebP. Такое изменение отлично демонстрирует эффективность проделанной работы, и особенно это касается преобразования GIF в WebP — тех самых возможностей, что были добавлены в Lilliput и Media Proxy. Ниже мы подробнее исследуем, как эти изменения повлияли на производительность.
Этап 3: поддержка AVIF
Опираясь на ту работу, которая была проделана над анимированными WebP, стек расширили так, чтобы предусмотреть в нём поддержку AVIF. Притом, насколько WebP хорошо подходит в веб-оптимизации, AVIF даже превосходит его в этом качестве, если требуется поддержка высококачественных фото и анимации. Поскольку с обоими форматами возникли схожие технологические сложности, команда Discord быстро интегрировала AVIF в масштабах всей системы.
Занявшись поддержкой AVIF, для начала добавили в Lilliput зависимости, относящиеся к AVIF: libyuv, aom и libavif. Эти зависимости нативного кода компилируются в двоичные библиотеки для Media Proxy и далее поспособствовали эффективной обработке изображений.
Далее в код Lilliput, написанный на C++, а также в код на Golang была была добавлена поддержка обнаружения AVIF и преобразования в этот формат. Поскольку метаданные и операции AVIF чисто отображаются на WebP, такая интеграция не составила труда. Поскольку незадолго до того довелось портировать Media Proxy с Go на Rust, потребовалось внести лишь минимальные изменения, чтобы состыковать Rust Media Proxy с кодом Lilliput, относящимся к обработке AVIF.
Наконец, поддержка файлов типа AVIF была добавлена в пределах всего приложения Discord. Принципиально работа велась по тем же паттернам, что уже были налажены с WebP.

Результаты и эффект
Файлы радикально уменьшились
Благодаря переходу к анимированным WebP, удалось существенно повысить производительность. Особенно это касается работы с анимированными эмодзи, которые используются в приложении Discord повсюду, на всех платформах. Для пользователей Discord это со всех сторон удобно: меньше данных скачивать, меньше кэша тратится на устройстве, причём, снижается вероятность промахов кэша как на устройстве, так и в CDN-сети Discord.
-
На 29,39% сократился медианный размер ответного пакета (с 31,3 КБ до 22,1 КБ)

-
На 42,54% сократился размер ответного пакета в 95-й перцентили (с 228 КБ до 131 КБ)

-
Более 61% эмодзи компактнее 231 КБ в формате WebP уменьшились, что видно в приведённом ниже чате. Здесь мы наблюдаем, как изменяется размер анимированных эмодзи при преобразовании их в WebP из GIF

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

Стремительное внедрение
Сразу после релиза эти новые возможности стали быстро подхватываться на всех платформах:
-
Более 95% запросов на анимированные эмодзи теперь касаются картинок в формате WebP
-
Сообразно этому упало количество запросов на эмодзи в унаследованном формате GIF
-
Плавные переходы на всех клиентских платформах
Поддержка анимированных WebP стала доступна на всех платформах после релиза мобильной версии 252 и выше, то есть, после 2 ноября 2024 года. В период с 1 декабря 2024 года по 18 февраля 2025 года извлечение прикреплённых анимированных WebP-картинок увеличилось на 39%:

Количество ежедневно прикрепляемых AVIF-файлов возросло на 33% за последние 30 дней перед публикацией оригинала этой статьи и сейчас охватывает все платформы:

Восприятие в сообществе
В процессе работы компания Discord получила массу полезных и просто положительных отзывов от пользователей.
В настоящее время в Discord можно загружать и отображать анимированные WebP в качестве альтернативы GIF! Обратите внимание: по-видимому, эта фича пока поддерживается только в версии для ПК и в браузерах, а в мобильном приложении — пока нет. pic.twitter.com/EZuQVQCHou
— Discord Previews (@DiscordPreviews) September 28, 2024
Заключительные мысли
Что дальше
Внедрение поддержки анимированных картинок WebP и AVIF — это важная веха в эволюции медиа-инфраструктуры Discord. Но это только начало. Компания активно изучает, как сделать визуальную составляющую платформы ещё привлекательнее, при этом поддерживая производительность на том высоком уровне, на который привыкли рассчитывать пользователи.
Вот некоторые наиболее увлекательные области, в которых ведутся исследования:
-
Улучшение поддержки HDR путём опоры на продвинутое управление цветами, характерное для AVIF. Таким образом предполагается повысить качество изображений HDR AVIF путём тонального отображения в SDR при преобразовании в такие 8-разрядные форматы как WebP.
-
Ускорение преобразования анимированных изображений. Притом, что анимированные картинки WebP и AVIF были успешно интегрированы в конвейер обработки изображений, эти сложные форматы обрабатываются медленнее, чем хотелось бы. Просматриваются возможности уменьшить задержку при преобразовании, как на уровне библиотеки Lilliput, так и на уровне сервиса Media Proxy.
-
Поддержка преобразования из анимированных WebP и AVIF в GIF. Преобразование в GIF требуется поддерживать ради обратной совместимости с более ранними версиями приложения. Это непросто сделать, поскольку глубина цвета в GIF ограничена, и возможности форматов в целом не совпадают.
Опыт модернизации форматов изображений в Discord очень информативен, если вам понадобится управлять крупномасштабными изменениями инфраструктуры и при этом поддерживать обратную совместимость. Такой проект позволяет как следует оценить, каким образом лучше переходить на новые технологии обработки изображений, чтобы пользователи от этого только выиграли.
ссылка на оригинал статьи https://habr.com/ru/articles/897698/
Добавить комментарий