npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-video-trim

v0.2.0

Published

A React component for selecting trim ranges on a video with a filmstrip timeline.

Downloads

745

Readme

React Video Trim

A React component for selecting trim ranges on a video with a filmstrip timeline.

The core library reports the selected { startTime, endTime } range. The included WebCodecs plugin can turn that range into a trimmed video file in the browser.

Install

# npm
npm install react-video-trim

# yarn
yarn add react-video-trim

# pnpm
pnpm add react-video-trim

# bun
bun add react-video-trim

Bundler

This package ships as ESM only. Use it with Vite, Next.js, webpack, or any modern bundler that supports import.

Import the component and its styles:

import { VideoTrim } from 'react-video-trim'
import 'react-video-trim/style.css'

The WebCodecs trimming plugin is a separate entry point so the core bundle does not load video processing code unless you import it:

import { createTrimHandler } from 'react-video-trim/plugins/webcodecs'

Props

VideoTrim

| Prop | Type | Required | Description | | ----------- | ---------------------------- | -------- | --------------------------------------------------------------------------------------------------- | | src | string \| File \| Blob | Yes | Video source URL, file, or blob. | | onTrim | (range: TrimRange) => void | Yes | Called when the user confirms a trim. Receives { startTime, endTime } in seconds. | | onCancel | () => void | No | Called when the user cancels. Renders a Cancel button when provided. | | labels | VideoTrimLabelsProp | No | Overrides visible text, ARIA labels, loading copy, and video error messages. Uses English defaults. | | className | string | No | Applied to the root element. | | style | CSSProperties | No | Inline styles for the root element. |

TrimRange

| Field | Type | Description | | ----------- | -------- | --------------------------- | | startTime | number | Trim start time in seconds. | | endTime | number | Trim end time in seconds. |

Labels

labels accepts a partial object, so you only need to provide the text you want to replace. Missing values fall back to defaultVideoTrimLabels.

import { VideoTrim, defaultVideoTrimLabels } from 'react-video-trim'

;<VideoTrim
  src={videoFile}
  onTrim={setTrimRange}
  labels={{
    actions: {
      trim: 'Guardar recorte',
      cancel: 'Cancelar',
    },
    playback: {
      play: 'Reproducir',
      pause: 'Pausar',
    },
    video: {
      ariaLabel: 'Vista previa del video',
    },
    toolbar: {
      ariaLabel: 'Controles para recortar video',
    },
    filmstrip: {
      loadingFrames: ({ loaded, total }) =>
        `Cargando fotogramas ${loaded}/${total}`,
    },
    errors: {
      ...defaultVideoTrimLabels.errors,
      load: 'No se pudo cargar este video.',
    },
  }}
/>

Example

import { useState } from 'react'
import { VideoTrim } from 'react-video-trim'
import type { TrimRange } from 'react-video-trim'
import 'react-video-trim/style.css'

export function App() {
  const [videoFile, setVideoFile] = useState<File | null>(null)
  const [trimRange, setTrimRange] = useState<TrimRange | null>(null)

  return (
    <div>
      <input
        type="file"
        accept="video/*"
        onChange={(event) => setVideoFile(event.target.files?.[0] ?? null)}
      />

      {videoFile ? <VideoTrim src={videoFile} onTrim={setTrimRange} /> : null}

      {trimRange ? <pre>{JSON.stringify(trimRange, null, 2)}</pre> : null}
    </div>
  )
}

WebCodecs Trimming

Use createTrimHandler as an onTrim adapter when you want WebCodecs to produce a trimmed file:

import { useMemo, useState } from 'react'
import { VideoTrim } from 'react-video-trim'
import {
  type TrimVideoResult,
  createTrimHandler,
} from 'react-video-trim/plugins/webcodecs'
import 'react-video-trim/style.css'

export function App() {
  const [videoFile, setVideoFile] = useState<File | null>(null)
  const [result, setResult] = useState<TrimVideoResult | null>(null)

  const onTrim = useMemo(() => {
    if (!videoFile) return undefined

    return createTrimHandler({
      src: videoFile,
      outputFormat: 'mp4',
      onComplete: setResult,
      onError: console.error,
      onProgress: ({ progress }) => {
        console.log(`Trimming… ${Math.round(progress * 100)}%`)
      },
    })
  }, [videoFile])

  if (!videoFile || !onTrim) return null

  return (
    <VideoTrim
      src={videoFile}
      onTrim={(range) => {
        void onTrim(range)
      }}
    />
  )
}

Or call trimVideo directly when you do not need the React handler adapter:

import { trimVideo } from 'react-video-trim/plugins/webcodecs'

const result = await trimVideo(videoFile, {
  startTime: 2.5,
  endTime: 12,
})

const url = URL.createObjectURL(result.blob)

The WebCodecs implementation uses Mediabunny to trim media in modern browsers without shipping a large video processing runtime. It can copy media data when possible and transcode when needed, depending on the browser codecs and selected output format.

Alternatives

WebCodecs is the default recommendation for this package because it keeps the browser bundle small and uses native media APIs. Depending on your product requirements, you may still consider another trimming strategy in your own app.

FFmpeg

FFmpeg.wasm runs FFmpeg in the browser through WebAssembly.

Pros:

  • Handles a broad range of containers, codecs, and transformations.
  • Gives you FFmpeg's familiar command model when you need advanced processing.
  • Can be a good fit for apps that need maximum format coverage and can tolerate heavier downloads.

Cons:

  • Adds a large (~38-42mb) WebAssembly payload compared with WebCodecs.
  • Usually has a slower startup because the FFmpeg runtime must load before work begins.
  • Increases memory and CPU pressure, especially on mobile devices.

MediaRecorder

MediaRecorder can replay the selected range through a media element or canvas stream and record the result with native browser APIs.

Pros:

  • No large processing runtime to download.
  • Works with browser-native APIs and can support files the browser can play.
  • Useful as a simple compatibility fallback for basic recording workflows.

Cons:

  • Runs in real time, so trimming a 20 second range takes about 20 seconds.
  • Output format and codec choices are limited by each browser's MediaRecorder support.
  • Re-recording can reduce quality and may not preserve the original media streams exactly.

Development

Clone the repo, install dependencies, and start the demo app:

git clone <repo-url>
cd react-video-trim
bun install
bun run dev

Other useful commands:

bun run build   # type-check and build dist/react-video-trim.js + dist/plugins/webcodecs.js
bun run lint
bun run preview # preview the production build locally

The demo lives in src/Demo.tsx and uses WebCodecs to trim and preview the output.