Skip to content

Instantly share code, notes, and snippets.

@AlexFrazer
Created July 11, 2017 15:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AlexFrazer/6d6b7bbd2e27d628219405ed171f3365 to your computer and use it in GitHub Desktop.
Save AlexFrazer/6d6b7bbd2e27d628219405ed171f3365 to your computer and use it in GitHub Desktop.
/**
* Provides the type definitions for JWPlayer@7.7.4
*/
// https://developer.jwplayer.com/jw-player/docs/developer-guide/customization/configuration-reference/#setup
// https://stackoverflow.com/questions/45019375/webpack-typescript-property-jwplayer-does-not-exist-on-type-window-when
interface Window {
jwplayer: any,
}
interface Track {
file: string,
kind: string,
label: string,
default: string,
}
interface AdSchedule {
offset: number|string,
tag: string,
}
interface Skin {
name: string,
active: string,
inactive: string,
background: string,
url: string,
}
interface Captions {
color: string,
fontSize: number,
fontFamily: string,
fontOpacity: number,
backgroundColor: string,
backgroundOpacity: number,
edgeStyle: string,
windowColor: string,
windowOpacity: number,
}
interface PlayListItem {
file: string,
withCredentials: boolean,
title: string,
description: string,
image: string,
mediaid: string,
recommendations: string,
minDvrWindow: number,
stereomode: string,
sources: Array<string>,
tracks: Array<Track>,
adschedule: Array<AdSchedule>,
}
interface RTMP {
bufferlength: number,
subscribe: boolean,
securetoken: string,
}
interface Logo {
file: string,
hide: boolean,
link: string,
margin: number,
position: 'top-left'|'top-right'|'bottom-left'|'bottom-right',
}
interface Sharing {
link: string,
code: string,
heading: string,
sites: Array<string>,
}
interface GoogleAnalytics {
label: string,
}
interface Related {
file: string,
oncomplete: string,
heading: string,
autoplaytimer: number,
autoplaymessage: string,
}
interface Advertising {
client: string,
tag: string,
admessage: string,
skipoffset: number,
cuetext: string,
skipmessage: string,
skiptext: string,
vpaidmode: string,
schedule: string|AdSchedule,
companiondiv: HTMLDivElement,
autoplayadsmuted: boolean,
enablepreloading: boolean,
vpaidcontrols: boolean,
forceNonLinearFullSlot: boolean,
setLocal: string,
creativeTimeout: string,
requestTimeout: string,
}
interface Headers {
name: string,
value: string,
}
interface PlayReady {
url: string,
headers: Array<Headers>,
}
interface WideVine {
url: string,
serverCertificateUrl: string,
headers: Array<Headers>,
}
interface FairPlay {
certificateUrl: string,
processSpcUrl: string,
extractContentId: (initData: string) => string,
licenseRequestHeaders: Array<Headers>,
licenseResponseType: string,
licenseRequestMessage: (licenseKey: string) => string,
extractKey: (ckc: string) => Promise<string>
}
declare interface ClearKey {
key: string,
keyId: string,
}
declare interface DRM {
playready: PlayReady,
widevine: WideVine,
fairplay: FairPlay,
clearkey: ClearKey,
}
declare interface Localization {
nextUp: string,
playlist: string,
related: string,
}
declare enum PlayState { 'buffering', 'playing', 'paused', 'idle' }
declare enum BufferReason { 'loading', 'complete', 'stalled', 'error' }
declare enum Client { 'vast', 'googima' }
interface BufferChangeEvent {
duration: number,
bufferPercent: number,
position: number,
metadata: {
bandwidth: number,
droppedFrames: number
}
}
interface QualityLevels {
bitrate: number,
height: number,
width: number,
label: string,
}
interface AudioTracks {
autoselect: boolean,
defaulttrack: boolean,
language: string,
name: string,
}
interface PlayPauseEvent {
oldstate: PlayState,
viewable?: number,
reason?: BufferReason,
}
interface FirstFrameEvent {
loadTime: number,
viewable: number,
}
interface PlayListItemEvent {
index: number,
item: PlayListItem,
}
interface PlaybackRateEvent {
playbackRate: number,
position: number,
}
interface SeekEvent {
position: number,
offset: number,
}
interface TimeEvent {
duration: number,
position: number,
viewable: number,
}
interface AdClickEvent {
client: Client,
creativetype: string,
tag: string,
}
interface Events {
onAll: () => void,
onViewable: () => void,
onReady: () => void,
onSetupError: () => void,
onPlaylist: () => void,
onPlaylistItem: (e: PlayListItemEvent) => void,
onPlaylistComplete: () => void,
onBufferChange: (e: BufferChangeEvent) => void,
onPlay: (e: PlayPauseEvent) => void,
onPause: (e: PlayPauseEvent) => void,
onBuffer: (e: PlayPauseEvent) => void,
onIdle: (e: PlayPauseEvent) => void,
onComplete: () => void,
onFirstFrame: (e: FirstFrameEvent) => void,
onError(e: { message: string }): void,
onPlaybackRateChanged(e: PlaybackRateEvent): void,
onSeek(e: SeekEvent): void,
onSeeked(): void,
onTime: (e: TimeEvent) => void,
onMute: (e: { mute: boolean }) => void,
onVolume: (e: { volume: number }) => void,
onFullscreen: (e: { fullscreen: boolean }) => void,
onResize: (e: { width: number, height: number }) => void,
onLevels: (e: { width: number, levels: QualityLevels[] }) => void,
onLevelsChanged: (e: { currentQuality: number }) => void,
onVisualQuality(e: { mode: string, label: string, reason: string }): void,
onAudioTracks(e: { levels: Array<AudioTracks> }): void,
onAudioTrackChanged(e: { currentTrack: number }): void,
onCaptionsList(e: { tracks: Array<Captions> }): void,
onCaptionsChanged(e: { currentTrack: number }): void,
onControls(e: { state: boolean }): void,
onDisplayClick(): void,
onAdBlock(): void,
onBeforePlay(): void,
onBeforeComplete(): void,
onAdClick(e: AdClickEvent): void,
}
declare interface SetupConfig {
file: string,
image: string,
title: string,
description: string,
mediaid: string,
interval: number,
mute: boolean,
autostart: string,
nextupoffset: number,
repeat: boolean,
abouttext: string,
aboutlink: string,
playbackRateControls: boolean|Array<number>,
controls: boolean,
localization: {},
aspectratio: string,
height: number,
width: number,
displaytitle: string,
displaydescription: string,
stretching: 'uniform'|'exactfit'|'fill'|'none',
timeSliderAbove: boolean,
nextUpDisplay: boolean,
qualityLabels: Array<{}>,
primary: 'html5'|'flash',
flashplayer: string,
base: string,
preload: string,
skin: Skin,
logo: Logo,
captions: Captions,
playlist: Array<PlayListItem>,
rtmp: RTMP,
sharing: Sharing,
ga: GoogleAnalytics,
related: Related,
drm: DRM,
}
import * as React from 'react';
import 'lib/jwplayer-7.7.4/jwplayer.js';
interface Props extends SetupConfig, Events {};
interface EventMap {
[name: string]: (e: any) => void,
}
export default class ShiftPlayer extends React.Component<Props, {}> {
player: any = null;
container: HTMLDivElement = null;
componentDidMount() {
this.setup();
}
componentWillReceiveProps(nextProps: Props) {
if (nextProps.file !== this.props.file) {
this.player.remove();
this.setup(nextProps);
}
}
setup(props: Props = this.props) {
const {
onAll, onViewable, onReady, onSetupError, onPlaylist, onPlaylistItem,
onPlaylistComplete, onBufferChange, onPlay, onPause, onBuffer, onIdle,
onComplete, onFirstFrame, onError, onPlaybackRateChanged, onSeek,
onSeeked, onTime, onMute, onVolume, onFullscreen, onResize, onLevels,
onLevelsChanged, onVisualQuality, onAudioTracks, onAudioTrackChanged,
onCaptionsList, onCaptionsChanged, onControls, onDisplayClick,
onAdBlock, onBeforePlay, onBeforeComplete, onAdClick,
// whatever is leftover after removing the events is basically just configuration
...setupConfig,
} = props;
// the key is the name of the event (according to jwplayer)
// and the value is the handler name in React.
const events = {
all: onAll,
viewable: onViewable,
ready: onReady,
setupError: onSetupError,
playlist: onPlaylist,
playlistItem: onPlaylistItem,
playlistComplete: onPlaylistComplete,
bufferChange: onBufferChange,
play: onPlay,
pause: onPause,
buffer: onBuffer,
idle: onIdle,
complete: onComplete,
firstFrame: onFirstFrame,
error: onError,
playbackRateChanged: onPlaybackRateChanged,
seek: onSeek,
seeked: onSeeked,
time: onTime,
mute: onMute,
volume: onVolume,
fullscreen: onFullscreen,
resize: onResize,
levels: onLevels,
levelsChanged: onLevelsChanged,
visualQuality: onVisualQuality,
audioTracks: onAudioTracks,
audioTrackChanged: onAudioTrackChanged,
captionsList: onCaptionsList,
captionsChanged: onCaptionsChanged,
controls: onControls,
displayClick: onDisplayClick,
adBlock: onAdBlock,
beforePlay: onBeforePlay,
beforeComplete: onBeforeComplete,
adClick: onAdClick,
};
this.player = window.jwplayer(this.container).setup(setupConfig);
this.bindEventListeners(events);
}
bindEventListeners(events: EventMap = {}): void {
for (const name of Object.keys(events)) {
const handler = events[name];
if (event && handler) {
this.player.on(name, handler);
}
}
}
render() {
return (
<div
ref={(el) => { this.container = el; }}
/>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment