Skip to content

Getting Started with Plugins

Lyric Video Maker supports external plugins that add scene components and scene presets. Plugins are CommonJS modules loaded at runtime by the desktop app.

Prerequisites

  • Node.js 18+
  • A code editor (VS Code recommended)
  • Basic TypeScript and React knowledge

Quick Start

bash
mkdir my-plugin && cd my-plugin
npm init -y
npm install --save-dev @lyric-video-maker/plugin-base react tsup typescript

Create src/plugin.ts:

typescript
import type {
  LyricVideoPluginActivation,
  LyricVideoPluginHost,
  SceneComponentDefinition,
} from "@lyric-video-maker/plugin-base";

interface MyOptions extends Record<string, unknown> {
  textColor: string;
}

export function activate(
  host: LyricVideoPluginHost
): LyricVideoPluginActivation {
  const { React } = host;

  const component: SceneComponentDefinition<MyOptions> = {
    id: "myplugin.hello",
    name: "Hello World",
    options: [
      {
        id: "textColor",
        label: "Text Color",
        type: "color",
        defaultValue: "#ffffff",
      },
    ],
    defaultOptions: {
      textColor: "#ffffff",
    },
    Component({ options, containerRef }) {
      return React.createElement(
        "div",
        {
          ref: containerRef,
          style: {
            width: "100%",
            height: "100%",
            display: "grid",
            placeItems: "center",
            color: options.textColor,
            fontSize: 48,
            fontFamily: "sans-serif",
          },
        },
        "Hello from my plugin!"
      );
    },
  };

  return { components: [component], scenes: [] };
}

Users position, time, and fade this component by adding the built-in Transform, Timing, and Opacity modifiers in the Component Editor — the plugin itself only concerns itself with its own visuals.

Create lyric-video-plugin.json at the project root:

json
{
  "schemaVersion": 1,
  "id": "myplugin.hello-pack",
  "name": "Hello Pack",
  "version": "0.1.0",
  "entry": "dist/plugin.cjs",
  "components": ["myplugin.hello"],
  "scenes": []
}

Build and commit the output:

bash
npx tsup src/plugin.ts --format cjs --out-dir dist --out-extension .cjs
git add dist/plugin.cjs

Project Structure

my-plugin/
  lyric-video-plugin.json   # Manifest (required at repo root)
  package.json
  tsconfig.json
  tsup.config.ts            # Or any bundler that outputs CJS
  src/
    plugin.ts               # Entry point exporting activate()
  dist/
    plugin.cjs              # Prebuilt bundle (committed to repo)
json
{
  "name": "my-lyric-video-plugin",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "scripts": {
    "build": "tsup",
    "typecheck": "tsc --noEmit"
  },
  "devDependencies": {
    "@lyric-video-maker/plugin-base": "^0.1.0",
    "react": "^18.3.1",
    "tsup": "^8.4.0",
    "typescript": "^5.8.2"
  }
}
json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "strict": true,
    "jsx": "react-jsx",
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true
  },
  "include": ["src/**/*.ts"]
}
typescript
import { defineConfig } from "tsup";

export default defineConfig({
  entry: ["src/plugin.ts"],
  format: ["cjs"],
  outDir: "dist",
  clean: true,
  dts: false,
  // React and plugin-base are provided by the host at load time. Bundling
  // them would produce duplicate React instances (invalid-hook-call) and
  // drag Node-only globals like `process.env.NODE_ENV` into the browser
  // eval context. Keep them external.
  external: ["react", "react-dom", "@lyric-video-maker/plugin-base"],
  outExtension() {
    return { js: ".cjs" };
  },
});

Distribution

Plugins are imported into the app via GitHub URL or local path.

Via GitHub

Push your repo (with dist/plugin.cjs committed) to GitHub. Users import via the HTTPS clone URL:

https://github.com/yourname/my-lyric-video-plugin.git

The app clones the repo, reads the manifest, and loads the plugin.

Via Local Path

For development, users can import from a local directory path.

What to Commit

Always commit dist/plugin.cjs to the repository. The app does not run npm install or any build commands on import.

Listing Your Plugin

Want your plugin discoverable? Open a PR adding it to the Known Plugins table on the Plugins doc page.

Bundled Assets

Plugins can include asset files (images, videos) and reference them in scene definitions. Place files anywhere in your repo and use createPluginAssetUri() to build references:

typescript
import { createPluginAssetUri } from "@lyric-video-maker/plugin-base";

const myScene = {
  id: "myplugin.showcase",
  name: "My Showcase",
  source: "plugin",
  readOnly: true,
  components: [
    {
      id: "bg",
      componentId: "image",
      enabled: true,
      options: {
        source: createPluginAssetUri("myplugin.hello-pack", "assets/bg.jpg"),
      },
    },
  ],
};

Asset files should be committed to the repo alongside dist/plugin.cjs. Users can override bundled assets by picking a different file in the editor. See the Plugin API Reference for full details.

Next Steps

  • Read the full Plugin API Reference for details on all component interfaces, the options schema, the modifier system, audio analysis, and more.
  • The Modifier System section covers how to contribute your own modifiers (shakes, glitches, custom color grades, etc.) alongside the built-in Transform, Timing, Opacity, and Visibility modifiers.
  • Check out the example plugin for a complete working reference.

Released under the MIT License.