Plyr is not a constructor - javascript

I've been struggling for a while to include a Plyr library (read & customise audio src) and I need to embed it via requireJS (important). all the other libraries work except this one, I wonder what's wrong!
Error: (console)
Uncaught TypeError: Plyr is not a constructor
Here is an example working without RequireJS, maybe it cool help.
JsFiddle
My JsFiddle example :
html:
<audio crossorigin playsinline>
<source src="https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3" type="audio/mp3">
<source src="https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg" type="audio/ogg">
</audio>
Js:
requirejs.config({
paths: {
jquery: 'https://code.jquery.com/jquery-3.6.3.min',
plyr: 'https://cdn.plyr.io/3.7.3/plyr'
},
shim: {
"plyr": {
deps: ["jquery"]
}
}
});
require(['jquery','plyr'], function($, Plyr) {
'use strict';
const player = new Plyr("audio", {});
window.player = player;
});

Related

component to play multiple audio files at the same time (on click) Aframe webVR

I am trying to find a way to reproduce the effect of having all my sound files in my A-frame vr project autoplay once the scene loads, but with an on-window-click function so that they are able to work on browsers that do not allow autoplay / require user interaction
i'm sure the solution is pretty simple but I have tried for quite a few hours and can't seem to find a solution online including stack anywhere. when I try to follow tutorials such as this, I can't get them to work:
Play sound on click in A-Frame
Autoplaying videosphere from A-frame is not working on any browser(Safari/Chrome)
in my html i have something like this (but with about 10 sound files and 10 models in total):
<a-assets>
<a-asset-item id="logo" src="code/to/gltf"></a-asset-item>
<a-asset-item id="logo" src="code/to/gltf"></a-asset-item>
<audio id="track" src="code/to/audio" crossOrigin="anonymous"></audio>
<audio id="track" src="code/to/audio" crossOrigin="anonymous"></audio>
</a-assets>
<a-entity
gltf-model="#logo"
play-audio
sound="
src: #track;
loop: true;
volume: 0.05;
distanceModel: inverse;
refDistance: 1000"
position="0 1.5 -2.5"
rotation="90 0 0"
scale="0.4 0.4 0.4"
foo>
</a-entity>
<a-entity
gltf-model="#bink"
navigate-on-click="url: bink.html"
play-audio
sound="
src: #binkaudio;
loop: true;
volume: 1;
distanceModel: inverse;
refDistance: 10"
position="-2.93 1.5 6"
rotation="90 149 0"
scale="0.4 0.4 0.4"
foo
></a-entity>
then in a separate js file linked into the html I have this
AFRAME.registerComponent('play-audio', {
init: function () {
this.onClick = this.onClick.bind(this);
},
play: function () {
window.addEventListener('click', this.onClick);
},
// pause: function () {
// window.removeEventListener('click', this.onClick);
// },
onClick: function (evt) {
var sceneEl = document.querySelector('a-scene')
var entity = sceneEl.querySelectorAll('[sounds]');
entity.components.sound.playSound();
}
});
EDIT
I keep recieveing this error message
Uncaught TypeError: Cannot read property 'sound' of undefined
at i.onClick (audiohandler.js:109)
at HTMLElement.emit (a-node.js:263)
at i.twoWayEmit (cursor.js:415)
at i.onCursorUp (cursor.js:271)
at HTMLCanvasElement.<anonymous> (bind.js:12)
EDIT
this was the final solution thank you !!!
AFRAME.registerComponent('play-audio', {
init: function () {
this.onClick = this.onClick.bind(this);
},
play: function () {
window.addEventListener('click', this.onClick);
},
pause: function () {
window.removeEventListener('click', this.onClick);
},
onClick: function (evt) {
let entity = document.querySelectorAll('[sound]');
for (let item of entity) {
item.components.sound.playSound();
}
}
});
If you want to grab all nodes that have the sound component, then you need to change your selector from sounds to sound - document.querySelectorAll('[sound]').
Also querySelectorAll will return a list of elements, so You have to iterate through them:
for (let item of list) {
item.components.sound.playSound()
}
This is fantastic and something I've been trying to figure out for a while. How could we adapt this component so that you had to click on once of the sound entities to start it (instead of clicking anywhere in the scene?)

How to play/pause video depending on visibility with jQuery

I want one or more videos to play/pause depending on whether or not they're in the viewport.
I understand this can be achieved with jQuery (and plugins), so I've tried using the isInViewport plugin along with the following code, but I receive the error shown below.
HTML
<script src="scripts/jquery.js"></script>
<script src="scripts/isInViewport.js"></script>
[...]
<video id="video1" src="file.mp4" width="50%"></video>
[...]
<script src="scripts/script.js"></script>
JS
var $video = document.getElementsByTagName("video1");
if ($video.is(":in-viewport")) {
$video.play();
} else {
$video.pause();
};
Console
TypeError: $video.is is not a function
try
$('video').each(function() {
if ($(this).is(":in-viewport")) {
$(this)[0].play();
} else {
$(this)[0].pause();
}
}
);

Custom HTML5 video player controls with AngularJS

I'm new with AngularJS. I must create customs controls for a video player (HTML5 <video>).
Basically, I would use getElementById('myvideotag'), listen clicks on the video for play/pause.
How I can do this with AngularJS ? Binding the click with ng-click="videoPlayPause()" but then, how I play or pause the video. How I use the classic methods of <video> ?
I guess it's really simple... I didn't get all the AngularJS concepts yet !
Thank you :)
Oh, the code... in the view:
<video autoplay="autoplay" preload="auto" ng-click="video()">
<source src="{{ current.url }}" type="video/mp4" />
</video>
In the right controller:
$scope.video = function() {
this.pause(); // ???
}
For full control, like behaviour and look&feel, I'm using videoJS in angular.
I have a ui-video directive that wraps the video HTML5 element. This is necessary to overcome a problem of integration with AngularJS:
m.directive('uiVideo', function () {
var vp; // video player object to overcome one of the angularjs issues in #1352 (https://github.com/angular/angular.js/issues/1352). when the videojs player is removed from the dom, the player object is not destroyed and can't be reused.
var videoId = Math.floor((Math.random() * 1000) + 100); // in random we trust. you can use a hash of the video uri
return {
template: '<div class="video">' +
'<video ng-src="{{ properties.src }}" id="video-' + videoId + '" class="video-js vjs-default-skin" controls preload="auto" >' +
//'<source type="video/mp4"> '+ /* seems not yet supported in angular */
'Your browser does not support the video tag. ' +
'</video></div>',
link: function (scope, element, attrs) {
scope.properties = 'whatever url';
if (vp) vp.dispose();
vp = videojs('video-' + videoId, {width: 640, height: 480 });
}
};
});
How about this:
In your HTML, set ng-click="video($event)" (don't forget the $event argument), which calls the following function:
$scope.video = function(e) {
var videoElements = angular.element(e.srcElement);
videoElements[0].pause();
}
I believe this is the simplest method.
Documentation for angular.element
Also, this might help you get used to Angular: How do I “think in AngularJS/EmberJS(or other client MVC framework)” if I have a jQuery background?
You could also take a look to my project Videogular.
https://github.com/2fdevs/videogular
It's a video player written in AngularJS, so you will have all the benefits of bindings and scope variables. Also you could write your own themes and plugins.
I also used videojs
bower install videojs --save
I wanted to use my directive in a ng-repeat and with a scope object, so... here's my version of it with props to Eduard above. I didn't seem to have a problem with the video player disposal, but the source tag issue referenced was an actual problem.
I also decided to write this up as an answer, so that I could give an example of how one might want to handle the videojs events.
IMPORTANT! Please note I am using Angular.js with Jinja2 templates, so I had to change my Angular HTML interpolation markers to {[ ]} from {{ }} in case anyone notices that as weird. I'll include that code too, so it's not weird for anyone.
Interpolation tweak
app.config(['$interpolateProvider', function($interpolateProvider) {
$interpolateProvider.startSymbol('{[');
$interpolateProvider.endSymbol(']}');
}]);
Directive
angular.module('myModule').directive('uiVideo', function () {
// Function for logging videojs events, possibly to server
function playLog(player, videoId, action, logToDb) {
action = action || 'view';
var time = player.currentTime().toFixed(3);
if (logToDb) {
// Implement your own server logging here
}
// Paused
if (player.paused()) {
console.log('playLog: ', action + " at " + time + " " + videoId);
// Playing
} else {
console.log('playLog: ', action + ", while playing at " + time + " " + videoId);
if (action === 'play') {
var wrapFn = function () {
playLog(player, videoId, action, logToDb);
};
setTimeout(wrapFn, 1000);
}
}
}
return {
template: [
'<div class="video">',
'<video id="video-{[ video.id ]}" class="video-js vjs-default-skin img-responsive" controls preload="none"',
' ng-src="{[ video.mp4 ]}"',
' poster="{[ video.jpg ]}"',
' width="240" height="120">',
'</video>',
'</div>'
].join(''),
scope: {
video: '=video',
logToDb: '=logToDb'
},
link: function (scope, element, attrs) {
scope.logToDb = scope.logToDb || false;
var videoEl = element[0].children[0].children[0];
var vp = videojs(videoEl, {},
function(){
this.on("firstplay", function(){
playLog(vp, scope.video.id, 'firstplay', scope.logToDb);
});
this.on("play", function(){
playLog(vp, scope.video.id, 'play', scope.logToDb);
});
this.on("pause", function(){
playLog(vp, scope.video.id, 'pause', scope.logToDb);
});
this.on("seeking", function(){
playLog(vp, scope.video.id, 'seeking', scope.logToDb);
});
this.on("seeked", function(){
playLog(vp, scope.video.id, 'seeked', scope.logToDb);
});
this.on("ended", function(){
playLog(vp, scope.video.id, 'ended', scope.logToDb);
});
}
);
}
};
});
Directive HTML usage
<div ng-repeat="row in videos">
<ui-video video="row"></ui-video>
</div>

loading mediaelementjs in an inline colorbox, pause video onClose

tried a few things and can't get this working. I have an inline video element that I'm loading into a colorbox, then applying mediaelementjs to it. I'm firing mediaelement on the colorbox onOpen event.
Problem is that the movie keeps playing when I close colorbox. I can't access that player outside the success function, like in onCleanup or onClose.
Here's the html where the video sits:
<div class="hidden">
<div id="trailer-wrap">
<video id="trailer" src="...video source..." type="video/mp4" controls="controls" width="720" height="480" preload="none">
<object width="720" height="405" type="application/x-shockwave-flash" data="path/to/flashmediaelement.swf">
<param name="movie" value="path/to/flashmediaelement.swf" />
<param name="flashvars" value="controls=true&file=...video source..." />
<img src="poster.jpg" alt="No video playback capabilities" />
</object>
</video>
</div>
</div>
and here's the script below it:
$(".cbox-trigger").colorbox({
inline:true,
innerWidth:"720px",
innerHeight:"480px",
scrolling:false,
onOpen: function(){
var player = new MediaElementPlayer('#trailer', {
success: function (mediaElement, domObject) {
// call the play method
mediaElement.play();
}
});
$.fn.colorbox.resize();
},
onCleanup: function(){
[how to access player object here?].pause();
}
});
For this, you may need to define player variable outside of colorbox block, then use this variable in the onCleanup callback
var player = null;
$(".cbox-trigger").colorbox({
inline:true,
innerWidth:"720px",
innerHeight:"480px",
scrolling:false,
onOpen: function(){
player = new MediaElementPlayer('#trailer', {
success: function (mediaElement, domObject) {
// call the play method
mediaElement.play();
}
});
$.fn.colorbox.resize();
},
onCleanup: function(){
player.pause();
}
});

YouTube API — not firing 'onYouTubePlayerReady()'

From what I've read, this is how I should setup the YouTube API:
<!DOCTYPE html>
<html lang="en">
<head>
<meta content='text/html;charset=UTF-8' http-equiv='content-type' />
<title>Youtube Player</title>
<script src="jquery.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js" type="text/javascript"></script>
<script type="text/javascript" charset="utf-8">
function onYouTubePlayerReady(id) {
console.log("onYouTubePlayerReady() Fired!");
var player = $("#youtube_player").get(0);
}
var params = { allowScriptAccess: "always" };
var atts = { id: "youtube_player" };
swfobject.embedSWF("http://www.youtube.com/apiplayer?enablejsapi=1",
"youtube", "425", "356", "8", null, null, params, atts);
</script>
</head>
<body>
<div id="youtube"></div>
</body>
</html>
However, 'onYouTubePlayerReady()' doesn't fire at all, and if I manually get a reference to the player, a lot of methods are undefined; for example, cueVideoById() works, but playVideo() doesn't.
How can I fix this problem?
You need to be on a web server with your test script, as stated in the documentation:
Note: To test any of these calls, you must have your file running on a webserver, as the Flash player restricts calls between local files and the internet.
this function:
function onYouTubePlayerReady(playerid) {
console.log('readyIn');
};
don't have to be directly in head in separate script tag.
Only rule you have to keep is: don't put this function inside domready event - it has to be defined sooner.
For example in mootools I use it like this:
function onYouTubePlayerReady(playerid) {
echo('readyIn');
};
document.addEvent('domready', function() {
...
});
I have the answer, separate out this portion of the script and put it in the head in its own script tag. OMG, finally
<script type="text/javascript" language="javascript">
function onYouTubePlayerReady(playerid) {
ytp = document.getElementById('ytplayer');
ytp.mute();
};
</script>
I consider this the best way of adding a youtube video to your website with javascript. It gives you a very clear way of dealing with events. It works on a local machine, and as far as I know it works on apple devices. You can use all the events and function described in the javascript documentation for the youtube api.
<div id="player"></div>
<script>
//Load player api asynchronously.
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var done = false;
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'JW5meKfy3fY',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(evt) {
evt.target.playVideo();
}
function onPlayerStateChange(evt) {
if (evt.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
</script>
source: http://apiblog.youtube.com/2011/01/introducing-javascript-player-api-for.html
<!DOCTYPE html>
had to lead the page in order for the html5 stuff to function for me in FF4
If you're embedding youtube videos like so:
<iframe src="http://www.youtube.com/embed/VIDEO_ID?jsapi=1" width="1280" height="720" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
then you should place
<script src="http://www.youtube.com/player_api"></script>
after the </iframe>. At least that's how I got it to work.
Additionally, if you're dynamically changing the [src] attribute of the iframe via jQuery or whatever to load a new video then you need to call onYouTubePlayerAPIReady() after it has loaded.
I prefer to change the [src] attribute and then:
setTimeout(onYouTubePlayerAPIReady, 500);
Just had the same issue, but for another reason. It worked in Chrome but not Firefox, and the reason was that I had a http header "Content-type: text/xml" instead of "Content-type: text/html". Serving as HTML now fires the onYouTubePlayerReady event in Firefox, too.
Just posting this in case someone stumbles on this answer from Google (like I just did when trying to find a solution).

Categories