Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions examples/nextjs-with-typescript/components/renderers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,58 @@ export const BooleanRenderer = ({
);
};

export const OptionalBooleanRenderer = ({
name,
value,
label,
onChange,
formatter = DefaultEnumFormatter
}: {
name: string;
value: boolean | undefined;
label?: string;
removeFalse?: boolean;
onChange: (obj: any) => void;
formatter?: (enumValue: boolean) => ReactNode;
}) => {
const labelStr = label ?? toWordsFromKeyName(name);
const values = [true, false];
return (
<div>
<label htmlFor={`${name}-control`}>
{labelStr} (<code>{name}</code>)
</label>
<div>
<input
id={`${name}-none-control`}
type="radio"
onChange={() => {
onChange(toChangeObject(name, undefined))}}
value=""
checked={value === undefined}
/>
<label htmlFor={`${name}-none-control`}>None</label>
{values.map((enumValue, i) => {
return (
<Fragment key={`${name}-${enumValue}`}>
<input
id={`${name}-${enumValue}-control`}
type="radio"
onChange={() => {
onChange(toChangeObject(name, enumValue));
}}
value={enumValue.toString()}
checked={value === enumValue}
/>
<label htmlFor={`${name}-${enumValue}-control`}>{formatter(enumValue)}</label>
</Fragment>
);
})}
</div>
</div>
);
};

