Разработка онлайн-редактора видео: браузерный монтаж и рендеринг

Разработка онлайн-редактора видео

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Разработка онлайн-редактора видео: браузерный монтаж и рендеринг
Сложный
от 2 недель до 3 месяцев

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1414
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1285
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    980
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1240
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    982
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    994

Разработка онлайн-редактора видео

Отметим: когда клиент просит сделать монтаж видео прямо в браузере — первое, с чем сталкивается команда: рендеринг финального результата. Если одну минуту ролика можно обработать на клиенте через FFmpeg.wasm, то десятиминутное видео «зависнет» даже на мощном ноутбуке. Мы прошли этот путь на нескольких проектах и выработали архитектуру, которая работает для любого масштаба. В этой статье разберём ключевые архитектурные решения: от типа рендеринга до реализации таймлайна и загрузки файлов. Вы узнаете, как выбрать стек, чтобы не переплачивать за серверы и не терять пользователей из-за тормозов. Мы также рассмотрим типичные ошибки, такие как создание тысяч запросов на один проект, и как их избежать. Если планируете создать браузерный видеоредактор — эта статья станет вашей архитектурной картой.

Браузер vs Сервер: где рендерить?

Выбор между клиентским и серверным рендерингом определяет весь стек и UX. Рассмотрим оба варианта в таблице.

Параметр Client-side (WebCodecs + FFmpeg.wasm) Server-side (Remotion + FFmpeg)
Зависимость от CPU пользователя Да Нет
Максимальная длительность видео ~2 мин Не ограничена
Время рендеринга 10 мин (CPU i7) 5–15 мин ~2 мин на GPU
Масштабирование Одно видео за раз Параллельные задачи (Lambda)
Поддержка браузеров Chrome 94+, Firefox 130+, Safari 16.4+ Любой браузер (файл по ссылке)
Стоимость инфраструктуры Нулевая Затраты на сервер (экономия до 40% при высокой нагрузке)

Client-side рендеринг (WebCodecs API + FFmpeg.wasm): не требует серверных мощностей, вся нагрузка на CPU пользователя. FFmpeg.wasm рендерит 10 минут видео за 5–15 минут реального времени (зависит от CPU). WebCodecs API поддерживается в Chrome 94+, Firefox 130+, Safari 16.4+. Идеален для коротких клипов до 2 минут — без задержек, без серверных затрат.

Server-side рендеринг (Remotion + FFmpeg): рендеринг на серверах с GPU, пользователь получает готовый файл по ссылке. Remotion позволяет описывать видео как React-компоненты, что даёт гибкость и переиспользование. Масштабируется через AWS Lambda — рендеринг параллельными чанками. Для коммерческого продукта с видео более 2 минут — это единственный надёжный путь. Мы в проектах чаще выбираем серверный подход: он даёт предсказуемое время рендеринга и не «съедает» батарею пользователя. Но в минимальном редакторе для коротких роликов клиентский вариант быстрее и дешевле.

Remotion официальная документация: https://remotion.dev/docs/

Как устроена временная шкала (таймлайн)?

Центральная UI-концепция — таймлайн с дорожками (треками). Структура данных:

interface VideoProject { id: string; duration: number; // секунды fps: number; // 24 | 30 | 60 width: number; height: number; tracks: Track[]; } interface Track { id: string; type: 'video' | 'audio' | 'text' | 'image' | 'effect'; clips: Clip[]; muted: boolean; locked: boolean; volume: number; // 0–1 } interface Clip { id: string; trackId: string; assetId: string; // ссылка на загруженный файл startTime: number; // позиция на таймлайне (секунды) duration: number; // длительность клипа trimStart: number; // обрезка начала исходного файла trimEnd: number; // обрезка конца speed: number; // 0.25 – 4.0 opacity: number; transform?: ClipTransform; filters?: VideoFilter[]; } 

Данные хранятся в сторе (Zustand или Redux) и синхронизируются с базой при сохранении. Drag-and-drop реализуем через @dnd-kit — он надёжно работает с перетаскиванием клипов по трекам.

Как разрезать клип на таймлайне?

Split (разрезать клип) — одна из базовых операций. Вот пошаговый алгоритм:

