А теперь о подробностях реализации.
Всё началось с дискуссии в чатике Telegram-разработчиков о грядущей фиче:
Мужик сказал — мужик сделал! Первый прототип на Pillow и svgwrite, разбирающий GIF’ку на пиксели и преобразующий их в векторные квадратики с предпросмотром в SVG, был написан за один выходной.
Веселье началось дальше…
JSON — открытый формат, говорили они.
Доселе с форматами в Telegram то и дело хитрили. Сделали поддержку GIF-анимаций — на самом деле они конвертируются в MP4-видео. Сделали поддержку стикеров — выгружаются они в PNG, но преобразуются в WebP. В этот раз всё честнее: что на входе, то и на выходе.
Для анимированных стикеров в Telegram используется не GIF, не видео, и даже не какой-нибудь устоявшийся формат векторной графики типа SVG или — упаси Ктулху! — Flash. В нём задействован новомодный формат, вышедший из-под крыла Airbnb — Lottie. Доселе он имел некоторую известность в среде мобильных разработчиков, но благодаря Telegram, возможно, обретёт бо́льшую популярность.
Как в Телеграмме найти GIF картинки на любую тематику?
По сути своей, файлы Lottie являются сериализованными в JSON проектами Adobe After Effects, по максимуму реализующими все возможности этой программы. С отображением, увы, всё не так радужно. Хотя готовых «официальных» реализаций библиотеки для рендеринга Lottie и много, как раз под покрываемые Telegram платформы: Android, iOS, Qt и Web — лишь часть из возможностей формата реализована во всех из них. В Telegram пошли ещё дальше и ограничили перечень поддерживаемых возможностей, а также «придумали» свой формат, который отличается от обычного Lottie всего лишь упаковкой в GZip и параметром «tgs»: 1 . Кажется, я знаю, где сейчас работает Денис Попов! 🙂
И если с документацией на библиотеки для разных платформ всё довольно неплохо, то найти хоть какое-то описание устройства формата, увы, не удалось — только JSON-схему в исходниках lottie-web. Пришлось попутно ковыряться в существующих анимациях, дабы понять общие концепции формата. Также обнаружились расхождения реальных файлов со схемой: в частности, в слоях типа 4, согласно схеме, вложенные объекты хранятся в свойстве «it» — однако в реальных файлах ключ называется «shapes» , а «it» не работает.
Выясненные нюансы формата:
- Файл состоит из слоёв. В отличие от GIF, здесь у каждого слоя может быть произвольное время начала и конца отображения. К слою можно (точнее, нужно) применять различные трансформации: масштабирование, повороты, изменение прозрачности и т.д. Слои могут быть даже трёхмерными (запрещено для Telegram).
- Слой состоит из «фигур» (shapes). Типов у них много, некоторе нельзя использовать в Telegram. На практике, чтобы слой отобразился, он должен включать три фигуры: контур (в готовых анимациях это обычно тип «sh» — кривые Безье; конвертер пока использует только тип «rc» — прямоугольники), заливка (тип «fl» ) и трансформация (тип «tr» ).
- Можно даже включать растровые элементы, создавать текстовые слои, устанавливать взаимосвязи параметров слоёв и фигур через выражения. Вся эта вкуснотища также запрещена в Telegram.
Казалось бы, это и не проблема вовсе? Даже простенький GZip неплохо справляется со сжатием вопиюще повторяющихся данных, и 1 МБ сырого JSON магическим образом превращается в пару десятков килобайт, которые спокойно пролезают в заявленное ограничение в 64 кБ. Не тут-то было!
Загружаю я, значит, пухленькую анимацию, которая спокойно отображается lottie-web, в Telegram — и тут вместо условно красивого пиксель-арта на меня смотрит статическое размазанное вот это:
Что такое?! А оказалось, на разжатые данные тоже есть явно не указанное ограничение в 1 МБ. Представитель команды Telegram оперативно подтвердил его и сообщил о грядущем поднятии лимита до 2 МБ.
Даже если эти проблемы решат — стикеры, выходящие за пределы 1 МБ несжатых данных и не содержащие трансформаций, окажутся недоступными для пользователей старых версий Telegram. Так что придётся, видимо, соблюдать ограничения и впредь.
Прозрачность — это важно
Pillow, наряду с OpenCV, можно назвать индустриальным стандартом для обработки изображений в Python. Мало того, он неплохо заточен и под особенности GIF: поддерживает индексированные цвета, даёт доступ к палитре. Поддерживает преобразование пиксельной карты в NumPy-массив, что важно для продуктивной обработки. Даже статистику по цветам собирает! Но обнаружились и минусы:
- Не нашлось задокументированного способа получить индекс прозрачного цвета. Пришлось в качестве временного решения подразумевать, что прозрачный цвет — самый распространённый, но в реальных GIF’ках это не всегда так.
- То же самое с задержкой между кадрами: Pillow отдаёт только сами кадры как последовательность изображений, без информации о задержках.
- Иногда некорректно накладываются частичные кадры.
Прозрачность, как оказалось, gif2numpy не поддерживает вообще: цвета сразу преобразуются в три канала с разрядностью в байт, без учёта разрядности и сохранения индексов цветов. Благо, модуль состоит из одного файла, так что не составило труда включить его в проект и доработать, зарезервировав под прозрачность цвет #FE00FE .
Проблему с частичными кадрами решить оказалось нетривиально. gif2numpy пытается накладывать такие кадры на предыдущий, однако не проверяет параметры наложения, из-за чего также не всегда выходит правильный результат. Дабы не возиться с флагами, добавлена предварительная обработка изображений с помощью gifsicle с ключом —unoptimize — он преобразует частичные кадры в полные. А заодно приводит их к использованию глобальной палитры, что устранило необходимость отдельным образом обрабатывать прозрачный цвет при использовании собственной палитры кадра.
Сожми меня сильнее
Квадратики — это хорошо, но с такими ограничениями нужно проявить больше фантазии, иначе в Telegram не «пролезают» даже миниатюрные GIF’ки.
Первым в ход пошло нечто похоже на RLE : соседние по горизонтали квадратики одного цвета объединяются в один прямоугольник.
Далее — черёд эксплуатации особенностей Lottie. Поскольку каждый слой имеет произвольное время начала и конца — можно применить технику, которая давным-давно используется видеокодеками, и отчасти в самом GIF: квадратики, которые остаются на одном месте в течение нескольких кадров, можно слить в один слой, во время отображения которого сменяется несколько других. Что и реализовано, пока только для пар соседних слоёв.
Планы по развитию
Идей, которые здесь можно применить, навалом:
- Распознавать одноцветные области любого размера. Можно разбивать их на набор прямоугольников, для чего есть неплохой алгоритм. Также целесообразно преобразовывать их в контур, но это омрачается необходимостью указывать все точки кривых Безье в Lottie — прямоугольниками в некоторых случаях может быть выгоднее.
- Распознавать движение. Техника, опять-таки, издревле применяющаяся в видеокодеках. Если один и тот же контур не меняет форму от кадра к кадру, но лишь координаты — стоит вместо дублирования на нескольких слоях поместить его на один слой с трансформацией.
- Распознавать «накрытие» одних областей другими. Пример:
. .O..O. . .OOOO. .
Ссылки
- Исходники. Местами страшные.
- Канал, на котором я выкладываю паки успешно сконвертированных GIF’ок.
Источник: habr.com
Как сделать анимированный стикер в Telegram
Всем привет. Вы наверняка видели в Telegram анимированные стикеры. Эти забавные двигающиеся картинки отлично передают эмоции и представляют собой неплохую альтернативу гифкам и привычным стикерам. Но если создать обычный стикерпак довольно просто, то с анимированными изображениями придется повозиться. Вам понадобится пара программ от Adobe и немного фантазии. В этом уроке я покажу, как все это реализуется.
Подготавливаем инструменты
Вам будут необходимы редактор векторной графики Adobe Illustrator, редактор анимаций Adobe After Effects и минимальные навыки работы с ними.
Кроме того, к Adobe After Effects нужно подключить плагин Bodymovin-TG. Он экспортирует анимации в формат .TGS, поддерживаемый Telegram. Для этого закройте Adobe After Effects, если он открыт. Загрузите и установите приложение ZXPInstaller. Оно совместимо и с Windows, и с macOS. Скачайте плагин Bodymovin-TG (нужный вам файл называется bodymovin-tg.zxp).
Теперь запустите ZXPInstaller и щёлкните по его окну. Выберите загруженный плагин и подождите, пока приложение установит его.
Откройте Adobe After Effects. Затем сделайте следующее:
- На Windows откройте «Правка» → «Настройки» → «Сценарии и выражения…». Включите опцию «Разрешить сценариям выполнять запись файлов и осуществлять доступ к Сети». Нажмите OK.
- На macOS откройте Adobe After Effects → «Настройки» → «Сценарии и выражения…». Включите опцию «Разрешить сценариям выполнять запись файлов и осуществлять доступ к Сети». Кликните OK.
Нажмите «Окно» → «Расширения». Если вы всё сделали правильно, то в списке расширений вы увидите Bodymovin for Telegram Stickers.
Всё, инструменты настроены. Теперь пора творить.
Рисуем векторную графику
Создайте новый проект в Adobe Illustrator. Размер холста должен быть ровно 512 × 512 пикселей — это важно. У проекта не должно быть фона. Объекты не могут выходить за границы монтажной области.
Для примера мы нарисуем рожицу. Её можно составить из фигур на панели инструментов Illustrator. Каждая значимая для анимации часть (рука, нога, глаз) должна быть вынесена на отдельный слой. Лучше сразу подписать, что где, чтобы не запутаться.
Когда ваша графика будет готова, сохраните её в формате AI.
Импортируем графику в After Effects
Откройте After Effects и создайте композицию. Размеры её должны быть ровно 512 × 512 пикселей. Количество кадров в секунду — 30 или 60 (для несложной анимации вроде нашей подойдёт 30). Длительность композиции не должна превышать 3 секунды.
Затем нажмите «Файл» → «Импорт» → «Файл» и найдите вашу графику в формате AI. В выпадающем списке «Импортировать как:» выберите «Композиция — сохранить размеры слоёв» и нажмите «Импорт».
Ваша графика импортируется вместе со всеми слоями. Выделите их (они будут в формате AI) и перетащите на иконку «Создать новую композицию».
Программа запросит у вас подтверждение. Нажмите OK.
Порядок слоёв может немного нарушиться. Перетаскивайте их на панели слева внизу, размещая в нужной последовательности.
Теперь предстоит создать из векторных слоёв фигуры для анимирования. Для этого выделите слои и нажмите правую кнопку мыши, затем «Создать» → «Создать фигуры из векторного слоя». Получатся так называемые кривые.
После этого слои в формате AI можно удалить, чтобы не мешались. Выделите их с зажатой клавишей Ctrl и нажмите Delete. Останутся только кривые.
Готово, импорт завершён.
Создаем анимацию
В Adobe After Effects можно создавать очень разные по сложности анимации. Но мы не будем погружаться в дебри и для примера попробуем заставить нашу рожицу просто приподнимать бровь.
Выберите бровь, которую хотите анимировать, и щёлкните по ней левой кнопкой мыши. Нажмите на значок > рядом с кривой на панели слева снизу и выберите «Преобразовать».
С помощью появившихся значков на панели можно изменять положение, масштаб, угол поворота и степень прозрачности объектов в анимации. Поскольку нам нужно только поднимать бровь, обойдёмся изменением её положения.
Нажмите «Опорная точка» и «Положение». Затем перетащите временной указатель на шкале на третью секунду анимации (тяните до упора).
Нажмите на ромбики на левой боковой панели, слева от «Опорной точки» и «Положения». Таким образом вы зациклите свою анимацию: её первый кадр будет таким же, как и последний. Это важно, так как иначе Telegram не примет ваш стикер.
Теперь разместите временной указатель примерно посередине шкалы.
Снова нажмите на ромбики, чтобы создать опорную точку и там. И измените положение брови, подняв её. Это можно сделать используя цифры рядом с параметром «Положение» или перетянув бровь вручную мышкой либо клавишами со стрелками.
Нажмите на пробел, чтобы запустить воспроизведение анимации. Всё, бровь двигается.
Аналогично вы можете заставить шевелиться и другие объекты на анимации. Просто создавайте для них опорные точки, нажимая на ромбики, и меняйте их положение.
Экспортируем стикер
Нажмите «Окно» → «Расширения» → Bodymovin for Telegram Stickers. Выделите композицию, которую хотите экспортировать (в нашем случае — ту, что с пометкой «Бровь»). В параметре Destination Folder укажите папку, где сохранить ваш стикер. И нажмите Render.
Если всё в порядке, расширение отрапортует о завершение рендеринга. Нажмите Done. Если что-то не так, расширение подскажет вам. Правда, только по-английски.
Стикер будет сохранён в указанной вами папке под именем data.tgs.
Размещаем стикер в Telegram
Затем отправьте стикер боту, перетянув файл data.tgs в окно Telegram.
Бот попросит прислать смайл, с которым ассоциируется стикер, — сделайте это. Если у вас есть ещё анимированные варианты для этого набора, добавьте их.
Когда закончите, введите команду /publish и выберите ваш стикерпак в выпадающем списке. Ему можно назначить иконку, если она у вас есть (это должно быть изображение в формате TGS размером до 32 килобайт). Впрочем, этот шаг можно без проблем пропустить, перейдя к команде /skip.
Последний шаг — выбор короткого адреса для вашего набора. Бот создаст ссылку, по которой вы и ваши друзья получат доступ к стикеру. Нажмите на неё и сможете добавить новую анимацию в коллекцию, как обычно.
Собственноручно сделанный анимированный стикер готов. На этом у меня все. До скорого!
Подписывайтесь на канал Видеогуру, чтоб не пропускать новые интересные уроки.
Источник: guru.study