HTML video not playing with Vue.js 2 - html

I have an HTML video in my web app:
<video src="" id="video-container" controls></video>
Initially the source is empty and I change it dynamically with JS, after loading some data:
var video = document.getElementById('video-container');
...
video.src = VIDEO_URL;
video.play();
That used to work perfectly and it was compatible with Vue.js 1 but, since I migrated to Vue.js 2 the video is no longer working. Calls to video.play(), video.pause() have no effect on the video player and attributes such as video.clientWidth returns zero values.
Is there any incompatibility with this element in Vue.js 2? Am I missing something?
Thanks!

Edit: Please check out Chrome's Documentation on force playing a video before implementing this.
Now that I know more about VueJS, this solution seems much better:
jsfiddle working
HTML
<div id="app">
<video ref="videoRef" src="" id="video-container" width="100%" controls></video>
</div>
JS
new Vue({
el: "#app",
mounted: function() {
this.$refs.videoRef.src = "http://iandevlin.github.io/mdn/video-player/video/tears-of-steel-battle-clip-medium.mp4";
this.$refs.videoRef.play();
}
});

While I was creating the fiddle as saurabh suggested I found the 'solution' (even if I can not provide an accurate explanation).
The problem arises when we are using VueJS 2 and we define the video element var before instantiating the Vue class. Strangely, the same code is working with VueJS 1:
Video not working. Vue 2.1.3
Video working. Vue 1.0.28
var video = document.getElementById('video-container');
new Vue({
el: "#app",
});
video.src = "http://iandevlin.github.io/mdn/video-player/video/tears-of-steel-battle-clip-medium.mp4";
video.play();
If the var is defined after Vue instantiation, everything works with version 2.
jsfiddle.net/6qmjw5xd/1/
new Vue({
el: "#app",
});
var video = document.getElementById('video-container');
video.src = "http://iandevlin.github.io/mdn/video-player/video/tears-of-steel-battle-clip-medium.mp4";
video.play();

Related

Angular 8 - Is there a way to bind to a video element to determine when it is loaded/starts playing?

Given:
<video poster="assets/videos/poster.png"
#videoPlayer
onloadedmetadata="this.muted = true">
<source src="assets/videos/video.mp4" type="video/mp4">
</video>
And in Angular:
...
public videoLoaded: boolean = false;
...
How can I bind videoLoaded to update once the video starts playing? (or is loaded) I've looked online and saw some older jquery implementations that seem to not be working in newer versions of chrome and want to know the latest way on how to accomplish this
Thanks
What you could do is make a reference to the video player itself with Angular's ViewChild and check if it's clicked.
#ViewChild('videoPlayer') videoPlayer: ElementRef;
videoClicked = false;
startVideo(): void {
this.videoClicked = true;
this.videoPlayer.nativeElement.play();
}
The startVideo() method will be used inside the HTML to trigger the change. The additional paragraph is used to see the change.
<video (click)="startVideo()" width="400"
#videoPlayer>
<source src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4">
</video>
<p>Video clicked: {{videoClicked}}</p>
See this StackBlitz as an example of above behaviour.
Edit
A better way to do this is to use HTMLMediaElement's onplaying and loadeddata event. See MDN for documentation on onplaying and documentation on onplaying. In normal JavaScript it would look like this:
const video = document.querySelector('video');
video.onplaying = (event) => {
console.log('Video is no longer paused.');
};
In Angular, there are some small changes required. The HTML can stay pretty clean.
<video controls width="400"
#videoPlayer>
<source src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4">
</video>
<p>Video loaded: {{dataLoaded}}</p>
<p>Video started: {{videoStarted}}</p>
The biggest changes are in the component, ngAfterViewInit checks if the element is there after view has been initialised. The loadeddata event is fired when the frame at the current playback position of the media has finished loading (so ready to play). Next to that, you can access the element's onplaying event to check if the video is not paused.
#ViewChild('videoPlayer') videoPlayer: ElementRef;
dataLoaded = false;
videoStarted = false;
ngAfterViewInit() {
this.videoPlayer.nativeElement.onloadeddata = (event) => {
console.log('Video data is loaded.');
this.dataLoaded = true;
};
this.videoPlayer.nativeElement.onplaying = (event) => {
console.log('Video is no longer paused.');
this.videoStarted = true;
};
}
Here's a StackBlitz example to show this example.
you can use HTML Audio/Video Events provided by html 5 video attribute.
loadeddata -> Fires when the browser has loaded the current frame of the audio/video
loadedmetadata -> Fires when the browser has loaded meta data for the audio/video
loadstart -> Fires when the browser starts looking for the audio/video

embed youtube html5 player shows no fullscreen button