  1. Определите точку разреза в секундах относительно таймлайна (например, при перетаскивании маркера).
  2. Рассчитайте splitPoint = (atTime - clip.startTime) + clip.trimStart.
  3. Создайте два новых клипа: левый с trimEnd = splitPoint и правый с trimStart = splitPoint.
  4. Удалите исходный клип и добавьте новые.

Код:

const splitClip = (clipId: string, atTime: number) => { const clip = getClip(clipId); const splitPoint = atTime - clip.startTime + clip.trimStart; const leftClip: Clip = { ...clip, id: uuid(), duration: atTime - clip.startTime, trimEnd: splitPoint }; const rightClip: Clip = { ...clip, id: uuid(), startTime: atTime, duration: clip.startTime + clip.duration - atTime, trimStart: splitPoint, }; removeClip(clipId); addClip(leftClip); addClip(rightClip); }; 

Предпросмотр в браузере

Для предпросмотра используем HTML5 <video> с синхронизацией через currentTime. Вот ключевой hook:

const PreviewPlayer: React.FC = () => { const { currentTime, isPlaying, tracks } = useEditorStore(); const videoRefs = useRef<Map<string, HTMLVideoElement>>(new Map()); useEffect(() => { // Синхронизируем все видео-клипы с таймлайном tracks.forEach(track => { track.clips.forEach(clip => { const video = videoRefs.current.get(clip.id); if (!video) return; const clipTime = currentTime - clip.startTime; const isActive = clipTime >= 0 && clipTime <= clip.duration; video.style.display = isActive ? 'block' : 'none'; if (isActive) { const targetTime = clip.trimStart + clipTime * clip.speed; if (Math.abs(video.currentTime - targetTime) > 0.05) { video.currentTime = targetTime; } isPlaying ? video.play() : video.pause(); } else { video.pause(); } }); }); }, [currentTime, isPlaying]); // ... }; 

Скроббинг по таймлайну делаем через mousedown/mousemove — расчёт позиции в секундах от ширины контейнера.

Клипы: drag, trim, split

Перетаскивание: при drag клипа вычисляем дельту и обновляем startTime с учётом пикселей на секунду. Ограничиваем границами проекта и соседними клипами.

Trim (обрезка) реализуется аналогично split, но без удаления исходного клипа: достаточно изменить trimStart/trimEnd.

Серверный рендеринг через Remotion

Remotion позволяет описать видео как React-компонент. Передаём проект через inputProps и рендерим на сервере:

// Компонент для рендеринга const VideoComposition: React.FC<{ project: VideoProject }> = ({ project }) => { const frame = useCurrentFrame(); const { fps } = useVideoConfig(); const currentTime = frame / fps; return ( <AbsoluteFill style={{ background: '#000' }}> {project.tracks.flatMap(track => track.clips.map(clip => { const clipTime = currentTime - clip.startTime; if (clipTime < 0 || clipTime > clip.duration) return null; return ( <OffthreadVideo key={clip.id} src={clip.assetUrl} startFrom={Math.round(clip.trimStart * fps)} style={{ opacity: clip.opacity }} /> ); }) )} </AbsoluteFill> ); }; 

Запуск рендеринга через API с использованием renderMediaOnLambda для масштабирования.

Загрузка ассетов

Крупные файлы (видео, аудио) загружаем напрямую в S3 через presigned URL — минуем сервер приложения:

// 1. Запрашиваем presigned URL const { uploadUrl, key } = await api.post('/api/editor/upload-url', { filename: file.name, contentType: file.type, size: file.size, }); // 2. Загружаем напрямую в S3 с прогрессом const xhr = new XMLHttpRequest(); xhr.upload.addEventListener('progress', (e) => { setProgress(Math.round(e.loaded / e.total * 100)); }); xhr.open('PUT', uploadUrl); xhr.setRequestHeader('Content-Type', file.type); xhr.send(file); 

Этот подход разгружает сервер и повышает скорость загрузки. Свяжитесь с нами, чтобы обсудить детали вашего проекта.

Сроки и что входит в работу

Минимальный редактор (таймлайн, обрезка, предпросмотр, экспорт через Remotion) — от 13 до 17 рабочих дней. Полный функционал с эффектами, переходами и аудиомикшером — 20–25 дней. Стоимость базового решения стартует от 300 000 руб., а затраты на серверную инфраструктуру — от $200 в месяц.

Отметим: Что входит в результат:

  • Архитектура и код проекта с документацией API.
  • Инструкция по развёртыванию (Docker Compose, .env).
  • Доступы к репозиторию и CI/CD.
  • 12 месяцев гарантии на код и поддержка при внедрении.

Ориентировочная стоимость рассчитывается индивидуально после брифа. Получите консультацию для оценки вашего проекта — мы подготовим смету и сроки за один рабочий день.

Этап Время
Таймлайн (drag, trim, split) 4–5 дней
Предпросмотр (синхронизация видео) 3–4 дня
Загрузка ассетов (S3 presigned) 1 день
Текстовые оверлеи, изображения 2–3 дня
Remotion рендеринг + статус задачи 3–4 дня
Аудио (громкость, mute, fade) 2 дня
Эффекты и фильтры (brightness, contrast) 2–3 дня

Минимальный редактор (без эффектов и сложных фильтров): 13–17 рабочих дней. Закажите разработку под ключ — мы учтём все ваши требования.