diff --git a/packages/core/src/dom/media/castable/index.ts b/packages/core/src/dom/media/castable/index.ts
index e3ccf130d..92c15cd10 100644
--- a/packages/core/src/dom/media/castable/index.ts
+++ b/packages/core/src/dom/media/castable/index.ts
@@ -2,14 +2,14 @@ import type { MixinReturn } from '@videojs/utils/types';
import type { RemotePlaybackLike } from '../predicate';
import { GoogleCastProvider } from './google-cast-provider';
import { RemotePlayback } from './remote-playback';
-import type { CastableMediaProps, CastableMediaSuperclass } from './types';
+import type { CastableMedia, CastableMediaHostConstructor } from './types';
import { getDefaultCastOptions, loadCastFramework, requiresCastFramework } from './utils';
export type { CastableMediaElement } from './types';
-export const CastableMediaMixin = (
+export const CastableMediaMixin = (
superclass: Base
-): MixinReturn => {
+): MixinReturn => {
class CastableMedia extends superclass {
#castOptions = getDefaultCastOptions();
#castCustomData: Record | null | undefined;
@@ -222,5 +222,5 @@ export const CastableMediaMixin = (
}
}
- return CastableMedia as unknown as MixinReturn;
+ return CastableMedia as unknown as MixinReturn;
};
diff --git a/packages/core/src/dom/media/castable/types.ts b/packages/core/src/dom/media/castable/types.ts
index 9de8c744f..4247357ec 100644
--- a/packages/core/src/dom/media/castable/types.ts
+++ b/packages/core/src/dom/media/castable/types.ts
@@ -2,7 +2,21 @@ import type { RemotePlaybackLike } from '../predicate';
import type { RemotePlayback } from './remote-playback';
import type { CastOptions } from './utils';
-export interface CastableMediaBase extends EventTarget {
+export interface CastableMediaProps {
+ castReceiver: string | undefined;
+ castContentType: string | undefined;
+ castStreamType: string | undefined;
+ castCustomData: Record | null | undefined;
+}
+
+export const castableMediaDefaultProps: CastableMediaProps = {
+ castReceiver: undefined,
+ castContentType: undefined,
+ castStreamType: undefined,
+ castCustomData: undefined,
+};
+
+export interface CastableMediaHost extends EventTarget {
readonly target: HTMLMediaElement | null;
readonly remote: RemotePlaybackLike | undefined;
title: string;
@@ -32,20 +46,16 @@ export interface CastableMediaBase extends EventTarget {
querySelector(selectors: K): HTMLElementTagNameMap[K] | null;
}
-export interface CastableMediaProps {
+export interface CastableMedia extends CastableMediaProps {
readonly remote: RemotePlayback | RemotePlaybackLike | undefined;
readonly castOptions: CastOptions;
- castReceiver: string | undefined;
castSrc: string;
- castContentType: string | undefined;
- castStreamType: string | undefined;
- castCustomData: Record | null | undefined;
poster: string;
title: string;
}
-export type CastableMediaElement = CastableMediaBase & CastableMediaProps;
+export type CastableMediaElement = CastableMediaHost & CastableMedia;
-export interface CastableMediaSuperclass {
- new (...args: any[]): CastableMediaBase;
+export interface CastableMediaHostConstructor {
+ new (...args: any[]): CastableMediaHost;
}
diff --git a/packages/core/src/dom/media/dash/index.ts b/packages/core/src/dom/media/dash/index.ts
index dd05f35bf..68dfac5e8 100644
--- a/packages/core/src/dom/media/dash/index.ts
+++ b/packages/core/src/dom/media/dash/index.ts
@@ -2,12 +2,20 @@ import * as dashjs from 'dashjs';
import type { MediaEngineHost } from '../../../core/media/types';
import { HTMLVideoElementHost } from '../video-host';
+export interface DashMediaProps {
+ src: string;
+}
+
+export const dashMediaDefaultProps: DashMediaProps = {
+ src: '',
+};
+
export class DashMedia
extends HTMLVideoElementHost
- implements MediaEngineHost
+ implements MediaEngineHost, DashMediaProps
{
#engine: dashjs.MediaPlayerClass;
- #src = '';
+ #src = dashMediaDefaultProps.src;
constructor() {
super();
diff --git a/packages/core/src/dom/media/hls/index.ts b/packages/core/src/dom/media/hls/index.ts
index dfea24387..78710268f 100644
--- a/packages/core/src/dom/media/hls/index.ts
+++ b/packages/core/src/dom/media/hls/index.ts
@@ -22,14 +22,32 @@ export const SourceTypes = {
MP4: 'video/mp4',
};
-export class HlsMedia extends HTMLVideoElementHost {
+export interface HlsMediaProps {
+ src: string;
+ type: SourceType | undefined;
+ preferPlayback: PlaybackType | undefined;
+ config: Record;
+ debug: boolean;
+ preload: PreloadType;
+}
+
+export const hlsMediaDefaultProps: HlsMediaProps = {
+ src: '',
+ type: undefined,
+ preferPlayback: 'mse',
+ config: {},
+ debug: false,
+ preload: 'metadata',
+};
+
+export class HlsMedia extends HTMLVideoElementHost implements HlsMediaProps {
#delegate: HlsJsMedia | NativeHlsMedia | null = null;
- #src = '';
- #type: SourceType | undefined;
- #preferPlayback: PlaybackType | undefined = 'mse';
- #config: Record = {};
- #debug = false;
- #preload: PreloadType = 'metadata';
+ #src = hlsMediaDefaultProps.src;
+ #type = hlsMediaDefaultProps.type;
+ #preferPlayback = hlsMediaDefaultProps.preferPlayback;
+ #config = { ...hlsMediaDefaultProps.config };
+ #debug = hlsMediaDefaultProps.debug;
+ #preload = hlsMediaDefaultProps.preload;
#loadRequested?: Promise | null;
#prevEngineProps?: Record | null;
diff --git a/packages/core/src/dom/media/mux/index.ts b/packages/core/src/dom/media/mux/index.ts
index e42432427..0fbdf8a12 100644
--- a/packages/core/src/dom/media/mux/index.ts
+++ b/packages/core/src/dom/media/mux/index.ts
@@ -1,14 +1,28 @@
import { CastableMediaMixin } from '../castable';
-import { HlsMedia } from '../hls';
-import { MuxDataMediaMixin } from './mux-data';
+import { type CastableMediaProps, castableMediaDefaultProps } from '../castable/types';
+import { HlsMedia, type HlsMediaProps, hlsMediaDefaultProps } from '../hls';
+import { MuxDataMediaMixin, type MuxDataMediaProps, muxDataMediaDefaultProps } from './mux-data';
-export class MuxVideoMedia extends MuxDataMediaMixin(CastableMediaMixin(HlsMedia)) {
+export type { CastableMediaProps, HlsMediaProps, MuxDataMediaProps };
+
+export interface MuxMediaProps extends HlsMediaProps, CastableMediaProps, MuxDataMediaProps {
+ castSrc: string | undefined;
+}
+
+export const muxMediaDefaultProps: MuxMediaProps = {
+ ...hlsMediaDefaultProps,
+ ...castableMediaDefaultProps,
+ ...muxDataMediaDefaultProps,
+ castSrc: undefined,
+};
+
+export class MuxVideoMedia extends MuxDataMediaMixin(CastableMediaMixin(HlsMedia)) implements MuxMediaProps {
static PLAYER_SOFTWARE_NAME = 'mux-video';
}
// TODO: HlsMedia extends HTMLVideoElementHost, we should extend
// HTMLAudioElementHost instead but this would require a HlsMediaMixin,
// keep it simple for now.
-export class MuxAudioMedia extends MuxDataMediaMixin(CastableMediaMixin(HlsMedia)) {
+export class MuxAudioMedia extends MuxDataMediaMixin(CastableMediaMixin(HlsMedia)) implements MuxMediaProps {
static PLAYER_SOFTWARE_NAME = 'mux-audio';
}
diff --git a/packages/core/src/dom/media/mux/mux-data.ts b/packages/core/src/dom/media/mux/mux-data.ts
index 69157a597..26dc07d71 100644
--- a/packages/core/src/dom/media/mux/mux-data.ts
+++ b/packages/core/src/dom/media/mux/mux-data.ts
@@ -5,15 +5,6 @@ import { Hls, type HlsMedia } from '../hls';
import { getPlayerVersion } from './env';
import type { MuxDataOptions, MuxDataSdk } from './types';
-const MUX_VIDEO_DOMAIN = 'mux.com';
-
-export interface MuxDataMediaHost extends MediaEngineHost {
- readonly debug: boolean;
- attach(target: HTMLMediaElement): void;
- detach(): void;
- load(): void;
-}
-
export interface MuxDataMediaProps {
MuxDataSdk: MuxDataSdk | undefined;
beaconCollectionDomain: string | undefined;
@@ -25,6 +16,26 @@ export interface MuxDataMediaProps {
metadata: MuxDataOptions['data'] | undefined;
}
+export const muxDataMediaDefaultProps: MuxDataMediaProps = {
+ MuxDataSdk: undefined,
+ beaconCollectionDomain: undefined,
+ disableCookies: false,
+ envKey: undefined,
+ playerSoftwareName: undefined,
+ playerSoftwareVersion: undefined,
+ playerInitTime: undefined,
+ metadata: undefined,
+};
+
+const MUX_VIDEO_DOMAIN = 'mux.com';
+
+export interface MuxDataMediaHost extends MediaEngineHost {
+ readonly debug: boolean;
+ attach(target: HTMLMediaElement): void;
+ detach(): void;
+ load(): void;
+}
+
export const MuxDataMediaMixin: Mixin = (BaseClass) => {
class MuxDataMedia extends BaseClass {
#MuxDataSdk: MuxDataSdk | undefined = Mux;
diff --git a/packages/core/src/dom/media/native-hls/index.ts b/packages/core/src/dom/media/native-hls/index.ts
index 7513d5409..955b3588c 100644
--- a/packages/core/src/dom/media/native-hls/index.ts
+++ b/packages/core/src/dom/media/native-hls/index.ts
@@ -3,9 +3,19 @@ import { NativeHlsMediaErrorsMixin } from './errors';
export type PreloadType = '' | 'none' | 'metadata' | 'auto';
-class NativeHlsMediaBase extends HTMLVideoElementHost {
- #src = '';
- #preload: PreloadType = 'metadata';
+export interface NativeHlsMediaProps {
+ src: string;
+ preload: PreloadType;
+}
+
+export const nativeHlsMediaDefaultProps: NativeHlsMediaProps = {
+ src: '',
+ preload: 'metadata',
+};
+
+class NativeHlsMediaBase extends HTMLVideoElementHost implements NativeHlsMediaProps {
+ #src = nativeHlsMediaDefaultProps.src;
+ #preload = nativeHlsMediaDefaultProps.preload;
get engine() {
return null;
diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts
index f75ce4c63..64c5e02b1 100644
--- a/packages/react/src/index.ts
+++ b/packages/react/src/index.ts
@@ -67,13 +67,11 @@ export { Time } from './ui/time';
export { TimeSlider } from './ui/time-slider';
export { Tooltip, type TooltipContextValue, useTooltipContext } from './ui/tooltip';
export { VolumeSlider } from './ui/volume-slider';
-
-// Media utilities
-export { attachMediaElement } from './utils/attach-media-element';
-export { mediaProps } from './utils/media-props';
// Utilities
export { mergeProps } from './utils/merge-props';
export type { HTMLProps, RenderFunction, RenderProp, UIComponentProps } from './utils/types';
+// Media utilities
+export { useAttachMedia } from './utils/use-attach-media';
export { composeRefs, useComposedRefs } from './utils/use-composed-refs';
export { useDestroy } from './utils/use-destroy';
export { useLatestRef } from './utils/use-latest-ref';
diff --git a/packages/react/src/media/dash-video/index.tsx b/packages/react/src/media/dash-video/index.tsx
index 73abf2f13..818f58483 100644
--- a/packages/react/src/media/dash-video/index.tsx
+++ b/packages/react/src/media/dash-video/index.tsx
@@ -1,24 +1,28 @@
'use client';
-import { DashMedia } from '@videojs/core/dom/media/dash';
-import type { InferClassProps } from '@videojs/utils/types';
-import type { PropsWithChildren, VideoHTMLAttributes } from 'react';
+import type { DashMediaProps } from '@videojs/core/dom/media/dash';
+import { DashMedia, dashMediaDefaultProps } from '@videojs/core/dom/media/dash';
+import type { ReactNode, VideoHTMLAttributes } from 'react';
import { forwardRef } from 'react';
-import { attachMediaElement } from '../../utils/attach-media-element';
-import { mediaProps } from '../../utils/media-props';
+import { useAttachMedia } from '../../utils/use-attach-media';
import { useComposedRefs } from '../../utils/use-composed-refs';
import { useMediaInstance } from '../../utils/use-media-instance';
+import { useSyncProps } from '../../utils/use-sync-props';
-export type DashVideoProps = PropsWithChildren> &
- InferClassProps;
+export interface DashVideoProps
+ extends Omit, keyof DashMediaProps>,
+ Partial {
+ children?: ReactNode;
+}
export const DashVideo = forwardRef(function DashVideo({ children, ...props }, ref) {
- const mediaApi = useMediaInstance(DashMedia);
-
- const composedRef = useComposedRefs(attachMediaElement(mediaApi), ref);
+ const media = useMediaInstance(DashMedia);
+ const attachRef = useAttachMedia(media);
+ const composedRef = useComposedRefs(attachRef, ref);
+ const htmlProps = useSyncProps(media, props, dashMediaDefaultProps);
return (
-