npm.io
2.0.1 • Published 2 weeks ago

use-media-stream

Licence
MIT
Version
2.0.1
Deps
0
Size
82 kB
Vulns
0
Weekly
0
Stars
21

use-media-stream

A React hook for getUserMedia that cleans up after itself.

Cameras, microphones, device switching and track muting — without the lifecycle bugs.

npm CI dependencies size license

Documentation · Live demo · Changelog


Getting a camera stream is one line. Getting it to stop is where the bugs are — a component unmounts and the recording light stays on, a device list leaves an orphaned stream open, a track goes silent and your UI never notices.

This hook owns that lifecycle so you don't have to.

  • Start, stop and swap devices with a small, predictable API
  • Releases tracks on unmount — no lingering camera light
  • Mute without dropping the device, so unmuting is instant
  • Device enumeration split by kind, with live track settings
  • Server-safe — renders in Next.js and Remix without a typeof window dance
  • Zero runtime dependencies, ESM + CJS, typed, published with provenance

Install

npm install use-media-stream

Requires react >= 16 as a peer dependency. Nothing else.

Upgrading from v1? stop() and unmounting now release the stream in cases where they previously did not. See Migrating from v1.

Quick start

import { useEffect, useRef } from 'react';
import useMediaStream from 'use-media-stream';

function Camera() {
  const { stream, isStreaming, error, start, stop } = useMediaStream();
  const videoRef = useRef<HTMLVideoElement>(null);

  useEffect(() => {
    if (videoRef.current) videoRef.current.srcObject = stream;
  }, [stream]);

  if (error) return <p>{error.message}</p>;

  return (
    <>
      <video ref={videoRef} autoPlay playsInline muted />
      <button onClick={isStreaming ? stop : start}>{isStreaming ? 'Stop' : 'Start'}</button>
    </>
  );
}

That's the whole thing. Navigate away mid-stream and the camera turns off on its own.

Documentation

Full guides and API reference at kothariji.github.io/use-media-stream:

Quick start A working camera in about fifteen lines
Streams and lifecycle When the stream is released, and by what
Devices Listing and switching cameras and microphones
Muting and track events Why muting isn't stopping
Constraints Resolution, frame rate, and how merging works
Server rendering Next.js, Remix, static export
API reference Everything the hook returns
Live demo Every function, wired to your camera

Development

npm install          # one install at the root; docs/ is an npm workspace
npm run typecheck
npm test
npm run test:coverage
npm run build

The docs site doubles as the development playground — it imports the hook from src/, so edits hot-reload against a real camera:

npm run docs         # dev server, http://localhost:4321/use-media-stream/
npm run docs:stop    # it runs detached, so it needs stopping explicitly
npm run docs:build

Install from the root, not from inside docs/. The demo imports the hook from src/, which resolves its dependencies from the root — a separate install in docs/ gives you two copies of React in one page.

Verifying the published output
npm run verify:package

Packs the library and installs it into a scratch project the way a consumer would, then checks require() resolves the CJS build, import resolves the ESM one, types resolve in every module mode (attw), and package.json is sane (publint).

Worth running before any release. npm link and file: installs are not equivalent — they skip packing and the files field, and both of the packaging bugs this library once shipped survive them. CI runs this same script.

Releasing
npm version <patch|minor|major>
git push --follow-tags

A v* tag runs the full suite and publishes with provenance. Prereleases go to the next dist-tag, so npm install use-media-stream is unaffected.

Contributing

Issues and pull requests welcome — open an issue to start.

License

MIT Dhruv Kothari

Keywords