@mottosports/motto-video-player 1.0.1-rc.23 → 1.0.1-rc.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -109,9 +109,9 @@ interface IconSizes {
109
109
  }
110
110
  interface PlayerProps extends Omit<HTMLAttributes<HTMLVideoElement>, 'src' | 'onError'> {
111
111
  /**
112
- * The source URL of the video (DASH, HLS, or regular MP4)
112
+ * The source URL of the video (DASH, HLS, or regular MP4) or playlist object with DRM info
113
113
  */
114
- src: string;
114
+ src: string | any;
115
115
  /**
116
116
  * Whether the video should autoplay
117
117
  */
@@ -151,7 +151,7 @@ interface PlayerProps extends Omit<HTMLAttributes<HTMLVideoElement>, 'src' | 'on
151
151
  */
152
152
  shakaConfig?: any;
153
153
  /**
154
- * DRM configuration for protected content
154
+ * DRM configuration for protected content (deprecated - now derived from src playlist)
155
155
  */
156
156
  drmConfig?: {
157
157
  clearKeys?: {
@@ -349,6 +349,28 @@ interface VideoData {
349
349
  }>;
350
350
  error?: string;
351
351
  }
352
+ interface DRMSettings {
353
+ window_size_seconds: number;
354
+ }
355
+ interface Widevine {
356
+ playlist_url: string;
357
+ license_url: string;
358
+ }
359
+ interface Fairplay {
360
+ certificate_url: string;
361
+ license_url: string;
362
+ playlist_url: string;
363
+ }
364
+ interface Playready {
365
+ playlist_url: string;
366
+ license_url: string;
367
+ }
368
+ interface DRM {
369
+ token?: string;
370
+ widevine?: Widevine;
371
+ fairplay?: Fairplay;
372
+ playready?: Playready;
373
+ }
352
374
  interface VideoListItem {
353
375
  id: string;
354
376
  name?: string;
@@ -356,6 +378,8 @@ interface VideoListItem {
356
378
  playlists?: Array<{
357
379
  url: string;
358
380
  format: string;
381
+ dvr_settings: DRMSettings;
382
+ dvr: DRM;
359
383
  }>;
360
384
  error?: string;
361
385
  }
@@ -427,7 +451,7 @@ interface VideoProps extends Omit<PlayerProps, 'src'> {
427
451
  }
428
452
  declare const Video: React.FC<VideoProps>;
429
453
 
430
- interface EventProps extends Omit<PlayerProps, 'src'> {
454
+ interface EventProps extends Omit<PlayerProps, 'src' | 'drmConfig'> {
431
455
  publicKey: string;
432
456
  eventId: string;
433
457
  hideTitle?: boolean;
package/dist/index.d.ts CHANGED
@@ -109,9 +109,9 @@ interface IconSizes {
109
109
  }
110
110
  interface PlayerProps extends Omit<HTMLAttributes<HTMLVideoElement>, 'src' | 'onError'> {
111
111
  /**
112
- * The source URL of the video (DASH, HLS, or regular MP4)
112
+ * The source URL of the video (DASH, HLS, or regular MP4) or playlist object with DRM info
113
113
  */
114
- src: string;
114
+ src: string | any;
115
115
  /**
116
116
  * Whether the video should autoplay
117
117
  */
@@ -151,7 +151,7 @@ interface PlayerProps extends Omit<HTMLAttributes<HTMLVideoElement>, 'src' | 'on
151
151
  */
152
152
  shakaConfig?: any;
153
153
  /**
154
- * DRM configuration for protected content
154
+ * DRM configuration for protected content (deprecated - now derived from src playlist)
155
155
  */
156
156
  drmConfig?: {
157
157
  clearKeys?: {
@@ -349,6 +349,28 @@ interface VideoData {
349
349
  }>;
350
350
  error?: string;
351
351
  }
352
+ interface DRMSettings {
353
+ window_size_seconds: number;
354
+ }
355
+ interface Widevine {
356
+ playlist_url: string;
357
+ license_url: string;
358
+ }
359
+ interface Fairplay {
360
+ certificate_url: string;
361
+ license_url: string;
362
+ playlist_url: string;
363
+ }
364
+ interface Playready {
365
+ playlist_url: string;
366
+ license_url: string;
367
+ }
368
+ interface DRM {
369
+ token?: string;
370
+ widevine?: Widevine;
371
+ fairplay?: Fairplay;
372
+ playready?: Playready;
373
+ }
352
374
  interface VideoListItem {
353
375
  id: string;
354
376
  name?: string;
@@ -356,6 +378,8 @@ interface VideoListItem {
356
378
  playlists?: Array<{
357
379
  url: string;
358
380
  format: string;
381
+ dvr_settings: DRMSettings;
382
+ dvr: DRM;
359
383
  }>;
360
384
  error?: string;
361
385
  }
@@ -427,7 +451,7 @@ interface VideoProps extends Omit<PlayerProps, 'src'> {
427
451
  }
428
452
  declare const Video: React.FC<VideoProps>;
429
453
 
430
- interface EventProps extends Omit<PlayerProps, 'src'> {
454
+ interface EventProps extends Omit<PlayerProps, 'src' | 'drmConfig'> {
431
455
  publicKey: string;
432
456
  eventId: string;
433
457
  hideTitle?: boolean;
package/dist/index.js CHANGED
@@ -1149,7 +1149,7 @@ var import_shaka_player4 = __toESM(require("shaka-player/dist/shaka-player.ui"))
1149
1149
 
1150
1150
  // src/hooks/useShakePlayer.ts
1151
1151
  var import_react = require("react");
1152
- var import_shaka_player = require("shaka-player/dist/shaka-player.ui");
1152
+ var import_shaka_player = __toESM(require("shaka-player/dist/shaka-player.ui"));
1153
1153
  var useShakePlayer = ({
1154
1154
  src,
1155
1155
  shakaConfig,
@@ -1160,16 +1160,70 @@ var useShakePlayer = ({
1160
1160
  const playerRef = (0, import_react.useRef)(null);
1161
1161
  const initializePlayer = (0, import_react.useCallback)(async (video) => {
1162
1162
  try {
1163
- import_shaka_player.polyfill.installAll();
1164
- if (!import_shaka_player.Player.isBrowserSupported()) {
1163
+ import_shaka_player.default.polyfill.installAll();
1164
+ if (!import_shaka_player.default.Player.isBrowserSupported()) {
1165
1165
  throw new Error("Browser not supported by Shaka Player");
1166
1166
  }
1167
- const player = new import_shaka_player.Player();
1167
+ const player = new import_shaka_player.default.Player();
1168
1168
  playerRef.current = player;
1169
1169
  await player.attach(video);
1170
1170
  if (shakaConfig) {
1171
1171
  player.configure(shakaConfig);
1172
1172
  }
1173
+ const isPlaylistObject = typeof src === "object" && src !== null && src.dvr;
1174
+ const manifestUrl = isPlaylistObject ? src.url : src;
1175
+ const drmData = isPlaylistObject ? src.dvr : null;
1176
+ if (drmData && drmData.token) {
1177
+ const isAppleDevice2 = () => {
1178
+ if (typeof navigator === "undefined") return false;
1179
+ const ua = navigator.userAgent || "";
1180
+ const isIOS = /iPad|iPhone|iPod/.test(ua) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
1181
+ const isSafari = /Safari/.test(ua) && !/Chrome|CriOS|FxiOS|Edg/.test(ua);
1182
+ const isMacSafari = /Macintosh/.test(ua) && isSafari;
1183
+ return isIOS || isMacSafari;
1184
+ };
1185
+ const useFairPlay = isAppleDevice2();
1186
+ const drmConfig2 = {
1187
+ servers: {},
1188
+ advanced: {}
1189
+ };
1190
+ if (useFairPlay && drmData.fairplay?.license_url) {
1191
+ drmConfig2.servers["com.apple.fps"] = drmData.fairplay.license_url;
1192
+ } else if (drmData.widevine?.license_url) {
1193
+ drmConfig2.servers["com.widevine.alpha"] = drmData.widevine.license_url;
1194
+ }
1195
+ if (useFairPlay && drmData.fairplay?.certificate_url) {
1196
+ try {
1197
+ const req = await fetch(drmData.fairplay.certificate_url);
1198
+ const cert = await req.arrayBuffer();
1199
+ drmConfig2.advanced["com.apple.fps"] = {
1200
+ serverCertificate: new Uint8Array(cert)
1201
+ };
1202
+ } catch (e) {
1203
+ console.warn("Failed to fetch FairPlay certificate:", e);
1204
+ }
1205
+ }
1206
+ if (Object.keys(drmConfig2.servers).length > 0) {
1207
+ player.configure({ drm: drmConfig2 });
1208
+ }
1209
+ const netEngine = player.getNetworkingEngine();
1210
+ if (netEngine) {
1211
+ netEngine.registerRequestFilter((type, request) => {
1212
+ if (type === import_shaka_player.default.net.NetworkingEngine.RequestType.LICENSE) {
1213
+ request.headers["x-dt-custom-data"] = drmData.token;
1214
+ }
1215
+ });
1216
+ netEngine.registerResponseFilter((type, response) => {
1217
+ if (type === import_shaka_player.default.net.NetworkingEngine.RequestType.LICENSE) {
1218
+ const ks = player.keySystem && player.keySystem();
1219
+ if (ks === "com.apple.fps") {
1220
+ const responseText = import_shaka_player.default.util.StringUtils.fromUTF8(response.data);
1221
+ response.data = import_shaka_player.default.util.Uint8ArrayUtils.fromBase64(responseText).buffer;
1222
+ }
1223
+ }
1224
+ });
1225
+ }
1226
+ }
1173
1227
  if (drmConfig) {
1174
1228
  if (drmConfig.clearKeys) {
1175
1229
  player.configure({ "drm.clearKeys": drmConfig.clearKeys });
@@ -1186,7 +1240,7 @@ var useShakePlayer = ({
1186
1240
  console.error("Shaka Player Error:", error);
1187
1241
  onError?.(new Error(`Shaka Player Error: ${error.message || "Unknown error"}`));
1188
1242
  });
1189
- await player.load(src);
1243
+ await player.load(manifestUrl);
1190
1244
  onPlayerReady?.(player);
1191
1245
  return player;
1192
1246
  } catch (error) {
@@ -1336,7 +1390,7 @@ var import_mux_data_shakaplayer = __toESM(require("@mux/mux-data-shakaplayer"));
1336
1390
  var import_shaka_player2 = __toESM(require("shaka-player/dist/shaka-player.ui"));
1337
1391
 
1338
1392
  // package.json
1339
- var version = "1.0.1-rc.23";
1393
+ var version = "1.0.1-rc.24";
1340
1394
 
1341
1395
  // src/hooks/useMuxAnalytics.ts
1342
1396
  var useMuxAnalytics = (playerRef, muxConfig, onMuxReady, onMuxDataUpdate) => {
@@ -4025,6 +4079,14 @@ var import_react15 = require("react");
4025
4079
  var import_tailwind_merge4 = require("tailwind-merge");
4026
4080
  var import_react_query2 = require("@tanstack/react-query");
4027
4081
  var import_jsx_runtime10 = require("react/jsx-runtime");
4082
+ var isAppleDevice = () => {
4083
+ if (typeof navigator === "undefined") return false;
4084
+ const ua = navigator.userAgent || navigator.vendor || "";
4085
+ const isIOS = /iPad|iPhone|iPod/.test(ua) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
4086
+ const isSafari = /Safari/.test(ua) && !/Chrome|CriOS|FxiOS|Edg/.test(ua);
4087
+ const isMacSafari = /Macintosh/.test(ua) && isSafari;
4088
+ return isIOS || isMacSafari;
4089
+ };
4028
4090
  var Event = ({
4029
4091
  publicKey,
4030
4092
  eventId,
@@ -4057,6 +4119,7 @@ var Event = ({
4057
4119
  const [activePlaylist, setActivePlaylist] = (0, import_react15.useState)();
4058
4120
  const [activeVideoId, setActiveVideoId] = (0, import_react15.useState)();
4059
4121
  const videoIds = eventData?.videoIds ?? [];
4122
+ const [isDRM, setIsDRM] = (0, import_react15.useState)(false);
4060
4123
  const {
4061
4124
  data: videosData,
4062
4125
  isLoading: videosIsLoading,
@@ -4083,9 +4146,34 @@ var Event = ({
4083
4146
  for (const video of videosWithPlaylists) {
4084
4147
  const hlsPlaylist = findHLSPlaylist(video);
4085
4148
  if (hlsPlaylist?.url) {
4086
- setActivePlaylist(hlsPlaylist.url);
4149
+ const matchedPlaylist = video.playlists?.find((p) => p.url === hlsPlaylist.url);
4150
+ const drm = matchedPlaylist?.dvr;
4151
+ const hasDrm = Boolean(drm?.token);
4152
+ let selectedPlaylist;
4153
+ if (hasDrm) {
4154
+ const useFairPlay = isAppleDevice();
4155
+ if (useFairPlay && drm?.fairplay?.playlist_url && drm?.fairplay?.license_url) {
4156
+ selectedPlaylist = {
4157
+ url: drm.fairplay.playlist_url,
4158
+ format: matchedPlaylist?.format || "HLS",
4159
+ dvr: drm
4160
+ };
4161
+ } else if (drm?.widevine?.playlist_url && drm?.widevine?.license_url) {
4162
+ selectedPlaylist = {
4163
+ url: drm.widevine.playlist_url,
4164
+ format: matchedPlaylist?.format || "HLS",
4165
+ dvr: drm
4166
+ };
4167
+ } else {
4168
+ selectedPlaylist = matchedPlaylist;
4169
+ }
4170
+ } else {
4171
+ selectedPlaylist = hlsPlaylist.url;
4172
+ }
4173
+ setActivePlaylist(selectedPlaylist);
4087
4174
  setActiveVideoId(video.id);
4088
4175
  hlsPlaylistFound = true;
4176
+ setIsDRM(Boolean(hasDrm));
4089
4177
  break;
4090
4178
  }
4091
4179
  }
@@ -4109,6 +4197,11 @@ var Event = ({
4109
4197
  events.onEventData(eventData);
4110
4198
  }
4111
4199
  }, [eventData, events]);
4200
+ (0, import_react15.useEffect)(() => {
4201
+ if (isDRM) {
4202
+ console.log("DRM is enabled");
4203
+ }
4204
+ }, [isDRM]);
4112
4205
  (0, import_react15.useEffect)(() => {
4113
4206
  if (events?.onVideoData && activeVideoId && videosData) {
4114
4207
  const activeVideo = videosData.find((video) => video.id === activeVideoId);