diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 62a6ea1b5..38f58e5a6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,6 @@ Areas where help is especially valuable: - Export optimisations - Native screen recording for Linux - Wallpaper submissions -- Extensions (device frames, click effects, render hooks — see [EXTENSIONS.md](./EXTENSIONS.md)) ## How to Contribute diff --git a/EXTENSIONS.md b/EXTENSIONS.md deleted file mode 100644 index 1104e9526..000000000 --- a/EXTENSIONS.md +++ /dev/null @@ -1,310 +0,0 @@ -# Recordly Extension API - -Go to https://www.marketplace.recordly.dev/extensions for full, regularly updated documentation - -Recordly extensions run in the editor renderer and use a permission-gated host API. They can draw into the render pipeline, react to playback and export events, register cursor effects, add settings panels, and contribute packaged assets such as frames, wallpapers, and cursor styles. - -## Quick Start - -For local user-installed extensions, use `Extensions -> Open Directory` in the app. Recordly stores them in the app `userData/extensions` directory. This repo also includes installable example bundles under `extension-examples/`. - -### Minimum Extension - -```text -my-extension/ - recordly-extension.json - index.js -``` - -```json -{ - "id": "com.example.my-extension", - "name": "My Extension", - "version": "1.0.0", - "description": "A short description", - "author": "Your Name", - "license": "MIT", - "main": "index.js", - "permissions": ["render"] -} -``` - -```js -export function activate(api) { - api.log("Hello from my extension"); -} - -export function deactivate() {} -``` - -### TypeScript - -Extensions can be authored in TypeScript. Import the `RecordlyExtensionAPI` type from `types.ts` in this repo for full IDE auto-complete and compile-time checks: - -```ts -import type { RecordlyExtensionAPI } from "./types"; - -export function activate(api: RecordlyExtensionAPI) { - api.registerRenderHook("final", (ctx) => { - ctx.ctx.fillStyle = "rgba(255,255,255,0.1)"; - ctx.ctx.fillRect(0, 0, ctx.width, 30); - }); -} - -export function deactivate() {} -``` - -Recordly loads the `main` entry from the manifest, which must be a `.js` file. If you author in TypeScript, compile or bundle to JavaScript before packaging. A `tsconfig.json` with `"module": "ESNext"` and `"target": "ESNext"` works well since extensions run in a Chromium renderer. - -### Manifest Screenshots - -Extensions can include `screenshots` in the manifest to show preview images in the marketplace: - -```json -{ - "id": "com.example.my-extension", - "screenshots": [ - "screenshots/preview-1.png", - "screenshots/preview-2.png" - ] -} -``` - -Paths are relative to the extension root. The marketplace displays screenshots in a carousel on both the in-app detail modal and the web detail page. - -## Manifest - -`recordly-extension.json` is validated both when the extension loads and when a zip is uploaded to the marketplace. - -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| `id` | `string` | Yes | Unique identifier, for example `yourname.cool-effect` | -| `name` | `string` | Yes | Human-readable name shown in the UI | -| `version` | `string` | Yes | Strict semver version, for example `1.0.0` | -| `description` | `string` | Yes | One-line summary | -| `author` | `string` | No | Author or organisation | -| `homepage` | `string` | No | HTTPS homepage or repository URL | -| `license` | `string` | No | SPDX license identifier | -| `engine` | `string` | No | Minimum supported Recordly version | -| `icon` | `string` | No | Relative path to a PNG icon | -| `screenshots` | `string[]` | No | Relative paths to preview images shown in the marketplace | -| `main` | `string` | Yes | Relative entry point JS file | -| `permissions` | `string[]` | Yes | Required capabilities | -| `contributes` | `object` | No | Metadata for packaged frames, cursor styles, sounds, wallpapers, and webcam frames | - -`contributes` is metadata only today. Recordly does not auto-register runtime behavior from the manifest. Use `activate()` to call APIs such as `registerFrame()`, `registerWallpaper()`, `registerCursorStyle()`, `registerSettingsPanel()`, and `playSound()`. - -## Permissions - -| Permission | Grants access to | -|-----------|------------------| -| `render` | Render hook registration | -| `cursor` | Cursor telemetry and cursor effect registration | -| `audio` | Bundled sound playback | -| `timeline` | Playback and timeline events | -| `ui` | Settings panels and device frame registration | -| `assets` | Bundled asset resolution plus wallpaper and cursor style registration | -| `export` | Export lifecycle events | - -## Render Pipeline - -Render hooks draw into `hookCtx.ctx`, a `CanvasRenderingContext2D`, at specific phases. - -| Phase | Preview | Export | Notes | -|-------|---------|--------|-------| -| `background` | Reserved | Reserved | Exists in the type surface but is not dispatched yet | -| `post-video` | Yes | Yes | Runs inside the scene transform | -| `post-zoom` | Yes | Yes | Runs inside the scene transform | -| `post-cursor` | Yes | Yes | Runs inside the scene transform | -| `post-webcam` | Yes | Yes | Runs after the built-in transform | -| `post-annotations` | Yes | Yes | Runs after the built-in transform | -| `final` | Yes | Yes | Last pass for HUD-style overlays | - -### Inside vs Outside the Scene Transform - -- `post-video`, `post-zoom`, and `post-cursor` already follow zoom and motion in preview and export. -- `post-webcam`, `post-annotations`, and `final` run after Recordly restores the canvas transform. Use `sceneTransform` manually if you want those overlays to move with the scene. - -### RenderHookContext - -```ts -{ - width: number; - height: number; - timeMs: number; - durationMs: number; - cursor: { cx: number; cy: number; interactionType?: string } | null; - smoothedCursor?: { - cx: number; - cy: number; - trail: Array<{ cx: number; cy: number }>; - } | null; - ctx: CanvasRenderingContext2D; - videoLayout?: { - maskRect: { x: number; y: number; width: number; height: number }; - borderRadius: number; - padding: number; - }; - zoom?: { scale: number; focusX: number; focusY: number; progress: number }; - sceneTransform?: { scale: number; x: number; y: number }; - shadow?: { enabled: boolean; intensity: number }; - getPixelColor(x: number, y: number): { r: number; g: number; b: number; a: number }; - getAverageSceneColor(): { r: number; g: number; b: number; a: number }; - getEdgeAverageColor(edgeWidth?: number): { r: number; g: number; b: number; a: number }; - getDominantColors(count?: number): Array<{ r: number; g: number; b: number; frequency: number }>; -} -``` - -Use `videoLayout.maskRect` and `videoLayout.borderRadius` for scene-relative sizing. That gives you true scene borders and correctly shaped rounded corners instead of canvas-wide overlays. - -## Cursor Effects - -Cursor effect callbacks run each frame after a click until they return `false`. - -```js -api.registerCursorEffect((ctx) => { - const progress = ctx.elapsedMs / 400; - if (progress >= 1) return false; - - const sceneWidth = ctx.videoLayout?.maskRect.width ?? ctx.width; - const x = ctx.cx * ctx.width; - const y = ctx.cy * ctx.height; - const radius = sceneWidth * 0.03 * progress; - - ctx.ctx.beginPath(); - ctx.ctx.arc(x, y, radius, 0, Math.PI * 2); - ctx.ctx.stroke(); - return true; -}); -``` - -`CursorEffectContext` now includes `videoLayout`, `zoom`, and `sceneTransform`, so effects can scale relative to the scene instead of the full canvas. - -## API Surface - -### Registration - -```js -api.registerRenderHook(phase, hook); -api.registerCursorEffect(effect); -api.registerFrame(frame); -api.registerWallpaper(wallpaper); -api.registerCursorStyle(cursorStyle); -api.registerSettingsPanel(panel); -api.on(event, handler); -``` - -Every registration returns a dispose function. - -### Settings - -```js -api.getSetting(settingId); -api.setSetting(settingId, value); -api.onSettingChange((settingId, value) => {}); -api.getAllSettings(); -``` - -Supported settings field types are `toggle`, `slider`, `select`, `color`, and `text`. - -### Assets and Audio - -```js -api.resolveAsset("images/overlay.png"); -api.playSound("sounds/click.mp3", { volume: 0.8 }); -api.log("hello", payload); -``` - -### Read-only Queries - -```js -api.getVideoInfo(); -api.getVideoLayout(); -api.getCursorAt(timeMs); -api.getSmoothedCursor(); -api.getZoomState(); -api.getShadowConfig(); -api.getKeystrokesInRange(startMs, endMs); -api.getAspectRatio(); -api.getActiveFrame(); -api.isExtensionActive(extensionId); -api.getPlaybackState(); -api.getCanvasDimensions(); -api.drawIcon(ctx, "Sparkle", 100, 100, 20, "#2563EB", "regular"); -``` - -### Drawing Icons - -Extensions can draw icons from Recordly's bundled Phosphor icon set directly on a canvas context: - -```js -api.drawIcon( - ctx, - "ArrowClockwise", // icon name from @phosphor-icons/react - 120, // x (center) - 80, // y (center) - 18, // size in px - "#ffffff", // color - "bold", // optional weight: thin | light | regular | bold | fill -); -``` - -This is useful for lightweight overlays and avoids bundling your own icon assets. - -## Settings Panels - -```js -api.registerSettingsPanel({ - id: "my-settings", - label: "My Extension", - icon: "sparkles", - parentSection: "cursor", - fields: [ - { id: "enabled", label: "Enable", type: "toggle", defaultValue: true }, - { id: "size", label: "Size", type: "slider", defaultValue: 1, min: 0.1, max: 3, step: 0.1 }, - { - id: "style", - label: "Style", - type: "select", - defaultValue: "ripple", - options: [{ label: "Ripple", value: "ripple" }, { label: "Pulse", value: "pulse" }], - }, - { id: "color", label: "Color", type: "color", defaultValue: "#2563EB" }, - ], -}); -``` - -Use `parentSection` to nest your panel inside an existing area such as `cursor` or `scene`. - -## Events - -| Event | Permission | Description | -|-------|------------|-------------| -| `playback:timeupdate` | `timeline` | Fires each playback tick | -| `playback:play` | `timeline` | Playback started | -| `playback:pause` | `timeline` | Playback paused | -| `cursor:click` | `cursor` | Cursor click detected | -| `cursor:move` | `cursor` | Cursor move detected | -| `timeline:region-added` | `timeline` | Region added | -| `timeline:region-removed` | `timeline` | Region removed | -| `export:start` | `export` | Export started | -| `export:frame` | `export` | A frame was rendered during export | -| `export:complete` | `export` | Export finished | - -## Frames, Wallpapers, and Cursor Styles - -- `registerFrame()` is the runtime API for device frames. Use a `draw(ctx, width, height)` function when possible for resolution-independent output. -- `registerWallpaper()` contributes scene backgrounds. -- `registerCursorStyle()` contributes cursor image packs. -- All three rely on packaged files relative to the extension root. - -## Lifecycle - -1. Discovery: Recordly scans built-in extensions and the user extensions directory. -2. Activation: `activate(api)` runs and you register hooks, effects, panels, and assets. -3. Runtime: Registered callbacks execute in preview and export according to their phase. -4. Deactivation: `deactivate()` runs and all registrations are automatically disposed. - -## Examples - -- `extension-examples/webadderall.more-wallpapers` shows a user-installable wallpaper bundle that registers 180 packaged wallpapers through `registerWallpaper()`. diff --git a/README.md b/README.md index 121ef9343..8e84cf46d 100644 --- a/README.md +++ b/README.md @@ -63,14 +63,6 @@ Use drag-and-drop timeline tools for zooms, trims, speed regions, annotations, e timeline editor

-## Extensions & Marketplace - -Recordly has a community-driven extension system. Anyone can build and publish extensions that add new capabilities to Recordly — cursor click sounds, device frames, browser mockups, wallpapers, render hooks, settings panels, and more. - -Browse and install community extensions from the [Recordly Marketplace](https://marketplace.recordly.dev/extensions). - ---- - ## All Features ### Recording diff --git a/README.zh-CN.md b/README.zh-CN.md index b1ca9f556..b90c6f238 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -58,14 +58,6 @@ Recordly 可以根据操作自动强调重点区域,平滑光标运动,添 timeline editor

-## 扩展与市场 - -Recordly 拥有一个社区驱动的扩展系统。任何人都可以构建和发布扩展来为 Recordly 添加新功能,例如光标点击音效、设备边框、浏览器模拟外壳、壁纸、渲染钩子、设置面板等等。 - -浏览并安装社区扩展:[Recordly 扩展市场](https://marketplace.recordly.dev/extensions)。 - ---- - ## 全部功能 ### 录制