Created
July 15, 2022 15:15
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Types: https://gist.github.com/bkwhite/1364b370bc220c5e66b2efd01d777712