"브라우저 기술(React·Canvas·WebGL)로 만든 화면을, 데스크탑 앱 껍데기(Tauri/Rust)에 담고, 무거운 영상 처리는 네이티브 FFmpeg에 떠넘긴 오픈소스 영상 편집기"입니다. 타임라인 위에 클립을 올리고 자르고 자막을 얹어 MP4로 뽑는, CapCut·프리미어가 하는 일을 무료·로컬·오픈소스로 합니다.
Clypra는 한 대의 자동차 같습니다. 운전석·계기판(UI)은 누구나 익숙한 웹 기술(React)로 만들고, 차체(데스크탑 앱)는 가볍고 빠른 Tauri(Rust)로 찍어냅니다. 그런데 실제로 바퀴를 굴리는 엔진(영상 디코딩·인코딩)은 직접 만들지 않고, 검증된 FFmpeg을 그대로 가져다 씁니다.
덕분에 "웹 개발자도 만들 수 있는 UI"와 "전문 편집기급 영상 성능"을 한 앱에 담았습니다. 이 분업이 Clypra 코드 전체를 관통하는 설계 철학입니다.
CapCut이 유료화·계정 강제·클라우드 종속으로 사용자 불만을 키우던 시점에, Clypra는 "프리미엄 CapCut 기능을 무료로"라는 직관적 슬로건을 들고 나왔습니다. 영상 편집기는 누구나 필요를 이해하는 카테고리라, "무료 + 오픈소스 + 로컬 처리(영상이 서버로 안 올라감)"라는 조합 자체가 강한 후킹 포인트입니다.
영상 편집기는 무겁기로 악명 높습니다. Clypra는 Electron 대신 Tauri를 택해 설치 용량과 메모리를 크게 줄였고, 무거운 연산은 웹뷰가 아니라 Rust/FFmpeg에 내려보냅니다. "웹 기술로 만들되 네이티브 성능을 포기하지 않는다"는 접근이 기술 커뮤니티의 흥미를 끕니다.
알파 단계(Rust 크레이트 0.1.0-alpha.1)인데도 구조가 성숙합니다. React에 의존하지 않는 순수 엔진 계층(src/core/)을 따로 두고, 프리뷰와 익스포트가 같은 스케줄러를 공유하며, 플랫폼별 차이는 어댑터로 격리합니다. 80여 개 테스트 파일에 속성 기반 테스트(fast-check·proptest)까지 갖췄습니다.
| Clypra | CapCut | DaVinci Resolve | Shotcut/Kdenlive | |
|---|---|---|---|---|
| 가격 | 무료·MIT | 유료(프리미엄) | 무료+유료 | 무료·오픈소스 |
| 오픈소스 | 예 | 아니오 | 아니오 | 예 |
| 로컬 처리 | 전부 로컬 | 클라우드 의존 | 로컬 | 로컬 |
| 기반 기술 | Tauri+웹 | 네이티브 | C++ 네이티브 | Qt/C++ |
| 앱 용량 | 작음(수십 MB) | 큼 | 매우 큼(GB) | 중간 |
| 성숙도 | 알파(신생) | 성숙 | 매우 성숙 | 성숙 |
제품 버전은 1.0.1로 표기돼 있지만 Rust 코어는 0.1.0-alpha.1(첫 알파 2026-05-11)입니다. 다중 트랙 오디오 믹싱·영상 필터·클립 간 트랜지션·플러그인 시스템은 로드맵에 있을 뿐 아직 미완성입니다. 지금 Clypra의 가치는 "당장 프리미어를 대체"가 아니라, 웹 기술로 네이티브급 편집기를 만드는 법을 보여주는 레퍼런스 코드베이스라는 데 있습니다.
실제 합성·텍스트 이펙트 연산은 @clypra/engine(v1.5.0)이라는 비공개 npm 패키지에 들어 있고, 공개 레포는 그것을 호출·조율(orchestrate)만 합니다. 즉 "타임라인을 어떻게 엮고, 프리뷰와 익스포트를 어떻게 한 파이프라인으로 묶는가"는 공개돼 배울 수 있지만, "픽셀 단위 텍스트 래스터라이즈가 정확히 어떻게 계산되는가"는 닫혀 있습니다. 학습용으로 볼 때 이 경계를 알고 보는 게 중요합니다.
Clypra는 크게 웹뷰(React 화면) / 네이티브(Rust+FFmpeg 엔진) / 빌드·배포 3층으로 나뉩니다. "가벼운 건 위(웹)에서, 무거운 건 아래(네이티브)에서" 처리하는 분업이 일관되게 적용됩니다.
| 분류 | 기술 | 역할 |
|---|---|---|
| UI 프레임워크 | React 19.1 + TypeScript ~5.8 | 편집기 화면 전체. 최신 React 19 채택 |
| 상태관리 | Zustand 5 | 도메인별 스토어 분리(timeline/project/ui/history/settings…) |
| 드래그앤드롭 | react-dnd 16 (HTML5 backend) | 클립을 타임라인에 끌어다 놓기 |
| 스타일 | Tailwind 4.2 + shadcn + Radix UI | CSS-우선 설정, 접근성 좋은 UI 컴포넌트 |
| 아이콘/유틸 | lucide-react, clsx, cva, tailwind-merge | 아이콘·조건부 클래스 처리 |
| 폰트 | @fontsource 24종 | 자막용 번들 폰트(오프라인에서도 동작) |
| 애니메이션 템플릿 | lottie-web 5.13 | 클라우드에서 받는 애니메이션 자막/템플릿 |
| 렌더 엔진(비공개) | @clypra/engine 1.5.0 | 장면 평가·텍스트 이펙트·래스터라이즈 (소스 비공개) |
| 분류 | 기술 | 역할 |
|---|---|---|
| 앱 셸 | Tauri 2.11 | 웹뷰 호스팅 + JS↔Rust 명령(invoke) 다리 |
| 영상 디코딩 | ffmpeg-next 8 (libav 바인딩) | 썸네일·프레임을 CLI가 아닌 라이브러리로 빠르게 디코딩 |
| 영상 인코딩 | FFmpeg 사이드카(CLI) | 최종 내보내기. 앱에 동봉된 ffmpeg/ffprobe 실행 |
| 병렬 처리 | rayon 1.10, crossbeam, dashmap 6 | 썸네일 대량 디코딩을 멀티코어로 |
| 비동기 런타임 | tokio | 프로세스 파이프·채널·타이머 |
| 이미지/유틸 | image 0.25, uuid, md5, base64, walkdir | 프레임 인코딩·세션 ID·캐시 키 |
| 로컬 자막(STT) | OpenAI Whisper tiny (Python, uv 실행) | 오디오에서 자막 자동 생성(로컬, 약 39MB 모델) |
| 분류 | 기술 | 역할 |
|---|---|---|
| 번들러 | Vite 7 (@tailwindcss/vite, plugin-react) | 프론트엔드 빌드, 포트 1420 고정 |
| 테스트 | Vitest 4 + Testing Library + fast-check / proptest | 단위·속성 기반 테스트(80여 개 파일) |
| 모바일 | Capacitor 8.4 (iOS/Android) | 같은 웹 코드를 모바일 셸로 |
| 배포 | Homebrew cask · DMG · MSI · AppImage | macOS/Windows/Linux 패키지 |
| CI/CD | GitHub Actions (ci.yml, release.yml) | 빌드·테스트·릴리스 자동화 |
주방에 비유하면 — 홀(React UI)은 손님이 보는 화려한 공간이고, 주방(Rust)은 주문을 받아 처리하는 곳, 그리고 가스불·오븐(FFmpeg)은 실제 열을 내는 설비입니다. Clypra는 홀과 주방은 직접 지었지만, 화구는 검증된 제품(FFmpeg)을 사다 설치했습니다. 그래서 "요리(영상)가 빠르고 안정적"입니다.
대부분의 편집기는 "화면에 보이는 미리보기"와 "최종 출력물"을 따로 만들어, 둘이 미묘하게 다른 사고를 냅니다(WYSIWYG 붕괴). Clypra는 FrameScheduler 하나가 우선순위(realtime > export > background)만 다르게 둔 채 같은 평가→래스터화 경로를 태웁니다. 그 결과 미리보기에서 본 그대로가 내보내기 결과로 나옵니다.
전통적 편집기는 "1번 트랙, 2번 트랙…"을 먼저 쌓고 그 위에 클립을 얹습니다. Clypra의 compositor는 반대로 "시각 T 시점에 존재하는 것이 무엇인가"를 먼저 풀고, 클립은 트랙이 아니라 역할(role)을 가집니다. 유효성 검사도 편집을 막지 않고 진단만 남기는(diagnostic, non-blocking) 방식이라, 사용자가 자유롭게 편집하다가 나중에 정리할 수 있습니다.
익스포트할 때 프레임을 PNG로 디스크에 잔뜩 저장했다가 합치는 방식은 느리고 용량을 잡아먹습니다. Clypra는 각 프레임을 원시 RGBA 바이트 그대로 FFmpeg의 표준입력(stdin)에 흘려보냅니다. 디스크에 중간 파일이 생기지 않습니다.
오디오는 클립마다 atrim → asetpts → adelay → volume 필터를 만들어 amix로 합치고 AAC 128k로 인코딩합니다. 코덱은 H.264(libx264)·H.265(libx265)·ProRes(prores_ks)를 지원하며 +faststart로 웹 재생에 최적화합니다.
타임라인을 빠르게 스크럽(scrub)하려면 프레임을 순식간에 뽑아야 합니다. Clypra는 이걸 내보내기 경로와 분리해, ffmpeg-next(라이브러리 바인딩)로 하드웨어 디코더(VideoToolbox·D3D11VA·VAAPI)를 쓰고, 재인코딩 없이 원시 RGBA를 바로 WebGL2 텍스처 아틀라스에 올립니다(프레임당 3~15ms). 같은 프레임을 동시에 여러 번 요청하면 in-flight 중복 제거로 한 번만 디코딩합니다.
epoch(세대 번호)를 올려 이전 캐시를 통째로 무효화합니다. 매번 개별 이미지를 GPU에 올리는 것보다 훨씬 빠릅니다.tauri.conf.json이 Cross-Origin-Opener-Policy: same-origin + Cross-Origin-Embedder-Policy: require-corp를 설정합니다. 이렇게 "교차출처 격리(cross-origin isolation)" 상태가 되면 브라우저가 SharedArrayBuffer와 고정밀 타이머를 허용합니다. 멀티스레드·고성능 렌더링에 필요한 보안 전제 조건입니다.src/core/가 React를 전혀 import하지 않는다는 게 핵심입니다. UI(React)와 엔진(core)을 분리해 두면, 나중에 React를 다른 프레임워크로 바꾸거나 모바일/웹/데스크탑에서 같은 엔진을 재사용할 수 있습니다. "화면은 갈아끼울 수 있고, 엔진은 유지된다"는 게 이 폴더 구조가 말하는 설계 의도입니다.
Clypra는 Tauri 2의 거의 모든 핵심을 실전 예제로 보여줍니다: invoke()로 JS에서 Rust 명령 호출, Channel로 Rust에서 JS로 진행률 스트리밍, capabilities/로 권한을 파일시스템·사이드카 실행만 좁게 허용, externalBin으로 FFmpeg을 동봉. "웹 개발 경험을 데스크탑 앱으로 확장하는" 가장 현실적인 교본입니다.
OffscreenCanvas로 백그라운드 스레드에서 합성하고, WebGL2 텍스처 아틀라스로 필름스트립을 한 번에 그리고, <video> 요소 풀(VideoElementPool)을 재사용하는 등, 브라우저에서 영상을 고성능으로 다루는 기법이 총집합돼 있습니다. 프런트엔드 개발자가 "캔버스/GPU"의 세계로 넘어갈 때 보기 좋은 코드입니다.
편집기는 상태가 폭발하는 앱입니다. Clypra는 하나의 거대 스토어 대신 timelineStore·projectStore·historyStore 등으로 책임을 나누고, autoSaveMiddleware로 자동 저장을 미들웨어 한 곳에 모았습니다. 대형 상태를 어떻게 분할·정복하는가의 실전 사례입니다.
core/history/는 Move/Trim/Split/Delete/Transform 같은 편집 동작을 각각 실행/되돌리기를 아는 명령 객체로 만들고 저널(journal)에 쌓아 100단계 undo/redo를 구현합니다. 디자인 패턴 교과서의 Command 패턴이 실제로 어떻게 쓰이는지 볼 수 있습니다.
같은 FFmpeg을 용도에 따라 다르게 씁니다: 빠른 응답이 필요한 썸네일은 ffmpeg-next 라이브러리 바인딩으로, 안정성과 코덱 호환이 중요한 최종 출력은 ffmpeg CLI 프로세스로. "도구를 언제 라이브러리로, 언제 외부 프로세스로 쓰는가"에 대한 좋은 판단 사례입니다.
platform/adapters/에 tauri·capacitor·web 어댑터를 두고 런타임에 환경을 감지(__TAURI_INTERNALS__·window.Capacitor)해 갈아끼웁니다. 같은 코드로 데스크탑·모바일·웹을 지원하는 추상화 설계를 배울 수 있습니다.
| 항목 | 내용 |
|---|---|
| 지원 OS | macOS · Windows · Linux (데스크탑) + iOS · Android (Capacitor) |
| 설치(사용자) | macOS: brew install AIEraDev/tap/clypra 또는 DMG · Windows: MSI · Linux: AppImage |
| FFmpeg | macOS·Linux·Windows 모두 사이드카 스텁 구조이며, 배포용 릴리스에서는 각 트리플별 정적 빌드로 교체 필요. 개발 모드(npm run tauri dev)에서는 PATH의 시스템 FFmpeg 사용 |
| GPU | WebGL2 지원 필요(미리보기·필름스트립 가속). 하드웨어 디코더(VideoToolbox·D3D11VA·VAAPI) 있으면 더 빠름 |
| 빌드(개발자) | Node.js 18+ · Rust/Cargo · FFmpeg → npm install → npm run tauri dev |
| 클라우드 기능 키 | VITE_CLYPRA_API_KEY(.env) — 텍스트 이펙트·템플릿·Lottie 사용 시 |
| 로컬 자막 | Whisper tiny 모델(약 39MB) + uv(Python 실행기) |
본인 OS에 맞게 설치한 뒤 영상·이미지·음악을 임포트해 타임라인에 올리고, 자막 한 줄을 얹어 1080p MP4로 내보내 보세요. 내보내는 동안 진행률 표시(fps·ETA)가 어떻게 갱신되는지 관찰합니다 — 그게 Rust Channel에서 오는 신호입니다.
레포를 클론해 npm install → npm run tauri dev로 직접 실행해 보세요. Rust가 처음 컴파일될 때 시간이 꽤 걸립니다. 콘솔에서 Rust 로그와 웹뷰 로그가 어떻게 같이 뜨는지(clearScreen:false 설정 덕분) 확인합니다.
src-tauri/src/commands/에 get_app_version 같은 간단한 Rust 명령을 만들어 lib.rs의 invoke_handler에 등록하고, React에서 invoke("get_app_version")로 호출해 화면에 표시해 보세요. JS↔Rust 왕복의 최소 단위를 손에 익힙니다.
익스포트 프리셋(1080p-fast, 4k-quality 등)이 정의된 곳을 찾아 "720p-경량(낮은 비트레이트)" 프리셋을 추가해 보세요. -crf·-preset·해상도 값이 결과 파일 용량/화질에 어떻게 작용하는지 실험합니다.
Clypra의 골격 — Tauri 셸 + Canvas 합성 + FrameScheduler + RGBA→FFmpeg stdin 스트리밍 — 을 본떠, "이미지 N장을 슬라이드쇼 영상으로 내보내는" 최소 앱을 만들어 보세요. 프리뷰와 익스포트가 같은 렌더 함수를 쓰도록 설계하는 것까지가 목표입니다.
| 주차 | 주제 | 할 일 |
|---|---|---|
| 1주차 | Tauri 2 기초 | 공식 튜토리얼로 빈 앱 만들기. invoke·Channel·capabilities(권한) 개념 익히기. 과제 1·2·3 수행 |
| 2주차 | 브라우저 그래픽스 | Canvas2D → OffscreenCanvas → WebGL2 순서로 학습. 이미지 합성·텍스처 아틀라스 개념 정리. Clypra core/render/ 읽기 |
| 3주차 | FFmpeg 파이프라인 | FFmpeg CLI로 rawvideo→mp4 인코딩, filter_complex 오디오 믹싱 직접 실습. 코덱(libx264/265·ProRes)·CRF·preset 이해 |
| 4주차 | 아키텍처 종합 | core(엔진)/UI 분리, 어댑터 패턴, Command 패턴 undo/redo 정리. 과제 4·5로 미니 편집기 완성 |
| 용어 | 뜻 |
|---|---|
| Tauri | 웹 기술로 만든 화면을 Rust로 데스크탑 앱화하는 프레임워크. Electron보다 가볍다(OS 웹뷰 재사용) |
| invoke | 웹뷰의 JS에서 Rust 백엔드 명령을 호출하는 Tauri API. Clypra는 34개 명령을 등록 |
| Channel | Rust → JS 방향으로 데이터를 흘려보내는 통로. 내보내기 진행률·fps·ETA 전송에 사용 |
| 사이드카(Sidecar) | 앱에 동봉되어 함께 배포·실행되는 외부 실행파일. Clypra는 ffmpeg·ffprobe를 사이드카로 동봉 |
| NLE | 비선형 편집기. 타임라인 어디든 자유롭게 잘라 붙이는 편집 방식(프리미어·CapCut) |
| 래스터라이즈 | 추상적 장면 기술을 실제 픽셀(비트맵)로 그려내는 과정 |
| OffscreenCanvas | 화면에 붙지 않은 캔버스. 백그라운드 스레드(Worker)에서 합성 연산을 돌릴 수 있음 |
| 텍스처 아틀라스 | 여러 작은 이미지를 한 큰 GPU 텍스처에 모아 한 번에 그리는 최적화 기법 |
| WebCodecs | 브라우저에서 영상 코덱(디코드/인코드)에 저수준 접근하는 웹 API |
| COOP/COEP | 교차출처 격리 헤더. SharedArrayBuffer·고정밀 타이머를 켜는 보안 전제 조건 |
| ffmpeg-next | FFmpeg의 libav를 Rust에서 직접 호출하는 라이브러리 바인딩. CLI보다 빠른 디코딩에 사용 |
| rayon | Rust의 데이터 병렬 처리 라이브러리. 썸네일 대량 디코딩을 멀티코어로 |
| Capacitor | 같은 웹 코드를 iOS·Android 네이티브 앱으로 감싸는 프레임워크 |
| Zustand | 가볍고 간결한 React 상태관리 라이브러리. Clypra는 도메인별 스토어로 분리 |
| Command 패턴 | 동작을 "실행/되돌리기를 아는 객체"로 캡슐화. undo/redo 구현의 정석 |
| Whisper tiny | OpenAI의 경량 음성인식 모델(약 39MB). 로컬에서 오디오→자막 생성에 사용 |
| 링크 | 설명 |
|---|---|
| GitHub 저장소 | 소스 전체. src/core/와 src-tauri/src/commands/export.rs가 핵심 읽을거리 |
| TrendShift 페이지 | 트렌딩 추이 |
| Tauri 2 공식 문서 | invoke·Channel·capabilities·사이드카 표준 |
| FFmpeg 공식 문서 | rawvideo 입력·filter_complex·코덱 옵션 |
| WebCodecs API (MDN) | 브라우저 영상 코덱 저수준 처리 |
| Zustand | React 상태관리 라이브러리 |
| Capacitor 공식 문서 | 웹 코드의 모바일 패키징 |