I include the YouTube player as follows in my php file but the player does not show the fullscreen button. Switching to the flash player works (whether through changing the url from /embed to /v or by disabling &html5=1). What am I doing wrong?
An example is available here: http://jonnyrimkus.square7.ch/stuff/youtube_html5_fullscreen.php
<script>
var tag = document.createElement(\'script\');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName(\'script\')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onYouTubeIframeAPIReady() {
player = new YT.Player(\'player\', {
playerVars: {
\'allowfullscreen\': \'true\',
\'allowscriptaccess\': \'always\'
},
events: {
\'onReady\': onYouTubePlayerReady,
\'onStateChange\': playerStateChange,
\'onError\': playerStateError
}
});
}
</script>
<iframe id="player" width="425" height="356" border="0" frameborder="0" src="http://www.youtube.com/embed/36XdO9Iv9ew?enablejsapi=1&playerapiid=lastfmplayer&autoplay=1&html5=1&fs=1&origin=http://jonnyrimkus.square7.ch"></iframe>
The fullscreen button will also not be visible if the Youtube player is inside another iframe that does not have allowfullscreen attribute.
Unlike what Google's documentation says(as of 11/2014), the fs attribute in querystring does not seem to influence the visibility of fullscreen. The visibility seems to be influenced by allowfullscreen attribute in iframe which youtube player puts by default during instantiation. That said, if your embed the player inside another iframe you should also mark that iframe for allowfullscreen ( or all its variants webkitallowfullscreen mozallowfullscreen)
<iframe src='' frameborder='0' webkitallowfullscreen mozallowfullscreen allowfullscreen>
<!-- YT player-->
</iframe>
The way you are using the iframe api now does nothing, the api is made to bind on an empty element, like <div id="player"></div>, the id is the first argument in the new YT.Player function.
In order to load a youtube video with the iframe api you need this in the body:
<div id="player"></div>
<script type="text/javascript">
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: 480,
width: 640,
videoId: "36XdO9Iv9ew",
});
}
</script>
There is no need to explicitely specify you want to enable fullscreen when using the iframe api.
You can also just use the iframe without the api, you'll need to specify you want fullscreen when you use it.
<iframe width="640" height="480" frameborder="0" id="player" allowfullscreen="1" title="YouTube video player" src="http://www.youtube.com/embed/36XdO9Iv9ew?enablejsapi=1"></iframe>
Just using the iframe tag is a bit faster, but if you want to use the extra features of the iframe api you have no choice.
A page with examples (also check the source): http://qnet.co/yt
You can also implement the fullscreen feature yourself (not needed for Youtube, but still cool):
var goFullscreen = function(id) {
var el = document.getElementById(id);
if (el.requestFullScreen) {
el.requestFullScreen();
} else if (el.mozRequestFullScreen) {
el.mozRequestFullScreen();
} else if (el.webkitRequestFullScreen) {
el.webkitRequestFullScreen();
}
}
var leaveFullscreen = function() {
if (document.cancelFullScreen) {
document.cancelFullScreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
}
}
and to make the Youtube player go fullscreen with: goFullscreen('player'), and leave fullscreen with: leaveFullscreen()
The different versions of requestFullscreen and cancelFullscreen are for different browsers, because the standard is not yet completely finished
More info on Javascript Fullscreen: http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/ (relative old document, but still valid)
off-topic: It is useless to echo such a string with php, you can just paste it in the body the file outside of the php tags.
This is still an issue in July 2014, and you just wonder if Google will ever fix this. Actually you can force the Flash player in another way at the client end by using a UA Spoofer, and for Google Chrome browser for instance, Chrome Web Store - djflhoibgkdhkhhcedjiklpkjnoahfmg and then spoof a browser that doesn't understand HTML5.
Actually HTML5 video is still a disaster, and the grainey spikey-jaggy edges to the video and the herringbone patterning though faint is still distracting. Whereas Flash is Smooth, Flawless, Reliable, and Sharp edges with zero patterning artifacts.
HTML5 - still big thumbs down, I wouldn't inflict it on users.
Oh yes and still Fullscreen not appear in embeds like this
Rick Astley - Never Gonna Give You Up # viewpure embed
http://viewpure.com/dQw4w9WgXcQ
You can use the above example to fiddle and diddle with different browser plugins.

How do I make a simple snapshot webapp in HTML5?

I need to make a HTML5 page that can display live video coming from the device's camera/webcam and that has a button that can take a snapshot; nothing fancy (similar to html5camera.com). I tried following some tutorials (http://www.html5rocks.com/en/tutorials/getusermedia/intro/ AND http://davidwalsh.name/browser-camera), but I'm still new at HTML, so I'm not sure what to do with the code snippets I find.
I copied some code into a HTML-file, but when I open it with Chrome, it says at the right in the address bar that it blocked access to the camera and microphone (without bothering to ask for permission). When I click the option to ask for permission next time and reload the page, nothing happens. There is no way to set the preferences to allow by default. I also tried Chrome Canary (same as Chrome) and Firefox (didn't ask for permission).
Did I make a mistake in the HTML? Is Chrome the problem?
The code I have so far:
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=yes">
</head>
<body>
<video id="video" width="640" height="480" autoplay></video>
<button id="snap">Snap Photo</button>
<canvas id="canvas" width="640" height="480"></canvas>
<script>
// Put event listeners into place
window.addEventListener("DOMContentLoaded", function() {
// Grab elements, create settings, etc.
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
video = document.getElementById("video"),
videoObj = { "video": true },
errBack = function(error) {
console.log("Video capture error: ", error.code);
};
// Put video listeners into place
if(navigator.getUserMedia) { // Standard
navigator.getUserMedia(videoObj, function(stream) {
video.src = stream;
video.play();
}, errBack);
} else if(navigator.webkitGetUserMedia) { // WebKit-prefixed
navigator.webkitGetUserMedia(videoObj, function(stream){
video.src = window.webkitURL.createObjectURL(stream);
video.play();
}, errBack);
}
// Trigger photo take
document.getElementById("snap").addEventListener("click", function() {
context.drawImage(video, 0, 0, 640, 480);
});
}, false);
</script>
</body>
</html>
You might also consider just going native. You can add native camera and camcorder support to any web app on Android, iOS or Windows Phone 8 very easily with BridgeIt: http://bridgeit.mobi. It's a simple javascript api that allows you to access native mobile features.

SoundCloud embedded track: How to refresh page after the track ends playing?

First off, I am quite a noob.
Ok, so I have embedded a SoundCloud track into my webpage. My question is, how do you refresh a page (or do anything else) when the track ends?
Can you do it with getDuration(I found that on SoundCloud API page)?
I tried to code it. In the code I tried to get the duration of the track and then print it on the screen/webpage. What is wrong with this code?
<script src="https://w.soundcloud.com/player/api.js" type="text/javascript"></script>
<span id="headerLeft-content">
<script type="text/javascript">
var duration = 0;
(function(){
var widgetIframe = document.getElementById('sc-widget'),
widget = SC.Widget(widgetIframe);
widget.bind(SC.Widget.Events.READY, function() {
widget.getDuration(function(val) {
duration = val;
});
});
}());
document.write(duration);
</script>
</span>
If that worked, I would just put something like wait(duration) and then refresh...
In other words, can soundcloud embedded track be "hacked" to loop(or to refresh page after track is over, that's what I want to do) even though the original widget doesn't support looping?
Please, take a look at the SoundCloud html5 widget page where I found getDuration command and see if you can help me... => http://developers.soundcloud.com/docs/api/html5-widget#getters
EDIT:
<script>
var html=<iframe blablabla...></iframe>
document.write(html);
</script>
<script src="https://w.soundcloud.com/player/api.js" type="text/javascript"></script>
<script type="text/javascript">
(function(){
var widgetIframe = document.getElementById('sc-widget'),
widget = SC.Widget(widgetIframe),
widget.bind(SC.Widget.FINISH, function() {
window.location.reload(false);
});
}());
</script>
Page doesn't refresh after the track is over. Can you see what's wrong?
You can bind a function to the SC.Widget.FINISH event documented here. The following code snippet should work:
widget.bind(SC.Widget.FINISH, function() {
window.location.reload(false);
});
Of course if all you want is for the widget to loop, you could use the seekTo and play methods:
widget.bind(SC.Widget.FINISH, function() {
// again, again!
widget.seekTo(0);
widget.play();
});
That would be less intrusive than a page refresh.
widget.bind(SC.Widget.Event.FINISH, function() {
widget.seekTo(0);
widget.play();
});
In the other reply, the first parameter is missing ".Event".
Finally. A truly working version.
var widgetIframe = document.getElementById("soundcloud"),
widget = SC.Widget(widgetIframe);
widget.bind(SC.Widget.Events.FINISH, function() {
widget.play();
});

Problem with html5 audio and javascript manipulation

I'm trying to manipulate an audio file (mp3), using <audio> and javascript but nothing happens when I click the link. The alert() is working but nothing happens with the audio i.e. no pause, no play, nothing..., whether in Safari or Firefox. Is the coding dodgy or what?
Check this out:
jQuery/javascript:
$(document).ready( function(){
var audioElement = document.getElementById('audio_player');
$('div.audioControls .play').live('click', function(){
//alert('play');
audioElement.play();
});
$('div.audioControls .pause').live('click', function(){
//alert('pause');
audioElement.pause();
});
$('div.audioControls .playatTime').live('click', function(){
alert('play at time: 30 sec');
audioElement.currentTime = 30;
audioElement.play();
return false;
});
});
HTML:
<audio id="audio_player" controls="controls" src="aaliyah.mp3">
Your browser does not support the audio element.
</audio>
<div class="audioControls">
play
pause
play at 35 secondes
</div>
Thanks!
I now know why, it didn't work. To make use of the javascript API, the controls attributes needs to be removed from the html tag itself and it should work.
Thanks