@norskvideo/norsk-player-react
v1.2.1
Published
React wrapper for @norskvideo/norsk-player — a frame-accurate, browser-native player for TAMS media stores.
Readme
@norskvideo/norsk-player-react
A React wrapper around @norskvideo/norsk-player
— a browser-native, frame-accurate video player for content served from a
TAMS (Time-addressable Media
Store).
It provides a single <Player> component with the
Media Chrome control bar (play, scrubber, time
display, volume, fullscreen) already assembled, and keyboard frame-stepping
wired up. For everything the underlying player can do — the src URL forms,
authentication, browser requirements — see the
@norskvideo/norsk-player README.
Installation
npm install @norskvideo/norsk-player-reactReact 19 is a peer dependency:
npm install react@^19 react-dom@^19Usage
import { Player } from '@norskvideo/norsk-player-react';
export default function App() {
return (
<div style={{ width: '100%', aspectRatio: '16 / 9' }}>
<Player
className="w-full h-full"
src="https://host/x-tams/"
authHeader={() => `Bearer ${token}`}
/>
</div>
);
}Point src at your TAMS store. The default form above plays the latest
audio and video source; see the
src URL forms
for how to select a specific source or play a plain MP4.
Changing source:
srcis read when the player mounts. To switch to a different source, give the<Player>akeythat changes with the source (e.g.key={src}) so React remounts it.
Server-side rendering (Next.js, Remix, …)
The component is SSR-safe. The underlying @norskvideo/norsk-player custom
element registers browser-only APIs, so it is imported lazily on the client —
importing <Player> from a server component or SSR bundle will not throw.
During server rendering and until the player module has loaded on the client,
the fallback is shown (an empty container by default, so layout is preserved).
Supply your own placeholder if you want one:
<Player
className="w-full h-full"
src="https://host/x-tams/"
fallback={<div className="skeleton">Loading player…</div>}
/>Props
| Prop | Type | Default | Purpose |
| --- | --- | --- | --- |
| src | string \| string[] | — | Media source. A single URL, or [audioUrl, videoUrl]. Required. |
| className | string | — | Applied to the player container. Required. |
| fillContainer | boolean | false | Fill the container (crop) instead of letterboxing to fit. |
| prefetchGops | number | 2 | How many groups-of-pictures to prefetch ahead. |
| thumbnailSize | { width: number, height: number } | { width: 142, height: 160 } | Size of generated scrubber thumbnails. |
| authHeader | () => string \| undefined | — | Called per request; return an Authorization header value (e.g. Bearer … or Basic …). |
| autoPlay | boolean | true | Start playback automatically once the media is ready. Browsers may still block autoplay until the user interacts with the page. |
| keyboardShortcuts | boolean | true | Enable the frame-stepping / play-pause keyboard shortcuts below. |
| keyboardTarget | 'element' \| 'window' | 'element' | Where shortcuts are listened for. 'element' only while the player has focus (recommended when embedding); 'window' captures globally (ignoring form fields), convenient for full-page players. |
| fallback | React.ReactNode | empty container | Rendered during SSR and until the player loads on the client. |
| ref | React.Ref<NorskVideoElement> | — | Ref to the underlying <norsk-video> element. See Accessing the element below. |
| onTimeUpdate | (el: NorskVideoElement) => void | — | Called on timeupdate with the element. Declarative alternative to attaching a listener via ref. |
| onSeeked | (el: NorskVideoElement) => void | — | Called on seeked with the element. |
| onLoadedMetadata | (el: NorskVideoElement) => void | — | Called on loadedmetadata with the element. |
| onDurationChange | (el: NorskVideoElement) => void | — | Called on durationchange with the element. |
| onError | (event: Event) => void | — | Called on error with the DOM event. |
| controls | React.ReactNode | default bar | Replace the default Media Chrome control bar. See Custom controls below. |
Accessing the element
Pass a ref to reach the underlying NorskVideoElement
directly — read/seek the playhead, drive transport, step frames, and subscribe
to media events. This is what you need to build a scrub / in-out trim UI around
the player. The ref is null until the player has loaded and mounted on the
client, so null-check before use.
import { useRef } from 'react';
import { Player, type NorskVideoElement } from '@norskvideo/norsk-player-react';
function Trimmer() {
const ref = useRef<NorskVideoElement>(null);
const markIn = () => {
const el = ref.current;
if (!el) return;
// Absolute (wall-clock) instant of the on-screen frame, for a TAMS cut:
const absolute = (el.mediaTimeOrigin ?? 0) + el.currentTime;
console.log('in point', el.currentTime, 'absolute', absolute);
};
return <Player ref={ref} className="w-full h-full" src="https://host/x-tams/" />;
}NorskVideoElement is re-exported from this package for convenience. It exposes
currentTime (get/set — assign to seek), duration, paused,
mediaTimeOrigin, play() / pause(), stepFrameNext() /
stepFramePrevious(), and the standard media events (timeupdate, seeked,
loadedmetadata, durationchange, error, …) via addEventListener.
Custom controls
By default <Player> renders a Media Chrome control bar (play, scrubber, time,
volume, fullscreen). Pass controls to replace it — for example to add
<media-clip-selector> for in/out trim markers. Your controls render inside the
same <MediaController>, so the standard Media Chrome elements still bind to the
player. Register any extra custom elements you use yourself.
import { Player } from '@norskvideo/norsk-player-react';
import {
MediaControlBar,
MediaPlayButton,
MediaTimeDisplay,
} from 'media-chrome/react';
// Registers the <media-clip-selector> custom element (a Media Chrome "extra"):
import 'media-chrome/dist/extras/media-clip-selector';
<Player
className="w-full h-full"
src="https://host/x-tams/"
controls={
<MediaControlBar>
<MediaPlayButton />
<media-clip-selector />
<MediaTimeDisplay showDuration />
</MediaControlBar>
}
/>;Keyboard shortcuts
Enabled by default (keyboardShortcuts). With keyboardTarget="element" (the
default) the player must be focused; with keyboardTarget="window" they work
anywhere except while a form field is focused.
| Key | Action |
| --- | --- |
| . or n | Step forward one frame |
| , or p | Step back one frame |
| Space | Toggle play / pause |
