Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 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,
capLevelToPlayerSize: undefined,
});

const SMALL_BREAKPOINT = 700;
Expand Down Expand Up @@ -282,6 +284,7 @@ function MuxPlayerPage({ location }: Props) {
// debug: true,
// }}
maxAutoResolution="720p"
capLevelToPlayerSize={state.capLevelToPlayerSize}
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.capLevelToPlayerSize}
name="capLevelToPlayerSize"
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 [capLevelToPlayerSize, setCapLevelToPlayerSize] = 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 capLevelToPlayerSize via JavaScript property (supports undefined, true, and false)
useEffect(() => {
if (mediaElRef.current) {
mediaElRef.current.capLevelToPlayerSize = capLevelToPlayerSize;
}
}, [capLevelToPlayerSize]);

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={capLevelToPlayerSize}
name="capLevelToPlayerSize"
onChange={({ capLevelToPlayerSize }) => setCapLevelToPlayerSize(capLevelToPlayerSize)}
/>
</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 [capLevelToPlayerSize, setCapLevelToPlayerSize] = 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
capLevelToPlayerSize={capLevelToPlayerSize}
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={capLevelToPlayerSize}
name="capLevelToPlayerSize"
onChange={({ capLevelToPlayerSize }) => setCapLevelToPlayerSize(capLevelToPlayerSize)}
/>
</div>
</>
);
Expand Down
1 change: 1 addition & 0 deletions packages/mux-player-react/REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
| `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 |
| `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 |
| `capLevelToPlayerSize` | `boolean` | Controls whether hls.js caps video quality based on player dimensions. When `undefined` (default), uses Mux's optimized behavior that caps quality to player size but maintains a 720p minimum floor. Set to `true` to explicitly enable standard hls.js capping (may drop below 720p). Set to `false` to disable capping entirely. | `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' | 'capLevelToPlayerSize'>> {
ref: React.MutableRefObject<MuxPlayerElement | null> | null | undefined;
style: React.CSSProperties;
style?: React.CSSProperties;
children?: React.ReactNode;
autoplay?: MuxPlayerProps['autoPlay'];
'cap-level-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;
capLevelToPlayerSize?: boolean;
onAbort?: GenericEventListener<MuxPlayerElementEventMap['abort']>;
onCanPlay?: GenericEventListener<MuxPlayerElementEventMap['canplay']>;
onCanPlayThrough?: GenericEventListener<MuxPlayerElementEventMap['canplaythrough']>;
Expand Down
Loading
Loading