export const NumberRenderer = ({
name,
value,
Expand Down
8 changes: 8 additions & 0 deletions examples/nextjs-with-typescript/pages/MuxPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
EnumMultiSelectRenderer,
EnumRenderer,
NumberRenderer,
OptionalBooleanRenderer,
TextRenderer,
URLRenderer,
} from '../components/renderers';
Expand Down Expand Up @@ -127,6 +128,7 @@ const DEFAULT_INITIAL_STATE: Partial<MuxPlayerProps> = Object.freeze({
fullscreenElement: undefined,
proudlyDisplayMuxBadge: undefined,
disablePseudoEnded: undefined,
capRenditionToPlayerSize: undefined,
});

const SMALL_BREAKPOINT = 700;
Expand Down Expand Up @@ -282,6 +284,7 @@ function MuxPlayerPage({ location }: Props) {
// debug: true,
// }}
maxAutoResolution="720p"
capRenditionToPlayerSize={state.capRenditionToPlayerSize}
title={state.title}
videoTitle={state.videoTitle}
startTime={state.startTime}
Expand Down Expand Up @@ -654,6 +657,11 @@ function MuxPlayerPage({ location }: Props) {
min={0}
step={1}
/>
<OptionalBooleanRenderer
value={state.capRenditionToPlayerSize}
name="capRenditionToPlayerSize"
onChange={genericOnChange}
/>
</div>
</main>
</>
Expand Down
44 changes: 32 additions & 12 deletions examples/nextjs-with-typescript/pages/mux-player.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
// @ts-nocheck
import Link from "next/link";
import Head from "next/head";
import "@mux/mux-player";
import { useState } from "react";
import { useEffect, useRef, useState } from "react";
import MuxPlayerElement from "@mux/mux-player";
import { OptionalBooleanRenderer } from "../components/renderers";
import { Autoplay, MuxMediaPropTypes } from "../../../packages/playback-core/dist/types/types";

const INITIAL_DEBUG = false;
const INITIAL_MUTED = false;
const INITIAL_AUTOPLAY = false;
const INITIAL_MUTED = true;
const INITIAL_AUTOPLAY: Autoplay = false;
const INITIAL_PLAYBACK_ID = "g65IqSFtWdpGR100c2W8VUHrfIVWTNRen";
const INITIAL_CAP_LEVEL_TO_PLAYER_SIZE : boolean | undefined = undefined;

function MuxPlayerWCPage() {
// const mediaElRef = useRef(null);
const mediaElRef = useRef<MuxPlayerElement>(null);
const [playbackId, setPlaybackId] = useState(INITIAL_PLAYBACK_ID);
const [muted, setMuted] = useState(INITIAL_MUTED);
const [debug, setDebug] = useState(INITIAL_DEBUG);
const [autoplay, setAutoplay] = useState(INITIAL_AUTOPLAY);
const debugObj = debug ? { debug: "" } : {};
const mutedObj = muted ? { muted: "" } : {};
const autoplayObj = autoplay ? { autoplay } : {};
const [autoplay, setAutoplay] = useState<MuxMediaPropTypes["autoplay"]>(INITIAL_AUTOPLAY);
const [capRenditionToPlayerSize, setCapRenditionToPlayerSize] = useState<boolean | undefined>(INITIAL_CAP_LEVEL_TO_PLAYER_SIZE);
const debugObj : {debug?: boolean}= debug ? { debug: true } : {};
const mutedObj : {muted?: boolean} = muted ? { muted: true } : {};
const autoplayObj : {autoplay?: Autoplay} = autoplay ? { autoplay: autoplay } : {};

// Set capRenditionToPlayerSize via JavaScript property (supports undefined, true, and false)
useEffect(() => {
if (mediaElRef.current) {
mediaElRef.current.capRenditionToPlayerSize = capRenditionToPlayerSize;
}
}, [capRenditionToPlayerSize]);

return (
<>
<Head>
Expand All @@ -26,7 +37,7 @@ function MuxPlayerWCPage() {

<div>
<mux-player
// style={{ aspectRatio: "16 / 9" }}
ref={mediaElRef}
playback-id={playbackId}
forward-seek-offset={10}
backward-seek-offset={10}
Expand All @@ -43,13 +54,17 @@ function MuxPlayerWCPage() {
></mux-player>
</div>
<div className="options">
<button onClick={() => {
if (!mediaElRef.current) return;
mediaElRef.current.load();
}}>Reload</button>
<div>
<label htmlFor="autoplay-control">Muted Autoplay</label>
<input
id="autoplay-control"
type="checkbox"
onChange={() => setAutoplay(!autoplay ? "muted" : false)}
checked={autoplay}
checked={!!autoplay}
/>
</div>
<div>
Expand Down Expand Up @@ -78,6 +93,11 @@ function MuxPlayerWCPage() {
defaultValue={playbackId}
/>
</div>
<OptionalBooleanRenderer
value={capRenditionToPlayerSize}
name="capRenditionToPlayerSize"
onChange={({ capRenditionToPlayerSize }) => setCapRenditionToPlayerSize(capRenditionToPlayerSize)}
/>
</div>
</>
);
Expand Down
26 changes: 24 additions & 2 deletions examples/nextjs-with-typescript/pages/mux-video-react.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import Head from 'next/head';
import { useRef, useState } from "react";
import MuxVideo from "@mux/mux-video/react";
import { EnumRenderer, OptionalBooleanRenderer } from '../components/renderers';
import MuxVideoElement from '@mux/mux-video';

const INITIAL_AUTOPLAY = false;
const INITIAL_MUTED = false;
const INITIAL_CAP_LEVEL_TO_PLAYER_SIZE : boolean | undefined = undefined;
const INITIAL_PREFER_PLAYBACK = undefined;

function MuxVideoPage() {
const mediaElRef = useRef(null);
const mediaElRef = useRef<MuxVideoElement>(null);
const [autoplay, setAutoplay] = useState<"muted" | boolean>(INITIAL_AUTOPLAY);
const [muted, setMuted] = useState(INITIAL_MUTED);
const [preferPlayback, setPreferPlayback] = useState<MuxVideoElement["preferPlayback"]>(INITIAL_PREFER_PLAYBACK);
const [capRenditionToPlayerSize, setCapRenditionToPlayerSize] = useState<boolean | undefined>(INITIAL_CAP_LEVEL_TO_PLAYER_SIZE);
const [paused, setPaused] = useState<boolean | undefined>(true);

return (
Expand All @@ -32,12 +38,13 @@ function MuxVideoPage() {
// }}
// envKey="mux-data-env-key"
controls
capRenditionToPlayerSize={capRenditionToPlayerSize}
autoplay={autoplay}
muted={muted}
maxResolution="2160p"
minResolution="540p"
renditionOrder="desc"
preferPlayback="native"
preferPlayback={preferPlayback}
onPlay={() => {
setPaused(false);
}}
Expand All @@ -47,6 +54,10 @@ function MuxVideoPage() {
/>

<div className="options">
<button onClick={() => {
if (!mediaElRef.current) return;
mediaElRef.current.load();
}}>Reload</button>
<div>
<label htmlFor="paused-control">Paused</label>
<input
Expand Down Expand Up @@ -74,6 +85,17 @@ function MuxVideoPage() {
checked={muted}
/>
</div>
<EnumRenderer
value={preferPlayback}
name="preferPlayback"
onChange={({ preferPlayback }) => setPreferPlayback(preferPlayback as MuxVideoElement["preferPlayback"])}
values={['mse', 'native']}
/>
<OptionalBooleanRenderer
value={capRenditionToPlayerSize}
name="capRenditionToPlayerSize"
onChange={({ capRenditionToPlayerSize }) => setCapRenditionToPlayerSize(capRenditionToPlayerSize)}
/>
</div>
</>
);
Expand Down
7 changes: 4 additions & 3 deletions packages/mux-player-react/REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@
| `targetLiveWindow` | `number` | An offset representing the seekable range for live content, where `Infinity` means the entire live content is seekable (aka "standard DVR"). Used along with `streamType` to determine what UI/controls to show. | (inferred from `playbackId` and/or `streamType`, otherwise `NaN`) |
| `startTime` | `number` (seconds) | Specify where in the media's timeline you want playback to start. | `0` |
| `preferPlayback` | `"mse" \| "native"` | Specify if Mux Player should try to use Media Source Extension or native playback (if available). If no value is provided, Mux Player will choose based on what's deemed optimal for content and playback environment. | Varies |
| `maxResolution` | `"720p" \| "1080p" \| "1440p" \| "2160p"` | Specify the maximum resolution you want delivered for this video. | N/A |
| `minResolution` | `"480p" \| "540p" \| "720p" \| "1080p" \| "1440p" \| "2160p"` | Specify the minimum resolution you want delivered for this video. | N/A |
| `maxAutoResolution` | `string` (`"720p"`, `"1080p"`, `"1440p"`, or `"2160p"`) | Cap the default resolution selection based on total pixels (width × height) to match Mux Video pricing tiers. Values align with [Mux Video resolution-based pricing](https://www.mux.com/docs/pricing/video#resolution-based-pricing). If there's an exact match, it will be used. Otherwise, selects the highest quality rendition that doesn't exceed the cap. Only accepts: `"720p"`, `"1080p"`, `"1440p"`, or `"2160p"`. Other values are ignored. | N/A |
| `maxResolution` | `"720p" \| "1080p" \| "1440p" \| "2160p"` | Limits the highest resolution rendition requested from the server. Renditions above this are excluded from the playlist entirely. For client-side dimension-based capping, see `capRenditionToPlayerSize`. | N/A |
| `minResolution` | `"480p" \| "540p" \| "720p" \| "1080p" \| "1440p" \| "2160p"` | Limits the lowest resolution rendition requested from the server. Renditions below this are excluded from the playlist entirely. | N/A |
| `maxAutoResolution` | `string` (`"720p"`, `"1080p"`, `"1440p"`, or `"2160p"`) | Caps automatic resolution selection to align with [Mux Video pricing tiers](https://www.mux.com/docs/pricing/video#resolution-based-pricing). The player won't automatically select resolutions above this cap. Unlike `maxResolution`, all renditions remain available. Unlike `capRenditionToPlayerSize`, this is independent of player dimensions. | N/A |
| `renditionOrder` | `"desc"` | Change the order in which renditions are provided in the src playlist. Can impact initial segment loads. Currently only support `"desc"` for descending order | N/A |
| `capRenditionToPlayerSize` | `boolean` | Caps video resolution based on the player's display dimensions to avoid downloading video larger than can be displayed. When `undefined` (default), caps to player size with a 720p minimum floor. Set to `true` to cap strictly to player dimensions (may use lower resolutions for small players). Set to `false` to disable dimension-based capping. Independent of `maxResolution` (server-side) and `maxAutoResolution` (pricing cap). | `undefined` (Mux optimized) |
| `programStartTime` | `number` | Apply PDT-based [instant clips](https://docs.mux.com/guides/create-instant-clips) to the beginning of the media stream. | N/A |
| `programEndTime` | `number` | Apply PDT-based [instant clips](https://docs.mux.com/guides/create-instant-clips) to the end of the media stream. | N/A |
| `assetStartTime` | `number` | Apply media timeline-based [instant clips](https://docs.mux.com/guides/create-instant-clips) to the beginning of the media stream. | N/A |
Expand Down
7 changes: 5 additions & 2 deletions packages/mux-player-react/src/lazy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ import useIsIntersecting from './useIsIntersecting';
import type { MuxPlayerProps, MuxPlayerRefAttributes, MuxCSSProperties } from './index';
import type MuxPlayerElement from '@mux/mux-player';

interface MuxPlayerElementReact extends Partial<Omit<MuxPlayerElement, 'style' | 'children'>> {
interface MuxPlayerElementReact
extends Partial<Omit<MuxPlayerElement, 'style' | 'children' | 'autoplay' | 'capRenditionToPlayerSize'>> {
ref: React.MutableRefObject<MuxPlayerElement | null> | null | undefined;
style: React.CSSProperties;
style?: React.CSSProperties;
children?: React.ReactNode;
autoplay?: MuxPlayerProps['autoPlay'];
'cap-rendition-to-player-size'?: boolean;
}

declare global {
Expand Down
1 change: 1 addition & 0 deletions packages/mux-player-react/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export type MuxPlayerProps = {
theme?: string;
themeProps?: { [k: string]: any };
fullscreenElement?: string;
capRenditionToPlayerSize?: boolean;
onAbort?: GenericEventListener<MuxPlayerElementEventMap['abort']>;
onCanPlay?: GenericEventListener<MuxPlayerElementEventMap['canplay']>;
onCanPlayThrough?: GenericEventListener<MuxPlayerElementEventMap['canplaythrough']>;
Expand Down
Loading
Loading