Skip to content

Instantly share code, notes, and snippets.

@bkwhite
Created July 15, 2022 15:15
Show Gist options
  • Save bkwhite/90a18f8269c94f0d27d7b9dc12db4f6a to your computer and use it in GitHub Desktop.
Save bkwhite/90a18f8269c94f0d27d7b9dc12db4f6a to your computer and use it in GitHub Desktop.
import React, { Component } from "react";
import ReactPlayer, { ReactPlayerProps } from "react-player";
import { getSDK } from "react-player/lib/utils";
import {
Player,
IkWidget,
KalturaNotificationName,
KalturaPlayerElement,
KalturaPlayerEvents,
} from "./types";
const FLASHVARS_REGEX = /(?:flashvars\[([\w.]*)\])/;
type KalturaPlayerState = {
targetId: string;
};
/**
* Custom player for `react-player` to play Kaltura videos using the kWidget API
*/
export class KalturaPlayer
extends Component<ReactPlayerProps, KalturaPlayerState>
implements Player
{
static displayName = "Kaltura";
/**
* Very basic check to see if the URL is a kaltura video. This can be replaced with
* `react-player`'s own `canPlay.kaltura`
*/
static canPlay(url: string) {
if (url.indexOf("kaltura.com") > -1) {
return true;
}
return false;
}
player: KalturaPlayerElement = null;
constructor(props: ReactPlayerProps) {
super(props);
this.state = {
targetId: `kaltura-${generateUUID()}`,
};
}
componentDidMount() {
this.props.onMount && this.props.onMount(this);
}
load() {
const { onReady, url } = this.props;
const partnerId = url.toString().match(/(?:partner_id\/)(\d+)/)[1];
const uiConfId = url.toString().match(/(?:uiconf_id\/)(\d+)/)[1];
const entryId = url.toString().match(/(?:entry_id[/|=])([^/&]+)/)[1];
/**
* "flashvars" should appear at the end of the url provided to this player.
*
* Example: &flashvars[mediaProxy.mediaPlayFrom]=10
*/
const urlParams = getQueryParams(url);
const flashvars = Object.keys(urlParams)
.filter((key) => key.match(FLASHVARS_REGEX))
.reduce(
(acc, key) => ({
...acc,
[key.match(FLASHVARS_REGEX)[1]]: urlParams[key],
}),
{}
);
const SDK_URL = `https://cdnapi.kaltura.com/p/${partnerId}/sp/${partnerId}00/embedIframeJs/uiconf_id/${uiConfId}/partner_id/${partnerId}`;
const SDK_GLOBAL = "kWidget";
getSDK(SDK_URL, SDK_GLOBAL).then((kWidget: IkWidget) => {
kWidget.embed(this.state.targetId, {
wid: `_${partnerId}`,
uiconf_id: uiConfId,
entry_id: entryId,
flashvars: {
...flashvars,
/**
* Makes things function nicely inside of an iOS WkWebView
*/
"EmbedPlayer.EnableIpadNativeFullscreen": true,
"EmbedPlayer.WebKitPlaysInline": true,
},
params: {},
readyCallback: () => {
const kdp = document.getElementById(
this.state.targetId
) as KalturaPlayerElement;
kdp.kBind(KalturaPlayerEvents.MEDIA_READY, () => {
this.player = kdp;
this.addEventListeners();
onReady(this as unknown as ReactPlayer);
});
},
});
});
}
addEventListeners() {
const { onBuffer, onPlay, onPause, onEnded } = this.props;
this.player.kBind(KalturaPlayerEvents.PLAYER_PLAY_END, onEnded);
this.player.kBind(KalturaPlayerEvents.PLAYER_PLAYED, onPlay);
this.player.kBind(KalturaPlayerEvents.PLAYER_PAUSED, onPause);
this.player.kBind(KalturaPlayerEvents.BUFFER_START_EVENT, onBuffer);
this.player.kBind(KalturaPlayerEvents.MEDIA_ERROR, (error) => {
console.error("Kaltura Media Error: ", error);
});
}
seekTo(amount: number) {
this.player.sendNotification(KalturaNotificationName.DO_SEEK, amount);
}
getCurrentTime() {
return Number(this.player.evaluate("{video.player.currentTime}"));
}
getDuration() {
return Number(this.player.evaluate("{duration}"));
}
getSecondsLoaded() {
const percentBuffered = this.player.evaluate(`{video.buffer.percent}`);
if (this.player) {
return this.getDuration() * Number(percentBuffered);
}
return null;
}
stop() {
this.player.sendNotification(KalturaNotificationName.DO_STOP);
}
render() {
return (
<div
style={{ width: "100%", height: "100%" }}
id={this.state.targetId}
></div>
);
}
}
function getQueryParams(qs) {
const params = {};
const re = /[?&]?([^=]+)=([^&]*)/g;
let tokens;
while ((tokens = re.exec(qs.split('+').join(' ')))) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
return params;
}
@bkwhite
Copy link
Author

bkwhite commented Jul 15, 2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment