Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PLAT-80843: Add Shaka Video Player sample #81

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions pattern-shaka-video-player/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.

# dependencies
node_modules

# testing
coverage

# production
build
dist

# misc
.DS_Store
npm-debug.log
9 changes: 9 additions & 0 deletions pattern-shaka-video-player/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
## Shaka Video Player pattern

A sample Enact application that demonstrates how to use [shaka-player](https://shaka-player-demo.appspot.com/docs/api/index.html).

Run `npm install` then `npm run serve` to have the app running on [http://localhost:8080](http://localhost:8080), where you can view it in your browser.

---

This project was bootstrapped with the Enact [cli](https://github.com/enactjs/cli).
43 changes: 43 additions & 0 deletions pattern-shaka-video-player/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "shaka-app",
"version": "1.0.0",
"description": "A general template for an Enact Moonstone application.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's update the description for completeness

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:yougotitdude:

"author": "",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Want to add your name here, Teck?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:okay:

"main": "src/index.js",
"scripts": {
"serve": "enact serve",
"pack": "enact pack",
"pack-p": "enact pack -p",
"watch": "enact pack --watch",
"clean": "enact clean",
"lint": "enact lint .",
"license": "enact license",
"test": "enact test",
"test-watch": "enact test --watch"
},
"license": "UNLICENSED",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make this apache like our others.

"private": true,
"repository": "",
"enact": {
"theme": "moonstone"
},
"eslintConfig": {
"extends": "enact"
},
"eslintIgnore": [
"node_modules/*",
"build/*",
"dist/*"
],
"dependencies": {
"@enact/core": "^2.0.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we update to 3.x? Add ilib? Update React?

"@enact/i18n": "^2.0.0",
"@enact/moonstone": "^2.0.0",
"@enact/spotlight": "^2.0.0",
"@enact/ui": "^2.0.0",
"prop-types": "^15.6.2",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"shaka-player": "^2.5.2"
}
}
3 changes: 3 additions & 0 deletions pattern-shaka-video-player/resources/ilibmanifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"files": []
}
27 changes: 27 additions & 0 deletions pattern-shaka-video-player/src/App/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import kind from '@enact/core/kind';
import MoonstoneDecorator from '@enact/moonstone/MoonstoneDecorator';
import Panels from '@enact/moonstone/Panels';
import React from 'react';

import MainPanel from '../views/MainPanel';

import css from './App.module.less';

const App = kind({
name: 'App',

styles: {
css,
className: 'app'
},

render: (props) => (
<div {...props}>
<Panels>
<MainPanel />
</Panels>
</div>
)
});

export default MoonstoneDecorator(App);
3 changes: 3 additions & 0 deletions pattern-shaka-video-player/src/App/App.module.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.app {
// styles can be put here
}
3 changes: 3 additions & 0 deletions pattern-shaka-video-player/src/App/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"main": "App.js"
}
76 changes: 76 additions & 0 deletions pattern-shaka-video-player/src/components/ShakaVideoPlayer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import hoc from '@enact/core/hoc';
import VideoPlayer from "@enact/moonstone/VideoPlayer";
import React from 'react';
import PropTypes from 'prop-types';
import shaka from 'shaka-player';

function initPlayer(config, manifestUri) {
// Create a Player instance.
const video = document.querySelector('video');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discovered the issue with getVideoNode(). We abstracted access to the DOM node behind ui/Media so you have to do something like videoPlayer.getVideoNode().media to get all the way to the node.

I'm not sure we should expose that (it's not terrible but it isn't good either) but I think a "within React" impl (e.g. using findDOMNode() or the above code) would be better to show in a sample than querySelector. Wdyt?

const player = new shaka.Player(video);

// Listen for error events.
player.addEventListener('error', onErrorEvent);

// Try to load a manifest.
// This is an asynchronous process.
player
.load(manifestUri)
.then(function() {
// This runs if the asynchronous load is successful.
console.log('The video has now been loaded!');
})
.catch(onError); // onError is executed if the asynchronous load fails.
// Configure player
player.configure(config);
}

function onErrorEvent(event) {
// Extract the shaka.util.Error object from the event.
onError(event.detail);
}

function onError(error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make this a bit more React-y by moving these handlers into the component and invoking callbacks via props as usual. Could then move the console.error into the app instead of here.

// Log the error.
console.error('Error code', error.code, 'object', error);
}

const defaultConfig = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these be runtime props vs design time configs?

preferredAudioLanguage: 'en-US',
playRangeStart: 420
};

const ShakaPlayerDecorator = hoc(defaultConfig, (config, Wrapped) => {
return class extends React.Component {
static displayName = 'ShakaPlayerDecorator';

static propTypes = {
manifestUri: PropTypes.string
};

componentDidMount () {
// Install built-in polyfills to patch browser incompatibilities.
shaka.polyfill.installAll();

// Check to see if the browser supports the basic APIs Shaka needs.
if (shaka.Player.isBrowserSupported()) {
// Everything looks good!
initPlayer(config, this.props.manifestUri);
} else {
// This browser does not have the minimum set of APIs we need.
console.error('Browser not supported!');
}
}

render () {
const props = Object.assign({}, this.props);
delete props.manifestUri;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spacing


return <Wrapped {...props} />
}
}
});

const ShakaVideoPlayer = ShakaPlayerDecorator(VideoPlayer);

export default ShakaVideoPlayer;
12 changes: 12 additions & 0 deletions pattern-shaka-video-player/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import {render} from 'react-dom';
import App from './App';

const appElement = (<App />);

// In a browser environment, render instead of exporting
if (typeof window !== 'undefined') {
render(appElement, document.getElementById('root'));
}

export default appElement;
19 changes: 19 additions & 0 deletions pattern-shaka-video-player/src/views/MainPanel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import kind from '@enact/core/kind';
import {Panel, Header} from '@enact/moonstone/Panels';
import React from 'react';
import ShakaVideoPlayer from '../components/ShakaVideoPlayer';

const sintelManifestUri = 'https://storage.googleapis.com/shaka-demo-assets/sintel/dash.mpd';

const MainPanel = kind({
name: 'MainPanel',

render: (props) => (
<Panel {...props}>
<Header title="VideoPlayer" titleBelow="powered by Shaka Player" />
<ShakaVideoPlayer autoPlay manifestUri={sintelManifestUri} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

autoPlay doesn't seem to be working. Are you seeing the same?

</Panel>
)
});

export default MainPanel;