Для моей танцевальной игры, над которой я работаю, мне нужен был способ отредактировать видео, на которые они хотели танцевать, прежде чем публиковать их на главной странице для других.
Идея проста:
- Позвольте пользователям создавать «проекты» на своих компьютерах, которые состоят из всей информации, связанной с танцевальной диаграммой, включая название, артист, идентификатор танцевального видео и так далее.
- Редактор позволит пользователям точно настроить видео по своему вкусу и проанализировать его с помощью tensorflow.js.
- После анализа пользователи могут воспроизводить свои диаграммы в редакторе, чтобы убедиться, что все настроено правильно.
- Наконец, пользователи могут опубликовать свою танцевальную диаграмму на главной странице, чтобы любой мог сыграть в нее.
Проектирование интерфейса
Первым шагом в процессе было разработка интерфейса для редактора – как он должен выглядеть?
Я узнал, что разработка красивых графических пользовательских интерфейсов- Действительно сложно. Вот почему в университетах есть целая область обучения, и почему большинство компаний играют роль только для разработки внешнего вида продуктов. Это занимает невероятное количество времени, усилий и тонкой настройки, чтобы получить что-то, что выглядит прилично.
У меня нет опыта в дизайне, поэтому я старался изо всех сил, чтобы сделать что -то функциональное, выглядело нормально, и мне не нужно было слишком много времени. Я хочу быстро доставить свою игру в играбельное состояние, поэтому я не могу потратить месяцы, выясняя, как должен выглядеть редактор.
Через неделю или две разработки редактора я придумал следующие дизайны.
Целевая страница
Целевая страница – это просто место для управления вашим проектом. Вы можете либо отредактировать, так и существующий проект или создать новый с ссылкой на заголовок и YouTube. После того, как вы нажимаете на проект, он загружает и отображает следующий экран (на фото ниже).
Общий макет
В верхнем левом разделе в редакторе есть несколько разных вкладок – редактировать, просмотреть и публиковать. Мне пришлось придумать цель каждой из этих вкладок еще до того, как я начал создавать дизайн, который был немного сложным. Под этими вкладками есть кнопка сохранения.
Справа есть предварительный просмотр видео, который отображает видео при протирке с временной шкалой, и у него есть несколько элементов управления: воспроизведение/пауза, следующий/предыдущий кадр и перейти к началу/конец. В нижней области вы можете увидеть временную шкалу с помощью видео миниатюров в зависимости от времени, области для ключевых кадров и аудио -сигнала.
Вкладка «Редактировать»
Вкладка «Редактировать» содержит ассортимент того, что я называю «компонентами», или маленькими аддонами, которые изменяют различные свойства вашей танцевальной карты. Компонент Metadata Project – это компонент по умолчанию, который содержит множество подробностей о информации вашего проекта, такой как имя, название диаграммы, артист песни и сложность. Компонент заблокированной области позволяет вам разделить определенные области в видео, которые не будут использоваться для оценки. Это полезно: есть несколько человек, и вы хотите проанализировать движения только одного человека.
Некоторые свойства компонентов смогут быть рамкими во время видео, чтобы обеспечить анимацию. Например, это полезно для компонентов заблокированной области, чтобы вы могли перемещать заблокированную область, чтобы покрыть танцовщица, если они перемещаются на протяжении всего видео.
Вкладка обзора
Вкладка «Обзор» – это место, где вы просмотрите все компоненты, которые вы добавили, и анализируете видео с использованием tensorflow.js. Автоматический анализ протирает видео, используя модель Movenet и собирает данные для клавиатуры для каждого кадра (не совсем, но больше об реализации позже).
После того, как автоматический анализ будет проведен, в результате анализа будет показана любые потенциальные проблемы, которые были обнаружены при анализе. Эти проблемы могут мешать графике, когда играют, поэтому лучше попытаться решить их перед публикацией.
И здесь вы также можете пройти тест своей графики! Нажмите кнопку «Маленькая воспроизведение», чтобы проверить все, что вы собрали до сих пор.
The Publish Tab
Вкладка «Публикация» является самой основной вкладкой из трех и в основном предназначена для проверки и публикации на главной странице, чтобы каждый мог воспроизводить ее. Вы можете просмотреть всю информацию о своем проекте и диаграмме, а затем опубликовать его после того, как все чеки будут выполнены.
Реализация редактора
Теперь, когда дизайн и идея сделаны (пока) для редактора, пришло время его построить!
Макет сетки
Макет редактора выглядит как Дисплей: GRID Было бы идеально подходит для его разработки. Перед этим проектом я не знал, как использовать макет сетки в CSS.
С момента начала этого проекта, одной из моих целей было узнать гораздо больше о Web Dev и получить более глубокое понимание принципов вождения, лежащих в основе свойств. Один из способов, которым я это сделал, – это через Josh’s CSS для JS Course , что я очень рекомендую, если бы вы хотите глубже погрузиться в Почему Вещи в CSS кажутся тем, что они делают.
До того, как я прошел свой курс, меня часто снимались с тем, как делать что -то в CSS и почему они не работали, что привело к тому, что я пытался сделать случайные вещи, пока все не выглядело нормально. Этот подход часто приводил к проблемам в разных решениях.
Проходя большую часть курса, я гораздо более уверен в своих способностях CSS и своих способностях хорошо создавать пользовательский интерфейс. CSS для основного контейнера сетки выглядит немного примерно так:
main.grid-container {
display: grid;
width: 100%;
height: 100%;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(14, 1fr);
background-color: var(--color-gray-500);
gap: 1px;
--tabs-row-amount: 11; /* Amount of rows that the tabs section should have */
}
Это довольно просто, но я все равно объясню это, потому что это было что -то совершенно новое для меня, когда я впервые начал.
Это сетка, которая заполняет весь контейнер шириной и высотой на 100%. Затем мы указываем, сколько столбцов и строк должна иметь сетка – в моем случае, 3 столбца (1 для раздела вкладок и 2 для разделения предварительного просмотра видео) и 14 строк (14 были произвольными в зависимости от того, насколько толстым я хотел кнопку сохранения Будьте, так как я планировал, чтобы он занял высоту пространства одного ряда, прямо под разделом вкладок.
Затем я придаю ему цвет фона и зазор, а затем определяю переменную CSS, чтобы определить, насколько высокой должен быть раздел вкладок. -Tabs-Row-Amount Переменная рассказывает о некоторых других правилах CSS, сколько строк вступил в раздел вкладок, или, другими словами, какая его приблизительная высота должна быть.
Круто, верно? И тогда мы просто должны сообщить каждому разделу в сетке, какую строки и столбцы это должны занять. Вот пара фрагментов некоторых разделов:
section.tabs {
grid-column: 1 / 2;
grid-row: 1 / var(--tabs-row-amount);
overflow-y: auto;
}
section.timeline {
grid-column: 1 / -1;
grid-row: calc(var(--tabs-row-amount) + 1) / -1;
}
section.preview {
grid-column: 2 / -1;
grid-row: 1 / calc(var(--tabs-row-amount) + 1);
}
Сетка-Колонд сообщает сетке, в какую столбце следует занять раздел, охватывая от первого номера до второго номера. Если второе число составляет -1, он охватывает до конца. сетка следует той же концепции, за исключением рядов, чтобы охватить.
Самая сложная часть, которую нужно следовать, – это Calc Часть с рядами – это использует переменную CSS, которую я определил выше. Эта переменная определяет, где должны быть определенные разделы и сколько строк они должны занять.
Видео Предварительный просмотр
Это легко отобразить видео элемент, но как насчет того, чтобы ограничить пользователей, щелкнув правой кнопкой мыши и загрузки его? Это немного сложнее.
Пока я технически построил YouTube Video Downloader Для моей игры я не хочу, чтобы люди могли сохранить эти загруженные видео на своем компьютере. Я только хочу, чтобы они были доступны для использования с моей игрой. Это нелегко, и для более технических пользователей всегда есть способ обойти это.
Мое решение здесь состоит в том, чтобы использовать элемент Canvas для отображения видео, а затем синхронизировать звук с ним отдельно. Таким образом, вы не можете просто щелкнуть правой кнопкой мыши, чтобы сохранить видео; щелкнув правой кнопкой мыши только позволяет сохранить текущий кадр.
Есть несколько других причин для использования холста в экземпляре:
- У меня уже есть отдельные видео и аудиофайлы, поэтому мне все равно пришлось бы синхронизировать аудио/видео.
- Canvas позволяет мне легко нарисовать сложные вещи над видео, и это потребуется для определенных компонентов, таких как компонент заблокированных областей, где пользователи могут нарисовать формы на холсте.
- Tensorflow.js также может использовать холст вместо видео для анализа, что в конце концов делает вещи намного проще. Я могу просто нарисовать заблокированные области на холсте, и Tensorflow не сможет увидеть за ними.
Отображение видео на холсте несколько тривиально, с несколькими ключевыми шагами:
- Непрерывный цикл, чтобы продолжать захватывать каждый кадр видео, используя
window.requestanimationFrame. Я бы не рекомендовал использоватьSetInterval/settimeoutПоскольку это не хорошо играет с Цикл событий (нажмите отличное видео на цикле событий) Анкет - Используйте
DrawMageна 2D контекст холста Чтобы отобразить текущий кадр видео на холсте. Есть отличное решение для некоторых недостатков, просто используяDrawMage, что вы можете проверить Здесь Анкет
Одним из недостатков этого подхода на основе холста является то, что воспроизведение видео не так плавно, как обычное воспроизведение видео. Я ожидаю, что это ограничение requestAnimationFrame , Но я еще не нашел, что вызывает это. Это может быть способ обойти это, или, возможно, мой браузер ограничивает количество анимационных кадров в секунду.
Синхронизация аудио/видео было тривиальной задачей, поскольку главным препятствием является просто воспроизводить/приостановить их одновременно и убедиться, что их Currenttime s такие же.
Дизайн для предварительного просмотра видео также имел текущий номер кадра вместе с минутами и секундами по обе стороны от панели прогресса. Чтобы найти текущий кадр, вам понадобятся кадры в секунду видео, а затем вы сможете использовать что -то подобное:
Math.floor(((time % 60) % 1) * fps)
Выглядит немного странно, верно? Давайте разберем это.
время это текущее время в видео, например, 12,432 секунды. Сначала мы модируем его на 60, чтобы просто получить количество секунд за текущую минуту. Затем мы модируем его на 1, чтобы просто получить десятичную сумму для второго, например, 0,432. Умножение этого на кадры в секунду дает нам точную кадр, в котором видео включено, и все, что осталось сделать после этого, – это завершить его, чтобы получить равномерное число.
Пока я работал над предварительным просмотром видео, я нашел это невероятно полезным Mdn Page о аудио и видео манипуляции в Интернете.
Временная навигация
Навигация с использованием временной шкалы внизу будет наиболее используемым способом очистки в разных частях видео. Нажмите на любую часть, и она прыгнет прямо туда и поместите желтую линию в текущую позицию.
Это не так сложно сделать – просто используйте ВКЛ: Нажмите Событие и используйте событие Layerx Свойство и общая ширина сроков, чтобы определить процент сроки, которая была нажата. Мой код выглядит примерно так:
const percentClick = e.layerX / (width - timeline_padding * 2 - 2); // Account for padding + border width $createVideo.currentTime = percentClick * $createVideoDuration;
Используя процент от конца временной шкалы, я умножаю это на общую продолжительность видео, чтобы найти время, на которое пользователь нажимал, а затем установил текущее время видео.
Форма волны с временной шкалой
Я хотел отобразить звук в форме волны на временной шкале, чтобы легко увидеть, где находятся максимумы и падения песни, что должно сделать для более быстрой навигации.
Я подумал, что кто -то уже сделал пакет для генерации сигналов, и я нашел тот, который был довольно прост в использовании Здесь ! Вы в значительной степени просто создаете Wavesurfer, и вы уходите:
WaveSurfer.create({
container: '#waveform',
waveColor: 'rgb(38, 126, 97)',
progressColor: 'rgb(77, 189, 152)',
interact: false,
height: 50,
responsive: true,
hideScrollbar: true,
});
Одна вещь, которую я хочу подчеркнуть, это отзывчивый Вариант – установить это на Верно Убедитесь, что форма волны изменяется, если окно браузера будет изменен! В противном случае это вообще не изменится.
Временные миниатюры
Как видно из дизайна ранее, я хотел иметь маленькие миниатюры на временной шкале, чтобы показать, как видео примерно выглядит на разных временных метках.
Как обычно, первым шагом было осмотреть вокруг, чтобы увидеть, сделал ли кто -то что подобное. Кто -то имел в форме Видео-Метадата-Тумб . Он возвращает все миниатюры как куча каплей, которые мы можем использовать в качестве модных. Я попробовал это И это было Невероятно Медленно, даже с миниатюрами низкого качества.
Моим решением для этого было выбросить Только файл, который мне нужен и напишите метод, чтобы получить миниатюры от видео параллельно. Таким образом, каждый работник должен получить только часть миниатюр в видео, чтобы каждый из них должен был пройти быстрее.
Конечный результат сработал хорошо, но когда было слишком много случаев, работающих параллельно, это вызвало бы проблемы с задержкой и заиканием. Я решил управлять только тремя работниками параллельно, что все еще привело к огромному ускорению по сравнению с первоначальной реализацией.
Получив все миниатюры, мне нужно было показать их на временной шкале, что оказалось намного сложнее, чем я ожидал.
Чтобы отобразить миниатюры, мне сначала нужно было выяснить, сколько миниатюр следует отобразить, учитывая ширину временной шкалы. Но для этого мне нужно было выяснить ширину одной миниатюры, которая также оказалась немного сложной, учитывая, что ширина автоматическая на основе высоты пространства, выделенного для миниатюр.
В конце концов, после нескольких проб и ошибок, я смог это выяснить. Это немного сложно, и я сохраняю детали реализации. Но одна классная деталь, которую я хочу упомянуть, это то, что она автоматически получает более или менее миниатюры в зависимости от ширины графиков при изменении размера окна! Я думал, что это была аккуратная часть этого, поэтому, независимо от вашей экрана, у вас будут правильные миниатюры видео.
Автоматический анализ с TensorFlow
Tensorflow может проанализировать кадр видео или статического изображения и возвращать данные о человеке, обнаруженном в нем, если есть. Поскольку модель Movenet может работать в режиме реального времени, я могу просто воспроизвести видео обратно и запустить TensorFlow на нем, чтобы проанализировать его.
В то же время есть улов: не все кадры будут проанализированы и имеют данные для них. Модель обязательно будет немного медленной на некоторых кадрах или пропускает другие, поэтому у нас не будет данных для каждого кадра, и это нормально! В большинстве случаев движения человека не различаются в результате огромного количества между последовательными кадрами.
Я решил пойти немного дальше с этой идеей и добавить к анализу слайдер «Playback», который позволяет вам установить, как быстро видео восхищается при его анализе. В зависимости от характеристик вашего компьютера, вы можете ускорить его до 2x или 3x скорости и при этом получить хорошие результаты.
Я ударил по контрольно -пропускному пункту, сохраняя эти данные в классе с проектом, хотя; Он превысил максимальную квоту для объекта LocalStorage. LocalStorage может содержать только 5 МБ данных на веб -сайт. Я использовал Этот метод Чтобы проанализировать, сколько данных на самом деле хранилось в ключевых точках, и оказывается, что это было чуть менее 5 МБ, что слишком много для LocalStorage, особенно если вы хотите иметь несколько проектов. Решением для этого было снова использовать IndexedDB, который является тем же местом, на которое загружаются видео.
Результат
Прочитав все это, держу пари, что вы хотите увидеть, как это получилось, верно? Это похоже на дизайн, который я создал в начале?
Как оказалось, это так! Вот быстрое видео:
Я действительно доволен тем, как это получилось! Это прекрасно работает И я думаю, что это выглядит даже лучше, чем мой дизайн макета. Одно интересное примечание заключается в том, что время загрузки определяется и основано на количестве времени, которое требуется для генерации миниатюр, поэтому оно это точный погрузчик.
И когда я пишу это, я понимаю, что предварительный просмотр видео каким -то образом не сосредоточен – это было исправлено сейчас! 😅
Следующие шаги
С редактором в хорошей форме пришло время наконец поработать над Геймплей ! Нам нужно провести тесто к таблицам, которые мы делаем, и для этого нам нужен экраны геймплея, чтобы быть выясненным. Вскоре мы сможем танцевать на любое видео на YouTube и получить результаты в реальном времени, чтобы рассказать нам, насколько хорошо мы делаем. Следите за обновлениями!
Оригинал: “https://dev.to/benank/creating-a-video-editor-on-the-web-with-svelte-4ibf”