OpenCut
OpenCut (надмозг. ОткрытыйПорез, Вскрытие, РазомкнутаяРана) — тысяча первый по счету убийца Premier Pro, Sony Vegas и, в особенности, китайского шпионского софта CapCut. Представляет собой попытку группы энтузиастов-альтруистов (или безумцев) написать полноценный нелинейный видеоредактор на православном TypeScript, который работает прямо в твоем хромом браузере.
Позиционируется как privacy-first (твои нюдсы не улетают на сервера товарища Си, если ты сам не накосячишь), бесплатный и с открытым исходным кодом. На деле же — это живой памятник тому, что бывает, когда веб-разработчики решают, что C++ и CUDA — это для старперов, а рендерить 4K-видео можно и через canvas, попутно сжигая оперативную память юзера во славу движка V8.
Суть[править]
В один прекрасный день китайские overlords из ByteDance решили, что хватит раздавать халяву, и начали анально огораживать функции CapCut платными подписками. Народ, привыкший клепать тиктоки и шортсы одной левой пяткой, возмутился. На этой волне хайпа и родился OpenCut.
Идея проста как три копейки: Давайте сделаем свой CapCut, с блэкджеком и открытым кодом!. Чтобы любой школьник мог скачать репозиторий, собрать билдец и монтировать свои летсплеи по Майнкрафту, не платя ни цента.
На практике это вылилось в монструозный проект на стеке React + Next.js, который пытается эмулировать работу десктопного софта в среде, предназначенной для показа котиков и отправки JSON-ов. Это как пытаться построить звездолёт из LEGO: теоретически возможно, но развалится при первом же входе в атмосферу.
Технологии[править]
Если заглянуть под капот, то можно увидеть типичный Modern Web Dev Starter Pack, от которого у любого сишника случится припадок, а у джависта — нервный тик.
- Язык: TypeScript. Потому что писать видеоредактор на чистом JS — это уже совсем БДСМ, а типы хоть как-то спасают от выстрела в ногу (но не в голову). Вездесущие
anyстыдливо прикрытыas unknown as T. - Фреймворк: Next.js. Да, Карл! Видеоредактор на фреймворке для SSR и статики. Зачем? Во славу Веб-стандартов, конечно! Видимо, чтобы SEO у твоего локального проекта было на высоте.
- Стейт-менеджмент: Zustand. Потому что Redux — это сложно и больно, а Context API тормозит. Zustand позволяет хранить состояние всего этого хаоса в глобальной помойке, доступной из любого хука, превращая отладку в увлекательный квест кто изменил эту переменную?.
- Рендеринг:
OffscreenCanvasи Web Codecs API (через прокладку в видеmediabunny). Да, видео рисуется на канвасе, кадр за кадром, с помощью JS. FPS при этом зависит от фазы луны, температуры на Марсе и количества открытых вкладок с порн… познавательным контентом. - Хранилище: IndexedDB и OPFS (Origin Private File System). Твои гигабайты футажей хранятся локально в браузере. Очистил кэш — потерял проект. Удобно, надежно, практично! Резервные копии? Не слышали.
Структура папок[править]
Внутри проекта царит классический хаос монорепы, управляемой Turborepo (потому что простого package.json нынче мало):
apps/web/ — Собственно, сама веб-морда, где происходит вся магия (и баги). packages/ui/ — Кнопочки, свистелки и перделки на Shadcn/UI. Копипаста компонентов, возведенная в абсолют. packages/env/ — Валидация переменных окружения через Zod, чтобы приложение падало сразу, а не потом. src/core/ — Попытка сделать вид, что у нас тут серьезная архитектура с менеджерами и синглтонами. src/hooks/ — Кладбище React-хуков, каждый из которых вызывает ререндер всего и вся при движении мыши.
Вскрытие поциента[править]
Разберем, как это чудо инженерной мысли пытается работать, на основе предоставленных исходников. Слабонервным и адептам чистого кода просьба отойти от экранов.
Менеджеры всего и вся[править]
Разработчики решили, что ООП — это не зашквар, и запилили класс EditorCore (синглтон, разумеется, ведь какой же говнокод без синглтона?), который держит в себе кучу менеджеров. Это напоминает попытку управлять атомной электростанцией с помощью пульта от телевизора.
- TimelineManager: Царь и бог монтажного стола. Отвечает за то, чтобы клипы не наезжали друг на друга (спойлер: наезжают), треки добавлялись, а юзер не плакал кровавыми слезами при попытке сделать split. Использует паттерн Команда (Command), чтобы можно было делать Ctrl+Z. Да, они реально реализовали стек
undo/redoвручную, вместо того чтобы взять готовую библиотеку. - PlaybackManager: Пытается синхронизировать
requestAnimationFrameс реальным временем. Получается с переменным успехом, ибо JS — однопоточный, и если сборщик мусора (Garbage Collector) решит проснуться, твое видео дернется, как припадочное. - MediaManager: Заведует ассетами. Загружает файлы в браузер, генерирует им UUID (потому что имена файлов — это для слабаков) и пихает в IndexedDB. Если файл большой — браузер говорит кря и падает.
- ScenesManager: Да, тут есть сцены! Можно делать вложенные таймлайны (наверное). В коде есть
isMainфлаг, намекающий, что есть главная сцена и побочные. Видимо, задел на будущее, когда редактор перестанет падать от одного видео.
The open-source CapCut alternative
Таймлайн[править]
Самая мякотка — это реализация таймлайна. Файл components/editor/timeline/index.tsx — это место, где надежды разбиваются о DOM-дерево.
- Виртуализация? Вроде есть, используется скроллинг и зуммирование. Но когда элементов становится больше 50, React начинает молить о пощаде.
- Снэппинг (прилипание): Реализован через
useTimelineSnapping. Пытается найти ближайшую точку (начало клипа, конец клипа, курсор) и примагнитить к ней перетаскиваемый элемент. Работает на магииMath.abs(target - current) < threshold. Иногда примагничивает не туда, иногда вообще не магнитит. - Зум: Экспоненциальный! Функция
zoomToSliderиsliderToZoomиспользует логарифмы. Математика в JS — это отдельный вид искусства, особенно когда дело доходит до плавающей точки. - Рендеринг дорожек: Всё на дивах (
div). Тысячи дивов. Каждый клип — див. Каждая ручка ресайза — див. Браузер пыхтит, греет комнату, но рендерит. DOM-дерево растет быстрее, чем долг США.
Рендеринг видео: Canvas API[править]
Как же оно экспортирует видео? А вот так:
- Берется корневая нода (
RootNode). - Пробегается по дереву сцены.
- Каждый кадр отрисовывается на
OffscreenCanvas. - Результат скармливается
mediabunny(обертка над ffmpeg.wasm или WebCodecs). - ????
- PROFIT (или краш вкладки из-за OOM — Out Of Memory).
В файле services/renderer/scene-builder.ts видно, как строится граф рендера:
if (background.type === "blur") {
rootNode.add(
new BlurBackgroundNode({
blurIntensity: background.blurIntensity ?? DEFAULT_BLUR_INTENSITY,
contentNodes,
}),
);
}
Блюр фона реализован программно. На JS. Для каждого кадра. Вы слышите этот звук? Это кулер вашего ноутбука пытается улететь в стратосферу, спасаясь от перегрева.
Аудио: Web Audio API[править]
Аудио движок (audio-manager.ts) — это отдельная песня. Они создают AudioContext, подключают узлы (nodes), микшируют каналы… В браузере.
Особенно доставляет функция scheduleUpcomingClips. Она пытается предугадать, какие клипы скоро заиграют, и подгрузить их. Если вкладка в фоне — таймеры браузера замедляются, и звук превращается в дабстеп-ремикс или замедленное демоническое мычание.
Где мой проект, Лебовски?[править]
Используется IndexedDBAdapter и OPFSAdapter.
- OPFS (Origin Private File System) — это круто и быстро, но попробуй достать оттуда файл, если сайт лег или скрипт завис. Это черная дыра: файлы входят, но не всегда выходят.
- Миграции: О да, они написали свою систему миграций (
v0-to-v1,v1-to-v2…). Потому что структура JSON-а проекта меняется чаще, чем настроение у биполярника. В коде есть проверки типаif (project.version >= 3). Это значит, что если ты обновил страницу, а разраб выкатил новый коммит — поздравляю, твой проект теперь Legacy, и запускается процедура конвертации, которая может (и будет) падать, оставляя тебя с битым JSON-ом.
Лузлы кодовой базы[править]
Читая исходники, можно найти немало забавного:
- TODO-driven development: Комментарии в духе Coming soon разбросаны повсюду. Например, в
ExportButtonесть заглушки для форматов, но работает только mp4 и webm. Эффекты? Coming soon. Переходы? Coming soon. Стабильность? Coming soon. - Zod-паранойя: Валидация всего, что движется. API роуты (
api/sounds/search/route.ts) обернуты в Zod-схемы такой толщины, что ими можно убить. Безопасность — это хорошо, но когда валидатор весит больше логики… - Бесконечные хуки:
useEditor,useTimelineZoom,useElementInteraction,useTimelineSnapping… Чтобы понять, откуда пришло событие клика, нужно пройти квест из 10 файлов, 5 контекстов и 3 сторов Zustand. - Копипаста: Некоторые куски кода выглядят так, будто их писали Copilot-ом и забыли поправить. Особенно в UI-компонентах.
- Борьба с типами:
as unknown as TScene[]— классика жанра. Когда TypeScript говорит нет, разработчик говорит as any и стреляет себе в ногу.
Разработчики[править]
Судя по списку контрибьюторов:
- mazeincoding — Главный архитектор хаоса. 733 коммита. Человек-оркестр, который, видимо, не спит и питается чистым кофеином.
- izadoesdev — Второй пилот. Строит аналитику (Databuddy) и, видимо, бэкенд, чтобы знать, на каком моменте у юзера сгорел стул.
- И еще 90+ человек, которые зашли поправить опечатку в README ради футболки на Hacktoberfest или строчки в резюме.
Фичи[править]
| Заявлено | Реальность |
|---|---|
| Multi-track support | Можно накидать видео друг на друга, и оно даже, может быть, не зависнет сразу. Но слоев больше трех — и твой браузер превращается в тыкву. |
| No watermarks | Действительно нет. Но есть невидимый вотермарк в виде твоих нервных клеток, потраченных на ожидание экспорта. |
| Privacy First | Все рендерится у тебя. Если у тебя слабый комп — это твоя приватная проблема. Никто не увидит твои видео, потому что они не срендерились. |
| AI Features | Авто-субтитры (Whisper), работающие через WebWorker. Скачивают модель весом в сотни мегабайт прямо в кэш браузера. Привет, мобильный трафик! |
| Stickers | Интеграция с Iconify. Можно лепить эмодзи поверх видео. Вершина эволюции видеомонтажа. |
Установка и запуск[править]
Если ты мазохист и хочешь это запустить локально:
- Установи Docker (чтобы поднять базу данных Postgres, ведь видеоредактору без базы никак. Зачем хранить настройки в localStorage, если можно поднять целый SQL-сервер?).
- Установи
bun(потому что npm — для дедов, а yarn — для хипстеров. Мы используем хайповый рантайм). - Клонируй репу.
bun install(скачай половину интернета).bun dev.- Смотри, как твой ноутбук превращается в обогреватель, пытаясь скомпилировать сотни TS-файлов.
См. также[править]
Ссылки[править]
- opencut.app — Официальный сайт
- github.com/OpenCut-app/OpenCut — Репозиторий на GitHub