OpenCut

Материал из Неолурк, народный Lurkmore
Перейти к навигации Перейти к поиску

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
— README.md

Таймлайн[править]

Самая мякотка — это реализация таймлайна. Файл components/editor/timeline/index.tsx — это место, где надежды разбиваются о DOM-дерево.

  • Виртуализация? Вроде есть, используется скроллинг и зуммирование. Но когда элементов становится больше 50, React начинает молить о пощаде.
  • Снэппинг (прилипание): Реализован через useTimelineSnapping. Пытается найти ближайшую точку (начало клипа, конец клипа, курсор) и примагнитить к ней перетаскиваемый элемент. Работает на магии Math.abs(target - current) < threshold. Иногда примагничивает не туда, иногда вообще не магнитит.
  • Зум: Экспоненциальный! Функция zoomToSlider и sliderToZoom использует логарифмы. Математика в JS — это отдельный вид искусства, особенно когда дело доходит до плавающей точки.
  • Рендеринг дорожек: Всё на дивах (div). Тысячи дивов. Каждый клип — див. Каждая ручка ресайза — див. Браузер пыхтит, греет комнату, но рендерит. DOM-дерево растет быстрее, чем долг США.

Рендеринг видео: Canvas API[править]

Как же оно экспортирует видео? А вот так:

  1. Берется корневая нода (RootNode).
  2. Пробегается по дереву сцены.
  3. Каждый кадр отрисовывается на OffscreenCanvas.
  4. Результат скармливается mediabunny (обертка над ffmpeg.wasm или WebCodecs).
  5. ????
  6. 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. Можно лепить эмодзи поверх видео. Вершина эволюции видеомонтажа.

Установка и запуск[править]

Если ты мазохист и хочешь это запустить локально:

  1. Установи Docker (чтобы поднять базу данных Postgres, ведь видеоредактору без базы никак. Зачем хранить настройки в localStorage, если можно поднять целый SQL-сервер?).
  2. Установи bun (потому что npm — для дедов, а yarn — для хипстеров. Мы используем хайповый рантайм).
  3. Клонируй репу.
  4. bun install (скачай половину интернета).
  5. bun dev.
  6. Смотри, как твой ноутбук превращается в обогреватель, пытаясь скомпилировать сотни TS-файлов.

См. также[править]

Ссылки[править]

  • opencut.app — Официальный сайт
  • github.com/OpenCut-app/OpenCut — Репозиторий на GitHub
App.png Весьма полезная вещь, позволяет машинам работать с помощью коммандычей
МетаПрограммаDRM (SecuROMStarForceАналоговая дыра) • БагБот (Автоответчик) • Варез (Repack) • ГлюкГуйДонатКопирайт (By design) • ЛогНюкРут (Не работай под рутом) • Спортивное программированиеМегапиксельКомпьютерВерсия 2.0КодОбфускацияСкриншотДатамайнПлагинТекстовый файлБольшие данныеАльфа и бета-тестыТаймстампКэшШаблоныHello WorldНейросетиФайлИнсталляцияВидеоМощный сбой Microsoft 19 июля 2024 годаCrowdStrikeПроект GNUUserscriptDxvkVkd3dБратан хорош давай давай впередКонечный автоматLumenЗаступник (приложение)NeeUnreal MCPОптимизацияДрайверТестированиеТройная буферизацияQBitTorrentСинтезаторОбрыв загрузки файла на 99%Polycount.comГрок написал программу о себеВредоносTamTamАппликацио
ФичиБагрепорт12309BSODCookiesEmbrace, extend and extinguishFL StudioSheep.exeWinlogon.exeБубенЗащита от дуракаКостыльМашинный переводПасхальное яйцоСвистелки и перделкиСм. рис. 1Съешь ещё этих мягких французских булокTermuxGNU MetroИндусский кодНескучные обои • Сжатие (За сжатие ДжипегаШакалШкала) • Работает — не трогайРандомайзерPDF (Распознавание PDF) • Дело Google в ФАСЧат-ботXMLМакросКритическая ошибкаФреймворкСинонимайзерSourceТрёхмерное отслеживаниеТрассировка фотоновHZB OcclusionДаунгрейд RTX 4070TressFXАвтопереводчикVSCodiumThorium BrowserShovelwareФайл подкачкиTea Dating AdviceSingle-Page ApplicationАптаймSafenSoft SysWatchМолния (мессенджер)C SharpОбновлениеOneDriveChatGPT AtlasVoice Over Translation
ВредоносноеБотнетБрутфорсВинлокЗвонилкаКитайские пингвиныПиксель смертиТроянЧервь МоррисаBonziBuddyMediaGetBrowser hijackingTinderМиссис МажорУтечка буфера обменаWin 10 TweakerОпараш Mozilla FirefoxЯндекс.МузыкаКрэкерБезопасность через умолчаниеGrifter.aviTrojan.Winlock.DeathМиссис МажорСредаDirectStorageDriverpackГенератор случайных чиселDisable Core 0РомхакингDDrawCompatWingetCreateWinGetCoowonЯндекс МессенджерVCPkgSELinuxXfireYouTube Auto-ResumeTape OperatorBotFatherMTProtoSignalDoubleClickFixGiteeБотофермаMalwareCeno BrowserLagoFastYouareanidiot
КомпанииApple / Apple (AppleScript) • GoogleMicrosoftSAPЯндексExiled Exchange 2BraveAdNauseamСкурвление FirefoxCafe BazaarAMD FEMFXPPSSPPАвтохукQuick machine recoveryПутинский мессенджер MAXBypassNROWizTreeJTubeGallium NineFalconRu-WireGuardМобильное приложениеWebRenderСмс-бомберInstaller-SHProton GEProcess LassoParkControlDolby AccessDevToolsDxWrapperБойкот мессенджера MaxFirejailLenzaБезопасность мессенджера MAXЦифровое гетто ГабенаQuasarRATGame MakerБрайан ЛандукСтарые форматы видеофайловMAX в школахdom.storage.default_quotaVirtualBoxArdourFlutter
ЛюдиВеб-мастерLovinGODБалмерГейтсГенерал ФейлорДжобсМитникПоттерингде РаадтСпольскиСтоллманТорвальдсШахиджанянAche666Марк ЦукербергЕвгений ПоповДенис КумпонМассовая компьютерная безграмотностьKomet ClientРеверс-инжинирингКроссплатформенностьDKMSАмигоAURWhiteMAXHyPrismСферумJiraTampermonkeyTauriSoroush Plus
Команды^H^WAlt+F4Ctrl+Alt+Delman/me/quitrm -rfRubikaГовнософтШпионское ПОАрхиваторДемон (программа)ClickHouseImo.imСкрытые функции мессенджера МаксBuildin.AI