Vlc не может декодировать формат av01 no description for this codec
FFmpeg — это грандиозный Open Source проект, своего рода мультимедийная энциклопедия. С помощью FFmpeg можно решить огромное число задач компьютерного мультимедиа. Но все-таки иногда возникает необходимость в расширении FFmpeg. Стандартный способ — это внесение изменений в код проекта с последующей компиляцией новой версии. В статье подробно рассмотрено, как добавить новый кодек. Также рассмотрены некоторые возможности для подключения к FFmpeg внешних функций. Если нет необходимости добавлять кодек, то статья может оказаться полезной для лучшего понимания архитектуры кодеков FFmpeg и их настройки. Предполагается, что читатель знаком с архитектурой FFmpeg, процессом компиляции FFmpeg, а также имеет опыт программирования с использованием FFmpeg API. Описание актуально для FFmpeg 4.2 «Ada», август 2019.
Кодек (codec, происходит от объединения терминов COder и DECoder) является весьма распространенным термином и, как в таких случаях часто бывает, его значение несколько меняется в зависимости от контекста. Основное значение — это программное или аппаратное средство для сжатия/разжатия (compression/decompression) медиаданных. Вместо терминов сжатие/разжатие часто используют термины кодирование/декодирование (encoding/decoding). Но в ряде случаев под кодеком понимают скорее просто формат сжатия (говорят еще формат кодека), безотносительно к средствам, используемым для сжатия/разжатия. Посмотрим как термин кодек используется в FFmpeg.
FFmpeg кодеки собраны в библиотеке libavcodec.
1.1. Идентификатор кодека
В файле libavcodec/avcodec.h определено перечисление enum AVCodecID . Каждый элемент этого перечисления как раз и идентифицирует формат сжатия. Элементы этого перечисления должны иметь вид AV_CODEC_ID_XXX , где XXX уникальное имя идентификатора кодека в верхнем регистре. Вот примеры идентификаторов кодека: AV_CODEC_ID_H264 , AV_CODEC_ID_AAC . Для более подробного описания идентификатора кодека служит структура AVCodecDescriptor (объявлена в libavcodec/avcodec.h , приводится в сокращенном виде):
Ключевым членом этой структуры является id , остальные члены как раз и дают дополнительную информацию об идентификаторе кодека. Каждый идентификатор кодека однозначно связан с типом медиаданных (член type ) и имеет уникальное имя (член name ), записанное в нижнем регистре. В файле libavcodec/codec_desc.c определен массив типа AVCodecDescriptor . Для каждого идентификатора кодека имеется соответствующий элемент массива. Элементы этого массива должны быть упорядочены по значениям id , так как для поиска элементов используется двоичный поиск. Для получения информации об идентификаторе кодека можно использовать функции:
1.2. Кодек
Собственно кодек — набор средств, необходимых для выполнения кодирования/декодирования медиаданных, объединяет структура AVCodec (объявлена в libavcodec/avcodec.h ). Вот ее сокращенная версия, более полная будет рассматриваться ниже.
Так как несколько кодеков могут иметь один и тот же идентификатор, то две последние функции возвращают один из них, который можно считать кодеком по умолчанию для данного идентификатора кодека.
ffmpeg -codecs >codecs.txt
После выполнения команды, файл codecs.txt будет содержать этот список. Каждый идентификатор кодека будет представлен отдельной записью (строкой). Вот, например, запись для идентификатора кодека AV_CODEC_ID_H264 :
DEV.LS
h264
H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
(decoders: h264 h264_qsv h264_cuvid)
(encoders: libx264 libx264rgb h264_amf h264_nvenc h264_qsv nvenc nvenc_h264)
Процедуру добавления нового кодека в FFmpeg рассмотрим на примере аудиокодека, который назовем FROX .
Шаг 1. Добавить новый элемент в перечисление enum AVCodecID .
Это перечисление находится в файле libavcodec/avcodec.h . При добавлении надо соблюдать правила:
- Значение элемента не должно совпадать со значениями существующих элементов перечисления;
- Не менять значения существующих элементов перечисления;
- Размещать новое значение в группе сходных кодеков.
В соответствии с шаблоном, идентификатор этого элемента должен быть AV_CODEC_ID_FROX . Разместим его перед AV_CODEC_ID_PCM_S64LE и дадим значение 0x10700 .
Шаг 2. Добавить элемент в массив codec_descriptors (файл libavcodec/codec_desc.c ).
Добавить элемент надо в «правильное» место, не должна нарушаться монотонность элементов массива по значению id .
Шаг 3. Определить экземпляры AVCodec отдельно для кодера и декодера.
Для этого предварительно надо определить структуру для контекста кодека и несколько функций, которые и будут выполнять фактическое кодирование/декодирование и некоторые другие необходимые операции. В данном разделе эти определения будут сделаны предельно схематично, более детальное описание будет сделано дальше. Код разместим в файле libavcodec/frox.c .
Для простоты в этом примере кодер и декодер имеют один и тот же один контекст — FroxContext , но чаще всего кодер и декодер имеют разные контексты. Также обратим внимание на то, что имена экземпляров AVCodec должны следовать специальному шаблону.
Шаг 4. Добавить экземпляры AVCodec в список регистрации.
Переходим в файл libavcodec/allcodecs.c . В начале этого файла находятся список объявлений всех регистрируемых кодеков. Добавляем в этот список наши кодеки:
В процессе выполнения скрипт configure находит все такие объявления и генерирует файл libavcodec/codec_list.c , который содержит массив указателей на кодеки, объявленные в libavcodec/allcodecs.c . После выполнения скрипта в файле libavcodec/codec_list.c мы увидим:
Также в процессе выполнения скрипт configure генерирует файл config.h , в котором мы найдем объявления
Шаг 5. Отредактировать libavcodec/Makefile
Шаг 6. Отредактировать код мультиплексора и демультиплексора.
Мультиплексор (muxer) и демультиплексор (demuxer) должны «знать» новый кодек. При записи необходимо записать идентифицирующую информацию для этого кодека, при чтении определить идентификатор кодека по идентифицирующей информации. Вот что нужно сделать для формата matroska (файлы *.mkv ).
1. В файле libavformat/matroska.c в массив ff_mkv_codec_tags добавить элемент для нового кодека:
Строка "A_FROX" и будет записываться мультиплексором в файл в качестве идентифицирующей информации. В данном массиве она связывается с идентификатором кодека, поэтому демультиплексор при чтении сможет легко его определить. Демультиплексор записывает идентификатор кодека в член codec_id структуры AVCodecParameters . Указатель на эту структуру является членом структуры AVStream .
2. В файле libavformat/matroskaenc.c в массив additional_audio_tags добавить элемент:
Итак все готово. Сначала запускаем скрипт configure . После этого надо убедится, что описанные выше изменения в файлах libavcodec/codec_list.c и config.h сделаны. После чего можно запускать компиляцию:
Если компиляция прошла без ошибок, появляется исполняемый файл ffmpeg (или ffmpeg.exe , если целевой ОС является Windows). Выполняем команду
./ffmpeg -codecs >codecs.txt
и убеждаемся, что FFmpeg «видит» наши новые кодеки, в файле codecs.txt находим запись
DEA..S frox FROX audio (decoders: frox_dec) (encoders: frox_enc)
В этом разделе более подробно опишем, как может выглядеть структура контекста кодека и необходимые функции.
3.1. Контекст кодека
Контекст кодека может поддерживать установку опций. Для кодеров эта поддержка используется достаточно часто, для декодеров реже. Структура, поддерживающая установку опций, должна в качестве первого члена иметь указатель на структуру AVClass и далее сами опции.
Далее надо определить массив типа AVOption , каждый элемент которого и описывает конкретную опцию.
Для каждой опции необходимо определить имя, описание, смещение в структуре, тип. Можно также определить значение по умолчанию и для целочисленных опций диапазон допустимых значений.
Далее надо определить экземпляр типа AVClass .
Указатель на этот экземпляр надо использовать для инициализации соответствующего члена AVCodec .
Теперь при выполнении функции
будет создан экземпляр структуры AVCodecContext и инициализирован член codec . Далее на основе значения codec->priv_data_size будет выделена необходимая память для экземпляра FroxContext , используя значение codec->priv_class первый член этого экземпляра будет инициализирован и после этого будет вызвана функция av_opt_set_defaults() , которая установит значений по умолчанию для опций. Указатель на экземпляр FroxContext будет доступен через член priv_data структуры AVCodecContext .
При работе с FFmpeg API значения для опций можно установить непосредственно.
Другой способ — это использование словаря опций, который будет передаваться третьим аргументом при вызове avcodec_open2() (см. ниже).
С помощью функции
можно получить список всех опций, поддерживаемых контекстом кодека. Это бывает полезно при исследовании кодека. Но перед этим надо обязательно проверить, что codec_ctx->codec->priv_class установлен в ненулевое значение, в противном случае контекст не поддерживает опций и при любой операции с опциями произойдет аварийное завершение программы.
3.2. Функции
Рассмотрим теперь подробнее, как устроены функции, используемые при инициализации кодека и фактического кодирования/декодирования. В них обычно всегда требуется получить указатель на FroxContext .
Функции frox_decode_init() и frox_encode_init() будут вызваны при выполнении функции
В них надо выделить необходимые ресурсы для работы кодека, и при необходимости инициализировать некоторые члены структуры AVCodecContext , например frame_size для аудиокодера.
Функции frox_decode_close() и frox_encode_close() будут вызваны при выполнении
В них надо освободить выделенные ресурсы.
Рассмотрим функцию для реализации декодирования
Она должна реализовать следующие операции:
- Фактическое декодирование;
- Выделение необходимого буфера для выходного кадра;
- Копирование декодированных данных в буфер кадра.
Рассмотрим, как надо выделять необходимый буфер для выходного кадра. Параметр outdata на самом деле указывает на AVFrame , поэтому сначала надо выполнить преобразование типа:
Далее надо выделить буфер для хранения данных кадра. Для этого надо инициализировать члены AVFrame , определяющие размер буфера кадра. Для аудио это nb_samples , channel_layout , format (для видео width , height , format ).
После этого надо вызвать функцию
В качестве первого аргумента используется указатель на кадр, являющийся преобразованным параметром outdata , в качестве второго рекомендуется передавать ноль. После использования кадра (это происходит уже вне кодека), буфер, выделенный этой функцией, освобождается функцией
Функция frox_decode() должна возвращать количество байт, использованных для декодирования, из пакета, на который указывает pkt . Если формирование кадра завершено, то переменной, на которую указывает outdata_size присваивается ненулевое значение, иначе эта переменная получает значение 0 .
Рассмотрим функцию для реализации кодирования
Она должна реализовать следующие операции:
- Фактическое кодирование;
- Выделение необходимого буфера для выходного пакета;
- Копирование закодированных данных в буфер пакета.
Для выделения необходимого буфер используется функция
В качестве первого аргумента используется параметр pkt , в качестве второго размер закодированных данных. После использования пакета (это происходит уже вне кодека), буфер, выделенные этой функцией, освобождаются функцией
Если формирование пакета завершено, то переменной, на которую указывает got_pkt_ptr присваивается ненулевое значение, иначе эта переменная получает значение 0 . В случае отсутствия ошибки, функция возвращает ноль, иначе код ошибки.
При реализации кодека обычно используется логгирование (для ошибок это можно считать обязательным требованием). Вот пример:
В этом случае при выводе в лог в качестве имени контекста будет использовано имя кодека.
3.3. Метки времени
Для задания времени в FFmpeg используется единица времени (time base), задаваемая в секундах с помощью рационального числа, представляемого типом AVRational . (Аналогичный подход используется в C++11. Например 1/1000 задает миллисекунду.) Кадры и пакеты имеют метки времени (timestamps), имеющие тип int64_t , их значения содержат время в соответствующих единицах времени. Кадр, то есть структура AVFrame , имеет член pts (presentation timestamp), значение которого определяет относительное время сцены, запечатленной в кадре. Пакет, то есть структура AVPacket , имеет члены pts (presentation timestamp) и dts (decompression timestamp). Значение dts определяет относительное время передачи пакета на декодирование. Для простых кодеков оно совпадает с pts , но для сложных кодеков может отличатся (например для h264 при использовании B-frames), то есть пакеты могут декодироваться не в том порядке в котором должны использоваться кадры.
Единица времени определена для потока и кодека, структура AVStream имеет соответствующий член — time_base , такой же член имеет структура AVCodecContext .
Метки времени пакета, извлеченного из потока с помощью av_read_frame() , будут заданы в единицах времени этого потока. При декодировании единица времени кодека не используется. Для видеодекодера она обычно просто не задана, для аудиодекодера имеет стандартное значение — обратное к частоте дискретизации. Декодер должен установить метку времени для выходного кадра основываясь на метках времени пакета. FFmpeg самостоятельно определяет такую метку и записывает ее в член best_effort_timestamp структуры AVFrame . Все эти метки времени будут использовать единицу времени потока, из которого извлечен пакет.
Для кодера необходимо задавать единицу времени. В клиентском коде, организующем декодирование, надо установить значение для члена time_base структуры AVCodecContext перед вызовом avcodec_open2() . Обычно берут единицу времени, используемую для меток времени кодируемого кадра. Если этого не сделать, то видеокодеры обычно выдают ошибку, аудиокодеры устанавливают значение по умолчанию — обратное к частоте дискретизации. Может ли кодек изменить заданную единицу времени, не вполне ясно. На всякий случай лучше всегда проверять значение time_base после вызова avcodec_open2() и, если оно изменилось, пересчитывать метки времени входных кадров на единицу времени кодека. В процессе кодирования необходимо установить pts и dts пакета. После кодирования, перед записью пакета в выходной поток необходимо пересчитать метки времени пакета с единицы времени кодека на единицу времени потока. Для этого можно воспользоваться функцией
При записи пакетов в поток необходимо гарантировать, чтобы значения dts строго возрастали, иначе мультиплексор выдаст ошибку. (Подробнее см. документацию на функцию av_interleaved_write_frame() .)
3.4. Другие функции, используемые кодеком
При инициализации экземпляра AVCodec можно зарегистрировать еще две функции. Вот соответствующие члены AVCodec :
Первая из них вызывается один раз при регистрации кодека.
Вторая сбрасывает внутреннее состояние кодека, она будет вызывается во время выполнения функции
Этот вызов необходим, например, при принудительном изменении текущей позиции проигрывания.
4.1. Подключение внешней функции
Такого решение может быть желательно по многим причинам. Вот некоторые из них:
- Кодек носит экспериментальный характер и часто меняется, а компиляция FFmpeg является довольно трудоемким процессом;
- Кодек написан не на C, а на другом языке, например на C++;
- Кодек использует библиотеки или framework, которые трудно интегрировать в FFmpeg.
Не смотря на закрытую, монолитную архитектуру FFmpeg такой вариант возможен и является вполне «законным», то есть для его реализации требуется только стандартный FFmpeg API. И ключом для решения этой задачи является механизм опций с помощью которого «внутрь» FFmpeg можно передать указатель на внешнюю функцию (или указатель структуру, содержащую указатели на внешние функции), которая и реализует требуемый функционал. Наиболее естественный вариант — это использование опций бинарного типа. В нашем примере для декодера можно предложить примерно следующее.
На стороне клиента FFmpeg API (в данном примере написан на C++) можно предложить примерно следующее.
4.2. Внешний декодер
Она из важных идей компьютерного мультимедиа — это отделение кодека от медиаконтейнера. В идеале медиаконтейнер любого типа может хранить медиапотоки, закодированные любым кодеком. Конечно, в реальности это не всегда выполняется. Мы видели, что для того, чтобы FFmpeg мог записать в контейнер медиапоток, мультиплексор должен «знать» кодек, так как необходимо записать идентифицирующую информацию о кодеке. А вот при чтении это уже не совсем так. Демультиплексор без проблем извлекает пакеты, закодированные неизвестным кодеком. Если клиент FFmpeg API может как-то идентифицировать этот кодек и умеет декодировать медиаданные, закодированные этим кодеком, то становится возможным воспроизведение таких медиаданных. У автора имеется подобный опыт. В свое время пришлось работать с одним видеорегистратором, который использовал аппаратное сжатие в некотором проприетарном формате. Сжатые данные переносились на PC (Windows) и затем записывались с помощью DirectShow в AVI файл. На PC имелся программный декодер для этого формата и на его основе был написан фильтр-декодер в стандарте DirectShow. Формат идентифицировался с помощью 32-битного FourCC. (Записывался в член biCompression структуры BITMAPINFOHEADER .) Таким образом, эти файлы воспроизводились на любом DirectShow проигрывателе при условии, что на PC был инсталлирован этот фильтр-декодер. При попытке воспроизвести такой файл с помощью FFmpeg проигрывателя декодер, естественно, не был найден, но член codec_tag структуры AVCodecParameters содержал вышеупомянутый FourCC, что решало проблему идентификации кодека. На основе имеющегося декодера для клиента FFmpeg API был написан дополнительный декодер, которому и передавался пакет. Таким образом проблема воспроизведения таких файлов была решена с помощью стандартной сборки FFmpeg и использования FFmpeg API.
В ряде случаев неизвестный кодек можно идентифицировать по метаданным потока, например в *.mkv файлах FFmpeg записывает туда имя кодека (свойство ENCODER ).
В данной статье рассматривались только изменения в коде, не рассмотрены изменения, которые необходимо внести в другие части FFmpeg: документации, changelog, систему контроля версий и т.д. Но если вы планируете «домашнюю» сборку FFmpeg, предназначенную только для конкретного проекта, то этого можно не делать.
Общие вопросы архитектуры FFmpeg
[5] FFmpeg Compilation Guide
[6] Compilation of FFmpeg 4.0 in Windows 10
Для эффективного сжатия видеофайлов разрабатываются различные кодеки, например, AV1. Здесь я покажу, как включить воспроизведение видео AV1 в Windows, Linux и macOS.
Что такое AV1?
AV1 — видео-кодек, который был выпущен в марте 2018. Его создавали, чтобы превзойти кодеки предыдущего поколения — HEVC, VP9, H.264 и VP8.
За счёт новых оптимизаций, AV1 сжимает видео на 30—50% лучше, чем H.264 или VP8, и до 30% лучше, чем HEVC.
Диаграмма поколений кодеков от Цахи Левент-Леви
Кроме того, этот кодек не требует авторских отчислений и имеет открытый исходный код, что облегчает его широкое внедрение.
Включите воспроизведение видео AV1 на Windows, Linux и macOS
Windows
Чтобы получить поддержку AV1 под Windows, просто перейдите в официальный магазин Microsoft и скачайте официальное расширение AV1.
Linux and macOS
Поиск простого решения для воспроизведения видео AV1 на Linux и macOS не так прост, как в Windows. Однако есть решение — VLC, универсальный медиаплеер, поддерживает воспроизведение AV1. Достаточно установить VLC и использовать его для воспроизведения видео AV1.
Кроме того, Firefox также поддерживает воспроизведение AV1. Чтобы подтвердить, что воспроизведение AV1 включено:
1. В строке URL-адреса Firefox введите:
3. В поле поиска введите «media.av1.enabled». Убедитесь, что в записи написано «true». Если написано «false», переключите значение на «true».
Ожидается, что Chrome также будет поддерживать воспроизведение AV1 с выходом Chrome 85.
Респект за пост! Спасибо за работу!
Хотите больше постов в блоге? Подборок софта и сервисов, а также обзоры на гаджеты? Сейчас, чтобы писать регулярно и радовать вас большими обзорами, мне требуется помощь. Чтобы поддерживать сайт на регулярной основе, вы можете оформить подписку на российском сервисе Boosty. Или воспользоваться ЮMoney (бывшие Яндекс Деньги) для разовой поддержки:
Заранее спасибо! Все собранные средства будут пущены на развитие сайта. Поддержка проекта является подарком владельцу сайта.
Telegram
Последние
Рубрики
СЧЕТЧИКИ
РЕКЛАМА И ДОНАТЫ
Социальные сети
©2016-2022 Блог Евгения Левашова. Самое интересное и полезное из мира ИТ. Windows 10, Linux, Android и iOS. Обзоры программ и веб-сервисов. Статьи о мотивации и продуктивности.
Данный блог является личным дневником, содержащим частные мнения автора. В соответствии со статьей 29 Конституции РФ, каждый человек может иметь собственную точку зрения относительно его текстового, графического, аудио и видео наполнения, равно как и высказывать ее в любом формате. Блог не имеет лицензии Министерства культуры и массовых коммуникаций РФ и не является СМИ, а, следовательно, автор не гарантирует предоставления достоверной, не предвзятой и осмысленной информации. Сведения, содержащиеся в этом блоге не имеют никакого юридического смысла и не могут быть использованы в процессе судебного разбирательства. Автор блога не несёт ответственности за содержание комментариев к его записям.
A Carafe of Ubuntu
VLC could not decode the format "av01"
Since I just asked another question on here, something that I stumbled upon the other day
The question is in the title of course, but in full the error message says:
Ubuntu Member
What Windows plays or doesn't play is irrelevant. It has its own codecs and so on. This has zero bearing on Ubuntu. Did you install the ubuntu-restricted-extras package? It installs a lot of codecs and may help
Ubuntu addict and loving it
It would help if you give more info about the video or a download link if available. VLC version and how you installed it. We aren't mind readers.
BTW it works here.
Test videos from here.
vlc 3.0.16 installed from flatpak.
A Carafe of Ubuntu
No. I searched for that. The only information I found seemed to be pretty old. For instance this thread:
Anyway, I followed that, and the thing seems to have installed. Actually I don't know if it's any good, because I just found the video that I was looking for on YouTube in the end.
Ubuntu addict and loving it
Originally Posted by heatopher2
No. I searched for that. The only information I found seemed to be pretty old. For instance this thread:
Anyway, I followed that, and the thing seems to have installed. Actually I don't know if it's any good, because I just found the video that I was looking for on YouTube in the end.
A Carafe of Ubuntu
Originally Posted by monkeybrain20122
Yes, I solved my problem, as you can see, because I found the video somewhere else. The main reason for that being that I don't especially like answering questions that sound more like an interrogation than a help, so would rather not go down that road.
Ubuntu addict and loving it
We expect help requests to include a minimal amount of relevant details. A lot of times those details are omitted, so we ask for them. I think it is reasonable, and may only look like an interrogation because you are being cagey. Needless to say, you are free to refuse, but the reasoning buffles me quite a bit.
Ubuntu addict and loving it
Originally Posted by mikewhatever
We expect help requests to include a minimal amount of relevant details. A lot of times those details are omitted, so we ask for them. I think it is reasonable, and may only look like an interrogation because you are being cagey. Needless to say, you are free to refuse, but the reasoning buffles me quite a bit.
Yes, good point.
Too many threads fade into oblivion when relevant details are missing.
Forum searchers are especially keen to find solved threads which mirror their own problem.
Grande Half-n-Half Cinnamon Ubuntu
I might add my twopence to this: That a problem is solved is very satisfying for everyone.
What I miss more often then not is being told how it was solved.
I myself, and of course many others, use this forum to find a solution to a problem. Not being told how that was done is not so nice.
For someone has helped to find a solution, it is very satisfying to read how his (or her of course) assistance has helped.
Topsiho
В этом руководстве мы научимся использовать видео в Вебе, как это принято в 2019. Chrome и Firefox начали поддерживать новый кодек AV1 — для них видео можно сделать в два раза меньше.
Отдельно поговорим, как заменить GIF на видео в AV1 и H.264 — тогда его размер упадёт в 20-40 раз.
YouTube уже использует его в TestTube. Netflix заявил, что AV1 будет «их основным кодеком следующего поколения».
Мы в Злых Марсианах уже используем его на нашем сайте и на Ампллифере. В этой статье я поделюсь опытом внедрения AV1 и шаг-за-шагом расскажу, как вставить видео, чтобы оно работало во всех браузерах.
Кодеки и контейнеры
С картинками всё просто: или JPEG с PNG для всех браузеров, или делать более компактные файлы в WebP для современных браузеров. Мы всегда можем быть уверены, что в файлах .jpg будет PNG-формат (за редким исключением PNG-бомб, от которых может защитить imgproxy).
С видео-файлами всё сложнее. Расширение файла ( .mp4 , .wmv , .webm или .mov ) говорит только о контейнере. В то время, как видео-файлы состоят из трёх различных компонентов:
- Видео-кодек определяет как сильно вы сможете сжать видео, и чем придётся пожертвовать. Основные видео-кодеки Веба: H.264, HEVC, VP9 и, теперь, AV1.
- Аудио-кодек сжимает звук. Само собой, он не нужен, если в видео нет звука. Популярные варианты: MP3, Opus и AAC.
- Контейнер хранит оба видео- (сжатого каким-то видео-кодеком) и аудио-потока (сжатого каким-то аудио-кодеком). А также дополнительные данные, типа субтитров и мета-информации. Популярные контейнеры: MP4, MOV, WebM.
Узрите AV1
AV1 — видео-кодек, который был выпущен год назад, в марте 2018. Его создавали, чтобы превзойти кодеки предыдущего поколения — HEVC, VP9, H.264 и VP8.
Диаграмма поколений кодеков от Цахи Левент-Леви
Если вам стало интересно, как именно AV1 удалось превзойти остальные кодеки в сжатии, почитайте технические подробности в переводах на Хабре:
«Видео следующего поколения: представляем AV1»
«Кодек нового поколения AV1: корректирующий направленный фильтр CDEF»
За счёт новых оптимизаций, AV1 сжимает видео на 30—50% лучше, чем H.264 или VP8, и до 30% лучше, чем HEVC. Но кодек был выпущен недавно и пока имеет несколько детских болезней:
- Текущий кодер не оптимизирован. AV1 сжимает видео очень медленно (новый быстрый кодер на Rust уже в разработке). Кодек не подойдёт для потокового вещания. Если мы говорим о статичных видео на лэндингах — эта проблема нам не актуальна.
- Пока кодек поддерживается только десктопным Chrome и Firefox под Windows. Поддержки Safari и Edge пока нет (хотя Microsoft уже тестирует её). Надо будет, как минимум, 2 файла: AV1 для Chrome и Firefox и H.264 для остальных браузеров.
Сравнение качества картинки у разных кодеков на разном битрейте — AV1 выигрывает
Готовим AV1 правильно
Давайте, наконец-то, перейдём к практике. Вначале определимся с контейнером. В теории, AV1 можно поместить в разные контейнеры, но MP4 компактнее и рекомендуется в спецификации. Для звука в AV1 мы возьмём Opus, потому что отлично сжимает звук.
Чтобы видео работало во всех браузерах, мы будем генерировать 3 файла:
- Для десктопного Chrome и Firefox на Windows (31% рынка на март 2019): контейнер MP4 с AV1 для видео и Opus для звука.
- Для Safari и Edge (16% рынка) — MP4 с HEVC и AAC.
- Для остальных: большой MP4-файл с H.264 и AAC.
Для сжатия я рекомендую взять консольный FFmpeg. Есть много графических утилит, но в консоли легче сохранить опции и потом запускать конвертацию автоматически. Убедитесь, что используете именно последнюю версию FFmpeg. Версии до 4.1 не поддерживают AV1 в MP4.
Переходим к конвертации файла H.264, который нужен нам для старых браузеров. Поскольку все наши файлы используют контейнер MP4, я буду использовать .av1.mp4 , .hevc.mp4 и .h264.mp4 постфиксы. Не пугайтесь длинной команды, мы потом её всю разберём:
Теперь откройте video.h264.mp4 . Если качество хорошее, а размер большой — попробуйте увеличить -crf ( -crf 26 потом -crf 28 ). Эта опция уменьшит размер файла ценой уменьшения качества. Подбор баланса качества и размера — искусство.
Теперь пришло время для конвертации AV1 — напоминаю, будет дольше H.264. Кодек пока не использует всю мощь процессора (имеет смысл запустить конвертацию нескольких файлов параллельно).
Снова поиграйте с -crf для подбора идеального баланса качества и размера.
Теперь то же самое для HEVC.
Скопируйте video.h264.mp4 , video.hevc.mp4 и video.av1.mp4 в корень вашего сайта.
Разбираемся с опциями FFmpeg
Команды выше выглядят как заклинание вызова демона? Не волнуйтесь, это не PostCSS. Давайте разберём опции.
-i SOURCE.mov указывает входящий файл, откуда FFmpeg возьмёт потоки видео и аудио, пережмёт их и запакует в новый контейнер.
-map_metadata -1 удалит мета-информацию из видео (например, программу, в которой видео было создано). В Вебе такая информация редко бывает полезной.
-c:a libopus или -c:a libfdk_aac выставляют аудио-кодеки. Если вам не нужен звук, замените их на -an .
-c:v libaom-av1 выбирает видео-кодек — библиотеку, которая сожмёт кадры видео-потока.
-crf 34 — Constant Rate Factor, баланс качества и размера. Это как слайдер качества JPEG, только он идёт в другом направлении (0 — лучшее качество и самый большой файл). Шкала CRF разная у H.264 и AV1 — у H.264 идёт до 51, у AV1 до 61. CRF для AV1 и H.264 будет разный.
Facebook подобрал примерное соответствие между значениями CRF для H.264 и AV1:
19 → 27, 23 → 33, 27 → 39, 31 → 45, 35 → 51, 39 → 57.
-preset veryslow заставляет H.264 и HEVC кодеки сжимать файл сильнее даже ценой резкого роста времени конвертации.
-profile:v main используется у H.264, чтобы выбрать профиль кодека. Только «Main» будет работать в Safari.
-b:v 0 выставляет минимальный битрейт для AV1, чтобы в видео было постоянное качество.
-pix_fmt yuv420p (формат пикселя) — хитрый способ уменьшить размер файла. Он оставляет оригинальное разрешение для яркости, но уменьшает разрешение для цвета. Наши глаза хуже видят цвет, поэтому не замечают эту хитрость. Удалите эту опцию, если в вашем случае она будет мешать.
-movflags +faststart перемещает всё само важное в начало файла, чтобы браузер мог проигрывать видео до окончания загрузки.
-vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" изменит размер сторон видео к ближайшим чётным (некоторые кодеки могут работать с разрешением 300×200 и 302×200, но не будут работать с 301×200). Если вы уверены, что везде разрешение делится на 2 — можете убрать эту опцию.
-strict experimental нужна для AV1, его кодер ещё экспериментальный.
video.av1.mp4 выставляет имя итогово файла.
Запускаем видео в браузерах
Теперь нам нужно, чтобы каждый браузер загружал видео, которое он поддерживает. Для этого у есть атрибут type . И советую почитать про опции у .
похожи на выражения if…else — браузер читает их сверху вниз, пока не найдёт тот, чей type он поддерживает.
В type можно указать весь формат файла: контейнер ( video/mp4 для MP4), видео-кодек ( av01.0.05M.08 для AV1, hevc для HEVC и avc1.4D401E для H.264) и аудио-кодек ( opus для Opus и mp4a.40.2 для AAC).
Бонус: как сконвертировать GIF в AV1 и H.264
В 2019 использовать GIF для коротких видео — большой грех. GIF весит в 20—40 раз больше, чем H.264 или AV1. GIF сильнее бьёт по CPU, заставляет аккумулятор утекать быстрее. Если вам нужно короткое зацикленное видео, берите видео-кодеки. И FFmpeg может конвертировать видео прямо из GIF.
Конвертируем GIF в H.264:
Генерируем ещё более маленький AV1:
Теперь вставим animation.h264.mp4 и animation.av1.mp4 в HTML.
Опции autoplay и loop делают из видео «гифку» — цикленное видео, которое сразу играет после загрузки страницы. playsinline блокирует Safari от открытия видео на весь экран при клике на видео.
Время выводов
AV1 ещё экспериментальный. Но его уже можно использовать, чтобы сделать четверть ваших пользователей счастливее. Пара команд FFmpeg сгенерируют видео-файлы. с самого начала создан, чтобы отдавать видео по возможностям браузеров. Мы уже используем AV1 в продакшене и всё работает отлично (исключая время ожидания, пока AV1-кодер закончит работу).
Для того, чтобы дать медиаплееру возможность читать новые аудио- и видео форматы дополнительно устанавливаются кодеки. Для VLC Media Player тоже есть специальные наборы кодеков, позволяющие расширить его возможности.
Для чего нужны кодеки
Кодеки – это специальные программы, используемые в устройствах записи звука и видео для кодирования и сжатия видео- и аудиодорожки. Для работы с видеодорожкой используются видеокодеки, для аудиодорожки, соответственно, аудиокодеки. Сжатие необходимо для того, чтобы записанный видеофайл не занимал слишком много места в памяти записывающего устройства.
В устройствах воспроизведения, кодеки используются для того, чтобы раскодировать записанную информацию и воспроизвести её на устройстве.
Какие кодеки нужны VLC Медиа Плееру
Как и у большинства проигрывателей, у VLC Media Player изначально вшит определённый набор кодеков для чтения самых популярных форматов. С ним можно подробно ознакомиться на сайте.
Для того, чтобы посмотреть, какие из них используются при воспроизведении данного видео, нужно во время просмотра зайти в панель «инструменты» и выбрать строку «Информация о кодеке».
То же самое можно сделать комбинацией клавиш Ctrl+J
После чего откроется меню, в котором можно просмотреть все, используемые при раскодировании, программы.
Один из самых популярных видеокодеков – H264. Он соответствует формату MPEG-4, а именно в этом формате кодируется подавляющее большинство видеодорожек. Он позволяет сжимать видеодорожку практически без потерь в качестве, но при этом сильно уменьшить количество занимаемой памяти.
Кроме описанного выше формата, существует ещё несколько самых популярных декодеров, без которых не обойтись проигрывателю:
- 265 (MPEG-H, HEVC);
- Flash;
- MPEG-2;
- WMV;
- APE;
- FLAC.
Дополнительные кодеки
Не все проигрыватели могут воспроизводить такое количество файлов самых разных форматов. Поэтому для них разработчики из VideoLAN создали специальный пакет программ, называемый VLC codec pack.
На данный момент в сети доступна версия 2.0.5 данного комплекта, и скачать кодеки от VLC Media Player не составит большого труда. База данных же самого VLC постоянно обновляется разработчиками. Обычно эти обновления происходят автоматически, если была скачана официальная версия программы с сайта разработчиков.
Однако, если по каким-либо причинам обновление не произошло, можно проверить их наличие вручную. Для этого нужно на главном экране проигрывателя выбрать вкладку «Помощь» и в появившемся меню нажать «Проверить обновления».
В большинстве случаев программа уведомит пользователя о том, что у него установлена самая последняя версия посредством данного окна.
Но если обновления всё же найдутся, пройдёт небольшая процедура установки нового ПО и система опять же уведомит о том, что установлена самая последняя версия.
Проблемы при воспроизведении
Несмотря на обширную базу встроенных модулей декодирования и дополнительного программного обеспечения у VLC Медиа Плеера могут случаться проблемы с воспроизведением определённых форматов, вследствие чего может появиться такая ошибка.
Формат «undf», указывающий на ошибку кодека VLC, обозначает, что воспроизводимый формат распознался программой как неопознанный. Медиа Плеер просто не может декодировать воспроизводимый файл за неимением необходимого инструмента.
Чаще всего подобное происходит с пользователями linux, так как большинство декодеров в популярных проигрывателях всё же заточены под Windows. Кроме этого, может так случиться, что файл окажется повреждённым и воспроизвести его в принципе не представляется возможным.
Решение
Если же дело в кодеке, может помочь утилита GSpot Codec Information Appliance. Её можно скачать по ссылке с официального сайта.
Воспроизведение Blu-Ray дисков
Долгое время для того, чтобы просмотреть материал с Blu-Ray дисков нужно было использовать специальные коммерческие медиаплееры, которые имели ограниченную функциональность. Однако после выпуска организацией VideoLAN, библиотеки декодирования AACS, просмотр фильмов в формате Blu-ray стал доступен и через VLC Media Player. Библиотека полностью сертифицирована и может работать с дисками, защищёнными по технологии AACS.
Читайте также: