Add id prop & autoplay handling, support DASH & HLS via Shaka Player

This commit is contained in:
Hampton Maxwell 2018-10-12 13:41:01 -07:00
parent 864da19d41
commit f0e0e555dd
3 changed files with 66 additions and 31 deletions

View File

@ -1,6 +1,7 @@
// @flow // @flow
import { RCTEvent, RCTView, type RCTBridge } from "react-native-dom"; import { RCTEvent, RCTView, type RCTBridge } from "react-native-dom";
import shaka from "shaka-player";
import resizeModes from "./resizeModes"; import resizeModes from "./resizeModes";
import type { VideoSource } from "./types"; import type { VideoSource } from "./types";
@ -25,6 +26,8 @@ class RCTVideo extends RCTView {
this.eventDispatcher = bridge.getModuleByName("EventDispatcher"); this.eventDispatcher = bridge.getModuleByName("EventDispatcher");
shaka.polyfill.installAll();
this.onEnd = this.onEnd.bind(this); this.onEnd = this.onEnd.bind(this);
this.onLoad = this.onLoad.bind(this); this.onLoad = this.onLoad.bind(this);
this.onLoadStart = this.onLoadStart.bind(this); this.onLoadStart = this.onLoadStart.bind(this);
@ -37,11 +40,11 @@ class RCTVideo extends RCTView {
this.videoElement.addEventListener("loadstart", this.onLoadStart); this.videoElement.addEventListener("loadstart", this.onLoadStart);
this.videoElement.addEventListener("pause", this.onPause); this.videoElement.addEventListener("pause", this.onPause);
this.videoElement.addEventListener("play", this.onPlay); this.videoElement.addEventListener("play", this.onPlay);
this.player = new shaka.Player(this.videoElement);
this.muted = false; this.muted = false;
this.rate = 1.0; this.rate = 1.0;
this.volume = 1.0; this.volume = 1.0;
this.videoElement.autoplay = true;
this.childContainer.appendChild(this.videoElement); this.childContainer.appendChild(this.videoElement);
} }
@ -71,36 +74,28 @@ class RCTVideo extends RCTView {
} }
presentFullscreenPlayer() { presentFullscreenPlayer() {
console.log("V PF");
this.videoElement.webkitRequestFullScreen(); this.videoElement.webkitRequestFullScreen();
} }
set controls(value: boolean) { set controls(value: boolean) {
if (value) { this.videoElement.controls = value;
this.videoElement.controls = true; this.videoElement.style.pointerEvents = value ? "auto" : "";
this.videoElement.style.pointerEvents = "auto"; }
} else {
this.videoElement.controls = false; set id(value: string) {
this.videoElement.style.pointerEvents = ""; this.videoElement.id = value;
}
} }
set muted(value: boolean) { set muted(value: boolean) {
if (value) { this.videoElement.muted = true;
this.videoElement.muted = true;
} else {
this.videoElement.muted = false;
}
} }
set paused(value: boolean) { set paused(value: boolean) {
this.playPromise.then(() => { if (value) {
if (value) { this.videoElement.pause();
this.videoElement.pause(); } else {
} else { this.requestPlay();
this.playPromise = this.videoElement.play(); }
}
});
this._paused = value; this._paused = value;
} }
@ -118,11 +113,7 @@ class RCTVideo extends RCTView {
} }
set repeat(value: boolean) { set repeat(value: boolean) {
if (value) { this.videoElement.loop = value;
this.videoElement.setAttribute("loop", "true");
} else {
this.videoElement.removeAttribute("loop");
}
} }
set resizeMode(value: number) { set resizeMode(value: number) {
@ -161,9 +152,19 @@ class RCTVideo extends RCTView {
uri = URL.createObjectURL(blob); uri = URL.createObjectURL(blob);
} }
this.videoElement.setAttribute("src", uri); if (!shaka.Player.isBrowserSupported()) { // primarily iOS WebKit
if (!this._paused) { this.videoElement.setAttribute("src", uri);
this.playPromise = this.videoElement.play(); if (!this._paused) {
this.requestPlay();
}
} else {
this.player.load(uri)
.then(() => {
if (!this._paused) {
this.requestPlay();
}
})
.catch(this.onError);
} }
} }
@ -182,6 +183,10 @@ class RCTVideo extends RCTView {
this.stopProgressTimer(); this.stopProgressTimer();
} }
onError = error => {
console.warn("topVideoError", error);
}
onLoad = () => { onLoad = () => {
// height & width are safe with audio, will be 0 // height & width are safe with audio, will be 0
const height = this.videoElement.videoHeight; const height = this.videoElement.videoHeight;
@ -223,6 +228,25 @@ class RCTVideo extends RCTView {
this.sendEvent("topVideoProgress", payload); this.sendEvent("topVideoProgress", payload);
} }
onRejectedAutoplay = () => {
this.sendEvent("topVideoRejectedAutoplay", null);
}
requestPlay() {
const playPromise = this.videoElement.play();
if (playPromise) {
playPromise
.then(() => {})
.catch(e => {
/* This is likely one of:
* name: NotAllowedError - autoplay is not supported
* name: NotSupportedError - format is not supported
*/
this.onError({ code: e.name, message: e.message });
});
}
}
sendEvent(eventName, payload) { sendEvent(eventName, payload) {
const event = new RCTVideoEvent(eventName, this.reactTag, 0, payload); const event = new RCTVideoEvent(eventName, this.reactTag, 0, payload);
this.eventDispatcher.sendEvent(event); this.eventDispatcher.sendEvent(event);

View File

@ -18,6 +18,7 @@ class RCTVideoManager extends RCTViewManager {
return super return super
.describeProps() .describeProps()
.addBooleanProp("controls", this.setControls) .addBooleanProp("controls", this.setControls)
.addStringProp("id", this.setId)
.addBooleanProp("muted", this.setMuted) .addBooleanProp("muted", this.setMuted)
.addBooleanProp("paused", this.setPaused) .addBooleanProp("paused", this.setPaused)
.addNumberProp("progressUpdateInterval", this.setProgressUpdateInterval) .addNumberProp("progressUpdateInterval", this.setProgressUpdateInterval)
@ -28,11 +29,16 @@ class RCTVideoManager extends RCTViewManager {
.addObjectProp("src", this.setSource) .addObjectProp("src", this.setSource)
.addNumberProp("volume", this.setVolume) .addNumberProp("volume", this.setVolume)
.addDirectEvent("onVideoEnd") .addDirectEvent("onVideoEnd")
.addDirectEvent("onVideoError")
.addDirectEvent("onVideoLoad") .addDirectEvent("onVideoLoad")
.addDirectEvent("onVideoLoadStart") .addDirectEvent("onVideoLoadStart")
.addDirectEvent("onVideoProgress"); .addDirectEvent("onVideoProgress");
} }
dismissFullscreenPlayer() {
// not currently working
}
presentFullscreenPlayer() { presentFullscreenPlayer() {
// not currently working // not currently working
} }
@ -41,6 +47,10 @@ class RCTVideoManager extends RCTViewManager {
view.controls = value; view.controls = value;
} }
setId(view: RCTVideo, value: string) {
view.id = value;
}
setMuted(view: RCTVideo, value: boolean) { setMuted(view: RCTVideo, value: boolean) {
view.muted = value; view.muted = value;
} }

View File

@ -35,7 +35,8 @@
}, },
"dependencies": { "dependencies": {
"keymirror": "0.1.1", "keymirror": "0.1.1",
"prop-types": "^15.5.10" "prop-types": "^15.5.10",
"shaka-player": "2.4.4"
}, },
"scripts": { "scripts": {
"test": "node_modules/.bin/eslint *.js" "test": "node_modules/.bin/eslint *.js"
@ -54,4 +55,4 @@
"react-native-video.podspec", "react-native-video.podspec",
"VideoResizeMode.js" "VideoResizeMode.js"
] ]
} }