Skip to content

Getting Started

This guide walks you through setting up a plugin development environment and building a minimal working plugin.

Prerequisites

  • Node.js ≥ 18 and npm ≥ 9
  • A text editor or IDE with TypeScript support (VS Code recommended)
  • Basic familiarity with TypeScript

Verify your Node.js version:

bash
node --version   # should print v18.x.x or higher
npm --version

Create the Project

Create a new directory and initialize it:

bash
mkdir mediavault-plugin
cd mediavault-plugin
npm init -y

Install Dependencies

The plugin core is distributed as a .tgz archive on GitHub Releases. Add it to your package.json dependencies:

json
{
  "dependencies": {
    "@xeinebiu/anplayer-plugin-core": "https://github.com/xeinebiu/android_anplayer_plugin/releases/download/2.17.0/xeinebiu-anplayer-plugin-core-2.17.0.tgz"
  },
  "devDependencies": {
    "typescript": "~5.7.3",
    "@vercel/ncc": "^0.38.3"
  }
}

Then install:

bash
npm install

Configure TypeScript

Create tsconfig.json:

json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["ES2020"],
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "./dist"
  },
  "include": ["src/**/*"]
}

Project Structure

mediavault-plugin/
├── src/
│   └── main.ts        ← your plugin entry point
├── package.json
└── tsconfig.json

Create the src directory:

bash
mkdir src

Write a Minimal Plugin

Create src/main.ts with a plugin that always returns a single hardcoded media item. This lets you verify your build and install pipeline before connecting to a real API.

typescript
import {
  AnPlayerExtractor,
  createMedia,
  createDirectStream,
} from '@xeinebiu/anplayer-plugin-core';

const MyPlugin: AnPlayerExtractor = ({ config, logger }) => {
  // Config is a string passed by AN Player. The format is up to you.
  return {
    /**
     * Determines if this plugin can handle the given URI.
     */
    async isSupported(uri) {
      return uri.hostname === 'mediavault.local';
    },

    /**
     * Identifies if the URI points to a browsable container (album/folder).
     */
    async isAlbum(_uri) {
      return false;
    },

    /**
     * Identifies if the URI points to a playable media item.
     */
    async isMediaTrack(uri) {
      return uri.pathname === '/media';
    },

    /**
     * Returns an extractor for the home feed/discovery screen.
     */
    async getFeedExtractor() {
      return {
        // next() should return an array of items for the next page.
        // Return an empty array to signal the end of the list.
        next: async () => [
          createMedia({
            id: 'test-video',
            title: 'Test Video',
            uri: 'https://mediavault.local/media?id=test-video',
          }),
        ],
      };
    },

    /**
     * Returns an extractor for a specific media item.
     */
    async getMediaExtractor(_uri) {
      return {
        getStream: async () =>
          createDirectStream({
            uri: 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
          }),
      };
    },
  };
};

export default MyPlugin;

INFO

createMedia, createAlbum, createDirectStream and other factory helpers are exported from the plugin core. They handle filling in default values so you only supply what you have.

The config and logger arguments passed to your plugin function allow you to handle user configuration and log messages to the AN Player console.

IMPORTANT

Ensure you use export default MyPlugin;. AN Player will not be able to load your plugin if the factory function is not the default export.

Build

Bundle your plugin into a single JavaScript file with ncc:

bash
npx ncc build ./src/main.ts -m -o ./dist/
  • -m: minify output
  • -o ./dist/: output directory

After a successful build you will have dist/index.js, the file you embed in your plugin manifest.

Add a Build Script

Add a build script to package.json for convenience:

json
{
  "scripts": {
    "build": "ncc build ./src/main.ts -m -o ./dist/"
  }
}

Then build with:

bash
npm run build

Next Steps

With a working build pipeline in place, move on to: