Keyboard
Keyboard shortcuts for playback, seeking, volume, and more.
import { hotkeys } from "react-video-kit/hotkeys";Adds 1.3 KB to a player1.8 KB on its ownSource
Adds keyboard shortcuts, and a brief message over the video that confirms what most of them did. Click the player below, then try the keys listed under it.
Click the player once, then try a key.
- Space
- Play or pause
- ← →
- Seek 5 seconds
- J L
- Seek 10 seconds
- ↑ ↓
- Volume
- M
- Mute
- 0–9
- Jump to a tenth of the video
- Home End
- Jump to the start or end
- < >
- Slower or faster
- C
- Captions
- P
- Picture in picture
- F
- Fullscreen
"use client";import { captions } from "react-video-kit/captions";import { fullscreen } from "react-video-kit/fullscreen";import { hotkeys } from "react-video-kit/hotkeys";import { idle } from "react-video-kit/idle";import { pip } from "react-video-kit/pip";import { VideoPlayer } from "react-video-kit/player";import { speed } from "react-video-kit/speed";const plugins = [ hotkeys(), idle(), speed(), captions({ tracks: [{ src: "/media/captions.en.vtt", language: "en", label: "English" }] }), pip(), fullscreen(),];const keys = [ ["Space", "Play or pause"], ["← →", "Seek 5 seconds"], ["J L", "Seek 10 seconds"], ["↑ ↓", "Volume"], ["M", "Mute"], ["0–9", "Jump to a tenth of the video"], ["Home End", "Jump to the start or end"], ["< >", "Slower or faster"], ["C", "Captions"], ["P", "Picture in picture"], ["F", "Fullscreen"],] as const;export default function Hotkeys() { return ( <> <VideoPlayer src="/media/sample-720.mp4" poster="/media/poster.jpg" plugins={plugins} load="visible" /> <div className="mt-3 text-sm text-current opacity-80"> <p className="font-medium">Click the player once, then try a key.</p> <dl className="mt-2 grid gap-x-6 gap-y-1.5 sm:grid-cols-2"> {keys.map(([key, action]) => ( <div key={key} className="flex items-baseline gap-2"> <dt> <kbd className="rounded border border-current px-1.5 py-0.5 font-mono text-xs">{key}</kbd> </dt> <dd>{action}</dd> </div> ))} </dl> </div> </> );}Usage
import { hotkeys } from "react-video-kit/hotkeys";import { VideoPlayer } from "react-video-kit/player";const plugins = [hotkeys()];<VideoPlayer src="/video.mp4" plugins={plugins} />;The options change how far the keys move things. seekStep and largeSeekStep are in seconds, and volumeStep is from 0 to 1.
hotkeys({ seekStep: 10, largeSeekStep: 30, volumeStep: 0.1 });Keys
| Key | What it does | Needs |
|---|---|---|
Space, K | Play or pause | |
←, → | Seek back or forward by seekStep, 5 seconds by default | |
J, L | Seek back or forward by largeSeekStep, 10 seconds by default | |
↑, ↓ | Volume up or down by volumeStep, 5% by default | |
M | Mute or unmute | |
0 to 9 | Jump to that tenth of the timeline: 0 is the start and 5 is halfway | |
Home, End | Jump to the start or end of the timeline | |
>, < | Next or previous rate | speed |
C | Captions on or off | captions |
P | Picture in picture on or off | pip |
F | Fullscreen on or off | fullscreen |
Letters work in either case. A key does nothing if the plugin it needs isn't installed. The keys themselves are fixed, and there's no option to rebind them, but the bind command adds keys of your own.
When keys are ignored
The player leaves a key alone when:
- Ctrl, Cmd, or Alt is held. Shift is fine, since
<and>usually need it. - The viewer is typing in an
input,textarea,select, orcontenteditableelement. - A slider has focus and the key is an arrow,
Home,End,Page Up, orPage Down. The slider uses those. Other keys still work. - A button, link, or
summaryhas focus and the key isSpace. That press belongs to the focused element.Kstill plays or pauses. - Something already called
preventDefault()on it, as an open menu does for the keys it uses. To keep a key for yourself, do the same before the event reachesdocument. - The player isn't the one receiving keys, as described below.
Several players on a page
Each player acts on a key when focus is inside it, or when it's the player the viewer last used.
- A click, a tap, or focus landing inside a player makes it the last used, replacing any other.
- It stays the last used until the viewer clicks or taps somewhere outside it, or it unmounts. Moving focus away with Tab doesn't end it.
- Until the viewer uses a player, keys pressed elsewhere on the page don't reach it.
So a key only ever controls one player, the one the viewer used most recently.
Confirm keys your own way
HotkeysFeedback is the message over the video, which the plugin adds to the overlay slot. It has role="status", so screen readers announce it, and it clears after 700ms. onFeedback gives you the same messages, such as Pause, +5s, Volume 40%, or 1.5×. The i18n plugin translates the words.
"use client";import { useEffect, useState } from "react";import { useCommands } from "react-video-kit";import { hotkeys } from "react-video-kit/hotkeys";function LastKey() { const { onFeedback } = useCommands(hotkeys); const [message, setMessage] = useState(""); useEffect(() => onFeedback(setMessage), [onFeedback]); return <p>{message}</p>;}Behaviour
- While a player is receiving keys, it takes every key in the table from the page, so the arrows,
Space,Home, andEndstop scrolling it. A click or tap elsewhere on the page gives them back. ↑from muted starts at 0, so it unmutes at one step.↓to 0 mutes.Cturns on the track that was last on, or the first track if none was.0to9,Home,End,C,P, andFshow no message.- The seek, jump, and speed keys do nothing and show no message when that isn't possible, such as during an ad or on a live stream with no DVR window.
- With the idle plugin, a key the player acts on brings hidden controls back, wherever focus is.
API
Options
| Option | Type | Description |
|---|---|---|
| seekStep? | number | Seconds moved by the arrow keys. |
| largeSeekStep? | number | Seconds moved by J and L. |
| volumeStep? | number | Change per Up or Down press, from 0 to 1. |
State
This plugin has no state of its own.
Commands
Call them with useCommands(hotkeys).
| Command | Type | Description |
|---|---|---|
| bindings | () => readonly HotkeyBinding[] | The shortcuts this player responds to, given which plugins are installed. |
| bind | (key: string, id: string, action: () => void) => () => void | Adds a shortcut, under the same rules as the built-in ones. Returns a function that removes it. |
| onFeedback | (listener: FeedbackListener) => () => void | Listens for the message each shortcut shows. |
Parts
| Part | Description |
|---|---|
| HotkeysFeedback | Confirms each shortcut in a brief message, also announced to screen readers. |