npm package: @renweilong/electron-ffmpeg-player
Description: A TypeScript React video player component for Electron projects using FFmpeg decoding and Canvas rendering.
Latest version: 0.1.4

# @renweilong/electron-ffmpeg-player

A TypeScript React video player component for Electron projects using FFmpeg decoding and Canvas rendering. This player is designed for high-performance, frame-accurate video playback up to 60fps, making it ideal for desktop applications that require precise video control.

## Features

- **Frame-Accurate Playback**: Utilizes FFmpeg/WASM for decoding and HTML5 Canvas for rendering, ensuring precise frame control.
- **60FPS Support**: Optimized pipeline for smooth 60fps video playback.
- **Interactive Timeline**: Supports highlight markers on the timeline with hover tooltips and seek-to-click.
- **Thumbnail Rail**: Optional clip-style thumbnail rail with real frame slices, hover preview, and click-to-seek.
- **Source Switching With Initial Seek**: Supports setting an initial position when switching sources so the player seeks before showing or autoplaying.
- **Standard Controls**: Play, pause, fast forward, rewind, volume control, and playback rate.
- **Built-in Speed Control**: Includes a speed selector in the control bar, with support for external rate synchronization.
- **Keyframe Stepping**: Navigate precisely between keyframes (Next / Prev I-frame).
- **Theming**: Built-in support for `light` and `dark` themes.
- **Customizable**: Exposes a comprehensive ref handle (`VideoCanvasPlayerHandle`) to control playback programmatically.

## Installation

```bash
npm install @renweilong/electron-ffmpeg-player
# or
yarn add @renweilong/electron-ffmpeg-player
# or
pnpm add @renweilong/electron-ffmpeg-player
```

Make sure you have `react` and `react-dom` installed as they are peer dependencies.

## Basic Usage

Import the component and its CSS file in your application:

```tsx
import React, { useRef } from 'react';
import { VideoCanvasPlayer, VideoCanvasPlayerHandle } from '@renweilong/electron-ffmpeg-player';
import '@renweilong/electron-ffmpeg-player/style.css'; // Don't forget to import styles

const App = () => {
  const playerRef = useRef<VideoCanvasPlayerHandle>(null);

  const highlights = {
    10.5: "Interesting moment",
    35.2: "Action starts here",
    120.0: "Conclusion"
  };

  return (
    <div style={{ width: '800px', height: '450px' }}>
      <VideoCanvasPlayer
        ref={playerRef}
        src="file:///path/to/your/local/video.mp4"
        theme="dark"
        targetFps={60}
        highlight={highlights}
        showThumbnailRail
        initialSeekTime={12.5}
        autoPlay={true}
        onTimeChange={(time, duration) => {
          console.log(`Current time: ${time}s / ${duration}s`);
        }}
      />
    </div>
  );
};

export default App;
```

## API Reference

### `VideoCanvasPlayerProps`

| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `src` | `string` | **Required** | The source URL or file path of the video. |
| `theme` | `"dark" \| "light"` | `"dark"` | The visual theme of the player. |
| `targetFps` | `number` | `60` | Target frames per second for playback. Max is 60. |
| `highlight` | `HighlightCollection` | `undefined` | A collection of timestamps and labels to display on the timeline. Supports `Map<number, string>` or `Record<number, string>`. |
| `showThumbnailRail` | `boolean` | `false` | Shows a clip-style thumbnail rail below the player with hover preview and click-to-seek. |
| `initialSeekTime` | `number` | `undefined` | Seeks to this time when a source is loaded, before the video is shown. |
| `pendingStartTime` | `number` | `undefined` | A higher-priority source-switch seek time. If provided, it overrides `initialSeekTime` for the current source load. |
| `autoPlay` | `boolean` | `false` | Whether to start playing automatically. |
| `loop` | `boolean` | `false` | Whether the video should loop when it ends. |
| `muted` | `boolean` | `false` | Whether the audio should be initially muted. |
| `playbackRate` | `number` | `1` | Initial playback speed multiplier. |
| `fastSeekStep` | `number` | `5` | The number of seconds to jump when fast forwarding or rewinding. |
| `ffmpeg` | `FFmpegAssetConfig` | `undefined` | Custom configuration for FFmpeg core/worker instances. |
| `backend` | `PlaybackBackend` | `undefined` | Custom backend for probe and playback resolution. |

### Source Switching Example

```tsx
<VideoCanvasPlayer
  src={nextSource}
  pendingStartTime={128.4}
  autoPlay
  showThumbnailRail
/>
```

When `pendingStartTime` or `initialSeekTime` is provided, the player seeks the underlying media element first, then reveals the frame and starts playback if `autoPlay` is enabled.

### Event Callbacks

| Callback | Signature | Description |
| :--- | :--- | :--- |
| `onPlay` | `() => void` | Fired when playback starts. |
| `onPause` | `() => void` | Fired when playback pauses. |
| `onFastForward` | `(time: number) => void` | Fired after fast forwarding. Provides the new time. |
| `onFastRewind` | `(time: number) => void` | Fired after fast rewinding. Provides the new time. |
| `onNextKeyframe` | `(time: number) => void` | Fired when jumping to the next keyframe. |
| `onPreviousKeyframe`| `(time: number) => void` | Fired when jumping to the previous keyframe. |
| `onPlaybackRateChange` | `(rate: number) => void` | Fired when the playback speed changes from the built-in control or ref API. |
| `onTimeChange` | `(time: number, duration: number) => void` | Fired during playback to indicate the current time stream. |
| `onError` | `(error: Error) => void` | Fired when an error occurs during playback or FFmpeg processing. |

### `VideoCanvasPlayerHandle` (Ref API)

You can interact with the player programmatically by passing a `ref`:

- `play(): Promise<void>`: Starts playback.
- `pause(): void`: Pauses playback.
- `seekTo(time: number): void`: Seeks the video to the specified time (in seconds).
- `fastForward(seconds?: number): void`: Skips forward by default or specified seconds.
- `fastRewind(seconds?: number): void`: Skips backward by default or specified seconds.
- `nextKeyframe(): void`: Uses FFmpeg probe data to jump to the next keyframe.
- `previousKeyframe(): void`: Uses FFmpeg probe data to jump to the previous keyframe.
- `setPlaybackRate(rate: number): void`: Updates the playback speed multiplier.
- `getPlaybackRate(): number`: Returns the current playback speed multiplier.
- `getCurrentTime(): number`: Returns the current video time.
- `getDuration(): number`: Returns the total video duration.

## License

MIT