Автор: Цзян Миньси, инженер-разработчик Beichao.
Эта статья также была опубликована вличный блог
предисловие
Домашняя страница нашего официального сайта——Официальный сайт Бэй ЛяоПервым экраном имеет автоматическое воспроизведение видео-видео, медленно загружено видео заболевания. Я просто подумал, что это то, что файл был слишком большим, или скорость сети была слишком медленной, но когда я оптимизировал ее, я обнаружил, что этого не ожидал. Эта статья записывает процесс оптимизации и резюме опыта, надеясь помочь читателям.
статус-кво
Главная страница официального сайта состоит из 6 экранов, а основное содержимое первого экрана — это фоновое видео, которое автоматически воспроизводится в цикле. Если страница не кэшируется:
- Для появления видеоэкрана требуется несколько секунд, в течение которых виден только фоновый цвет страницы, а после появления первого кадра экран зависает на долгое время, иногда даже более чем на 10 секунд. упомянутые ниже.карта первого кадра
- После первого кадра экрана застреваетВоспроизведение не плавноеОпыт как слайд
Предварительное исследование
Чтобы оптимизировать проблему заикания при воспроизведении видео, я начинаю с размера видеофайла. скачатьMediaInfoПросмотр видеофайлов:
- Формат: mp4
- Разрешение: 1080P
- Битрейт: 4K
- Размер: 7,3 м
- Продолжительность: 15 секунд
Битрейт 4K очень высок для онлайн-видео, я использую инструменты сжатия видеофабрика форматовНастройте его и установите битрейт на 2400, что является приемлемым для качества изображения.На данный момент размер файла составляет 4,4 МБ. Видя, что размер файла был уменьшен до 60% от исходного размера, должен быть очевидный эффект оптимизации.
странный первый кадр
Упаковал и отправил в тестовую среду, но от эффекта мои очки упали: видео зависает чуть меньше, чем раньше, но плавность все равно ощущается явно, а проблема первого кадра видеокарты почти не улучшилась . Кажется, что уменьшение размера файла за счет сжатия скорости кода кажется каплей в море.
Подробно изучить
Поняв, что простой метод уменьшения размера файла ресурсов не сработает, я поискал в интернете решение, но обнаружил, что статей по теме очень мало, а причину первой фреймкарты так и не нашел. Я не мог найти решение, поэтому мне пришлось нащупывать себя.Я медленно догадывался в своем уме: если видео разделено на несколько частей, браузер может играть, пока загружается первая часть.Снизит ли это первая часть видео?проблема с картой кадра?
Загрузка видео по частям
Я разрезал исходное видео на два сегмента и, прослушав конечное событие тега видео, изменил src для переключения на второй сегмент после воспроизведения первого сегмента, а затем снова переключился на первый сегмент после второго сегмента. был воспроизведен. Зациклить этот процесс.
Хотя это и принесло некоторое улучшение проблемы карты первого кадра, побочный эффект таков: переключение экрана не плавное, и каждое переключение будет зависать примерно на одну секунду.
отражение
В конце концов я решил отказаться от практики сегментации видео. Причина в том, что с одной стороны длина видео всего 15 секунд, и смысл разбиения не велик, с другой стороны, я думаю, что даже если это решение можно будет плавно переключать, оно не будет лучшее решение, потому что оно не решает фундаментальной проблемы (почему застревает первый кадр видео).
Положение moov вызывает первую карту кадра? сломать легенду
Насчет того, почему медленно загружается первый кадр, я начал подозревать, что это связано с форматом mp4, искал, и во многих статьях упоминалась проблема moov:
Хотя mp4 поддерживает потоковое воспроизведение, «индекс» видео хранится в объекте moov, и видео начнет воспроизводиться только после того, как moov загрузит видео. Большинство mp4-файлов помещают этот moov в начало файла, но если он находится в конце, вам нужно загрузить весь файл, чтобы начать воспроизведение. Ссылаться наblog.CSDN.net/Golden Snake Langjun/AR….
Я посмотрел сжатый файл mp4, и в конце действительно есть moov. Поэтому я использовал qt-faststart (инструмент предварительной подготовки moov, основанный на ffmpeg) для предварительной обработки объекта moov. Но после моего теста я обнаружил, что moov не оптимизировал карту первого кадра, и производительность воспроизведения была такой же, как и в конце. И когда файл moov находится в конце, видео начинает воспроизводиться до загрузки файла, и ни один файл не может быть загружен до того, как его можно будет воспроизвести.
Поэтому я снова проверил информацию и, наконец, нашел причину: если сам сервер поддерживает поиск, то видео MP4 также можно играть нормально. Для справкисегмент fault.com/ah/119000001…
Поскольку это не moov вызвало первую карточку фрейма, в чем причина?
Формат, более подходящий для потоковой передачи по сети - flv
Пока проблема с картой первого кадра не решена, поэтому планирую попробовать другой формат видео.Есть ли формат видео более подходящий для онлайн воспроизведения, чем mp4?
Я искал много соответствующей информации, flv — это очень простой формат с характеристиками потоковой передачи, который очень подходит для потоковой передачи по сети. Если «индекс» видео mp4 хранится вместе целиком, то «индекс» flv хранится по сегментам. Возьмем простой пример: посмотрите на начало видео, mp4 нужно загрузить «индекс» всего видео, чтобы начать воспроизведение, а flv нужно загрузить только «индекс» начала.
Браузеры изначально не поддерживают декодирование FLV, которое обычно выполняется через флэш-память. Однако изПлагин Bilibili с открытым исходным кодом — flv.js, что позволяет тегу видео поддерживать воспроизведение FLV. Чтобы попробовать, может ли flv решить проблему карты первого кадра, я представил flv.js и преобразовал исходное видео в формат flv. flv.js после сжатия занимает всего 100 КБ+ и очень удобен в использовании.Пример кода выглядит следующим образом:
const flvjs = require('../fiv.js');
if (flvjs.isSupported()) {
var videoElement = $bgVideo[0];
var flvPlayer = flvjs.createPlayer({
type: 'flv',
url: src // 视频的地址
});
flvPlayer.attachMediaElement(videoElement);
flvPlayer.load();
flvPlayer.play();
}
Я протестировал его, и результаты меня удивили. Проблема с картой первого кадра решена, но воспроизведение по-прежнему не гладкое, а впечатление похоже на слайд-шоу. Хотя проблема не решена полностью, а flv.js не совместим с браузерами ниже IE10, по крайней мере, достигнут существенный прогресс. Тогда просто сосредоточьтесь на решении проблемы не плавного воспроизведения видео.
Узнайте, кто ворует скорость интернета
Проблема неплавного воспроизведения относительно проста, потому что загрузка слишком медленная или файл слишком большой. И файл уже сжат, просто нужно выяснить, почему загрузка идет медленно.
В это время я начал сосредотачиваться на статических ресурсах страницы, чтобы посмотреть, смогу ли я оптимизировать некоторые ресурсы, которые занимают много денег. Статические ресурсы были сжаты инструментом, когда они выпущены для производства, и нет места для дальнейшего сжатия. Моя идея состоит в том, чтобы попытаться сделать так, чтобы ресурсы, видимые на первом экране, загружались немедленно, а ресурсы за пределами первого экрана загружались лениво. Откройте инструмент разработчика браузера и обнаружите, что большинство файлов ресурсов очень маленькие, только один файл особенно большой, до 900+ КБ, и это движущееся изображение, и его нет на первом экране. На данный момент нам нужно рассмотреть, как загрузить изображение после загрузки видео. Основная идея заключается в динамическом добавлении тега изображения на страницу после загрузки видео.
Я проверил тег видеородное событие. Среди многих событий приостановка больше подходит для текущей сцены, которая срабатывает по завершении загрузки видео. Однако совместимость приостановки не очень хорошая, и ее нельзя запустить в браузерах с низкими версиями, таких как IE 9, но событие progress не имеет этой проблемы. Событие прогресса запускается при загрузке видео. Если загрузка видео занимает 10 секунд, прогресс будет запускаться каждую секунду в течение этих 10 секунд.
Прослушивая событие прогресса и устанавливая таймер для определения того, загружено ли видео, достигается отложенная загрузка анимации. Конкретный код выглядит следующим образом:
/**
监听事件progress,触发后设置定时器。每一次progress事件触发便会清空上一次的定时器。
假如在一秒内progress都没有触发,则视为下载完成,触发callback同时删除绑定。
**/
// $bgVideo[0]是视频的dom节点
afterDownload($bgVideo[0], function() {
$bgImg.removeClass('hiden');
});
function afterDownload(video, callback) {
// 计时器
var callbackTimer = null;
// progress事件回调函数。监听progress,直到一秒间不触发progress才执行callback
var progressCallBack = function() {
clearTimeout(callbackTimer);
// 设定1秒的定时器,触发后删除绑定,删除定时器
callbackTimer = setTimeout(function() {
callback();
video.removeEventListener('progress', progressCallBack);
}, 1000);
};
// 绑定事件
video.addEventListener('progress', progressCallBack);
}
В процессе отладки в приведенном выше коде возникла небольшая проблема. Событие прогресса иногда не срабатывает, если видео уже кэшировано, и то же самое касается события приостановки. Я предполагаю, что загрузка видео происходит слишком быстро, и addEventListener был загружен до его выполнения. Пытаюсь написать привязку события на html:
<video onprogress="progressCallBack" .../>
После принятия этого метода не будет проблем при нажатии F5 для непрерывного обновления во время локальной отладки, но иногда будут возникать проблемы при публикации на сервере, и ход события не запускается. В итоге я выбрал простой и грубый способ, установив 3-секундный таймер при инициализации страницы:
function afterDownload(video, callback) {
var callbackTimer = null;
var progressCallBack = function() { ... };
// 防止chrome在缓存的情况下,不触发progress
callbackTimer = setTimeout(function() {
callback();
clearTimeout(callbackTimer);
video.removeEventListener('progress', progressCallBack);
}, 3000);
video.addEventListener('progress', progressCallBack);
}
После входа на страницу, если событие прогресса не срабатывает в течение 3 секунд, считается, что видео закэшировано, и выполняется прямой обратный вызов, а привязка и таймер удаляются. Задача решена.
Хотя этот подход решает проблему, я не думаю, что реализация идеальна. Если у вас есть лучший способ, пожалуйста, оставьте комментарий ниже ☺
Простой в использовании и бесплатный инструмент для сжатия видео - Pill Toolbox
После вышеуказанной оптимизации эффект воспроизведения видео на домашней странице стал намного лучше, но время от времени все еще случаются зависания. Хотя я и раньше использовал Format Factory для сжатия видео, но, учитывая, что на рынке есть много других инструментов для сжатия видео, я отправился на Baidu, чтобы поискать больше, и нашел инструмент с хорошей репутацией под названием «Pill Toolbox».
По сравнению с предыдущей фабрикой форматов, Xiaowan Toolbox может напрямую удалять аудиопоток (видео не требует звука в требовании), так что объем видео меньше; операция более глупая, пользователю нужно только изменить CRF и разрешение в опциях, в основном требования по сжатию в большинстве случаев выполнены. Что касается CRF, процитируйте слова автора Xiaowan для введения:CRF (Const Quality, фиксированное качество), этот метод управления битрейтом настолько превосходен, что его можно использовать без подавления 2-проходного режима, то есть даже 1-проходный может обеспечить очень хорошее распределение и использование битрейта. Методы подавления, такие как режим качества, также доступны в других кодировщиках (таких как xvid или ERP, которые подавляют rmvb), но, насколько я знаю, они являются только «постоянным квантованием». X264 CRF основан на квантовании, согласно визуальной психологии человека. распределять битрейт более разумно, цель состоит в том, чтобы сделать качество видео как можно более равномерным, когда люди смотрят видео, но битрейт можно использовать максимально эффективно. У режима CRF есть и преимущество, многие не знают, какой битрейт надо жать для видео при съемке. CRF распределяет битрейт в соответствии с необходимостью, поэтому фактически избавляет от необходимости решать, какой битрейт необходим.
Здесь прикреплен набор инструментов для таблеток.Руководство по началу работы.
Наконец, используйте Pill Toolbox, чтобы попробовать разные значения CRF, а затем сравните их невооруженным глазом после нажатия, найдите баланс между качеством изображения и размером файла и нажмите видео до 3,4M при разрешении 1080P. И я попытался снова уменьшить разрешение, и обнаружил, что при уменьшении разрешения до 720P разница в качестве изображения не была очевидной. В конце концов, я выбрал разрешение 720p и параметр сжатия CRF23.На этот раз видео было подавлено до 2M, что очень мало по сравнению с исходными 7,3M.
Суммировать
Пока что видео может быть быстро обработано и воспроизведено плавно. В то же время также обнаружено, что независимо от того, используется ли формат mp4 или формат flv, проблема с первой картой кадра больше не существует. Для этой ситуации я протестировал его с функцией ограничения скорости Chrome.Только когда скорости Интернета недостаточно (либо скорость Интернета слишком низкая, либо видеофайл слишком большой), возникает проблема с первой картой кадра в формате mp4. видео. Поскольку мы сжали размер видео до достаточно маленького размера и отложили загрузку большого изображения, разница между flv и mp4 на данный момент незначительна. В конце концов, я снял flv.js и использовал для воспроизведения файлы mp4.
конец
В этой статье описан весь процесс оптимизации первого экрана и часть полученного мною опыта.Этот процесс ухабистый, и я надеюсь, что он поможет читателям избежать обходных путей. В то же время, я думаю, что оптимизация бесконечна, особенно мои знания о сжатии видео относительно слабы.Если в тексте что-то не так, или есть хорошие предложения, пожалуйста, читатели.
Пополнить
После отзывов восторженных пользователей сети я обнаружил, что в моем понимании moov есть некоторые отклонения, и при воспроизведении первого видео на экране в Chrome возникают две проблемы:
- Файл mp4 инициирует три запроса
- Иногда анимация начинает загружаться до загрузки видео (не удалось прослушать событие прогресса)
В браузерах IE9 и Firefox две вышеуказанные проблемы воспроизвести невозможно.Поскольку при разработке я в основном использую Firefox, я пренебрег этими двумя проблемами. Я искал соответствующую информацию и использовал три файла mp4 с разной структурной последовательностью для сравнительного теста.Теперь я поделюсь с вами результатами:
Приложены три схемы структуры файлов mp4 с задними элементами moov, передними элементами без метаданных и передними элементами Moov с метаданными:
Прежде всего, передняя и задняя части файла moov будут влиять на Fast Streaming (быстрое воспроизведение) видео.Если сервер не поддерживает поиск, файл за moov необходимо загрузить, прежде чем его можно будет воспроизвести, и если сервер поддерживает поиск, на стороне тоже можно играть, но браузер отправляет три запроса. Процесс этих трех запросов, если говорить простым языком: первый запрос скачать из шапки файла и найти метаданные необходимые для воспроизведения в moov, а когда их невозможно получить, то отправит второй запрос с конца файл. Загрузите и выполните поиск, найдите содержимое, а затем инициируйте третий запрос, чтобы запросить содержимое файла. В это время начинается воспроизведение видео. Для онлайн-воспроизведения отправка трех запросов займет как минимум на несколько сотен миллисекунд больше, чем отправка одного.Во-вторых, Fast Streaming не обязательно возможен при предустановленном moov.Метаданные видео хранятся в moov.udta.meta.Если moov.udta.meta нет, то требуется три запроса. В процессе тестирования обнаружил, что moov.udta.meta отсутствует, но файл pre-moov нужно запрашивать три раза в хроме, а в Firefox только один раз. думаю, что это другой браузер на данный момент.Стратегии приняты разные.
Поскольку предыдущее использование Xiaowan toolbox заключалось в том, чтобы подавить файл без мета после moov, использование qt-faststart только добавляло перед moov, но не генерировало moov.udta.meta, поэтому в Chrome появилось три запроса, которые повлияли на ход выполнения. к двум вышеуказанным проблемам. После этого он был изменен на использование оптимизации ffmpeg (ffmpeg -i input.mp4 -movflags faststart -acodec copy -vcodec copy output.mp4), а moov.udta.meta был сгенерирован под moov, и две вышеуказанные проблемы исчезли.
Ссылаться на:
Optimizing MP4 Video for Fast Streaming
Understanding the MPEG-4 movie atom | Adobe Developer Connection