A-Frame video not playing, only 1st frame visible - html

I can't seem to get my video playing. At first, it was just a black plane but I managed to get it to the point where I can see the first frame of the video but it doesn't play.I am using MindAR too.
The video is a 4 seconds long 608 x 1408 h.264 MPEG video. I've tried another 1080 x 1920 video but that one just displays a black plane.
Currently only testing on my Macbook Pro 14 Inch, but will eventually be for android and iOS as I'm making a AR publication.
https://glitch.com/edit/#!/unreal-realities-test
https://unreal-realities-test.glitch.me
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js#1.1.4/dist/mindar-image.prod.js"></script>
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras#v6.1.1/dist/aframe-extras.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js#1.1.4/dist/mindar-image-aframe.prod.js"></script>
<script>AFRAME.registerComponent("play-on-click", {
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 videoEl = this.el.getAttribute("material").src;
if (!videoEl) {
return;
}
this.el.object3D.visible = true;
videoEl.play();
},
});
</script>
<script>
AFRAME.registerComponent('hide-on-play', {
schema: {type: 'selector'},
init: function () {
this.onPlaying = this.onPlaying.bind(this);
this.onPause = this.onPause.bind(this);
this.el.object3D.visible = !this.data.playing;
},
play: function () {
if (this.data) {
this.data.addEventListener('playing', this.onPlaying);
this.data.addEventListener('pause', this.onPause);
}
},
pause: function () {
if (this.data) {
this.data.removeEventListener('playing', this.onPlaying);
this.data.removeEventListener('pause', this.onPause);
}
},
onPlaying: function (evt) {
this.el.object3D.visible = false;
},
onPause: function (evt) {
this.el.object3D.visible = true;
}
});</script>
</head>
<body>
<a-scene
mindar-image="imageTargetSrc: https://cdn.glitch.global/644ffc8d-f16a-4136-9daf-b2a8d5be4cd1/ASCIItargets.mind?v=1646650005503; maxTrack: 2"
color-space="sRGB"
renderer="colorManagement: true, physicallyCorrectLights"
vr-mode-ui="enabled: false"
device-orientation-permission-ui="enabled: false"
>
<a-assets>
<img
id="card0"
src="https://cdn.glitch.global/644ffc8d-f16a-4136-9daf-b2a8d5be4cd1/Jesper1_2.jpg?v=1645538130237"
/>
<a-asset-item
id="card1"
src="https://cdn.glitch.global/644ffc8d-f16a-4136-9daf-b2a8d5be4cd1/3D%20Scan%20Test.gltf?v=1645538142025"
></a-asset-item>
<video
id="video"
preload="auto"
src="https://cdn.glitch.global/644ffc8d-f16a-4136-9daf-b2a8d5be4cd1/NFTDemo.mp4?v=1646662685556"
autoplay
loop="true"
crossorigin="anonymous"
width="1"
height="0.552"
webkit-playsinline
></video>
</a-assets>
<a-entity mindar-image-target="targetIndex: 2">
<a-image
src="#card0"
alpha-test="0.5"
position="0 0 0"
height="0.552"
width="1"
material=""
geometry=""
>
</a-image>
</a-entity>
<a-entity mindar-image-target="targetIndex: 1">
<a-gltf-model
rotation="0 -270 0"
position="0 0 0"
scale="1 1 1"
src="#card1"
animation="property: position; to: 0 0.2 0.2; dur: 1000; easing: easeInOutQuad; loop: true; dir: alternate"
></a-gltf-model>
</a-entity>
<a-entity
mindar-image-target="targetIndex: 0"
material="shader: flat; src: #video"
geometry="primitive: plane; width: 2.25; height: 5.25"
position="0 0 0"
rotation="0 0 0"
play-on-click
visible="false"
>
</a-entity>
<a-camera position="0 0 0" look-controls="enabled: false">
<a-entity
position="0 0 -1.5"
text="align: center;
width: 4;
wrapCount: 100;
color: black;
value: Tap to allow videos to play"
hide-on-play="#video">
</a-entity>
</a-camera>
</a-scene>
</body>
</html>

As per browser policies most browsers today don't allow video autoplay without user consent. You need to capture a click or tap and trigger video playback by calling the play() method on the video element. The click event cannot be synthesized: A-Frame entities won't work, you need a 2D DOM element that the user clicks (the window element will work letting the user click anywhere on the screen but can also have some button somewhere that the user needs to tap).
See A-Frame example displaying a modal UI (made with A-Frame) to request the user to start video playback (a component listens for click / taps on the window element): https://aframe.io/aframe/examples/test/video/
The corresponding component logic can be found at: https://github.com/aframevr/aframe/blob/master/examples/js/play-on-click.js#L16
You need something like the code below:
window.addEventListener('click', function () {
document.querySelector('#video').play();
});
I modified your example to illustrate how to play the video on user click. I omitted the mind-ar parts. The video feed covers the UI and I think it's not relevant to the issue: video playback must be triggered by user action.
https://glitch.com/edit/#!/roomy-hyper-bear
Notice play-on-click and hide-on-play are not built-in A-Frame components and you have to import them in your page (see index.html in example above).

Related

Videosphere does not work on android browser

I add videosphere using aframe. But in android browser it does not work. I am using Samsung S6. In S6 I checked many examples along with my code. It does not work.
<!DOCTYPE html>
<html>
<head>
<title>Hello, WebVR! - A-Frame</title>
<meta name="description" content="Hello, WebVR! - A-Frame">
<script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
var scene = document.querySelector("a-scene");
var vid = document.getElementById("video");
var videoShere = document.getElementById("videoShere");
if (scene.hasLoaded) {
run();
} else {
scene.addEventListener("loaded", run);
}
function run () {
if(AFRAME.utils.device.isMobile()) {
document.querySelector('#splash').style.display = 'flex';
document.querySelector('#splash').addEventListener('click', function () {
playVideo();
this.style.display = 'none';
})
} else {
playVideo();
}
}
function playVideo () {
vid.play();
videoShere.components.material.material.map.image.play();
}
})
</script>
</head>
<body>
<div id="splash" style="display:none;">
<div id="start-button">Start</div>
</div>
<a-scene>
<a-assets>
<video id="video" src="https://ucarecdn.com/fadab25d-0b3a-45f7-8ef5-85318e92a261/" webkit-playsinline></video>
</a-assets>
<a-entity camera="userHeight: 1.6" look-controls cursor="rayOrigin: mouse"></a-entity>
<a-videosphere id="videoShere" loop="true" src="#video" rotation="0 -90 0"></a-videosphere>
</a-scene>
</body>
</html>
This is my code. What is the issue with my code? And why it does not work on android browser? Any way to solve this?
As per the A-Frame docs (https://aframe.io/docs/0.8.0/primitives/a-videosphere.html#caveats), you should have the following lines in your code to ensure they function properly in as many devices as possible:
<head>
...
<meta name="apple-mobile-web-app-capable" content="yes">
...
</head>
In the <video> element, itself, you will want to use this code to ensure that the video will play inline and will start playing immediately, if supported by the browser:
<video id="video" src="https://ucarecdn.com/fadab25d-0b3a-45f7-8ef5-85318e92a261/" autoplay loop playsinline webkit-playsinline crossorigin="anonymous"></video>
Note that crossorigin="anonymous" should be set when using assets hosted on other domains. It's also worth noting that some domains won't let you do this even if you use this code.
User interaction within the browser (outside of A-Frame) may be required to trigger the video for browsers that do not allow autoplaying by default. I modified your modal slightly to make it more visible:
<div id="splash" style="display: flex; height: 100%; width: 100%; z-index: 999999; position: absolute; background: rgba(0, 0, 0, 0.8);">
<div id="start-button">Start</div>
</div>
The javascript can be simplified just by placing the following code immediately before the ending </body> tag:
<script>
// User interaction modal to trigger video in some browsers/devices.
var modal = document.querySelector('#splash');
var video = document.querySelector('#video');
modal.addEventListener('click', function(e) {
video.play();
this.parentNode.removeChild(this);
});
</script>
Now, when a user clicks the modal splash screen, the event listener will capture the event, play the video, and remove the splash screen entirely from the DOM.
Here is a working demo: https://ultra-bass.glitch.me/
You just may need to add logic for detecting mobile devices, or more specifically, the devices that require this workaround.

Hide Video Controls Until User Hover Over Video

i'm trying to hide the video controls on my video, until the user hover over the video, then the controls shows up. Any idea or advice? Thanks. And I've got more than one video.
HTML:
<div class="item spoon burger"><video width="300" height="auto" controls><source src="videos/sruthi.mp4" type="video/mp4"></video></div>
We can accomplish this through just a couple lines of jQuery, making use of .hover():
Working Example
$('#myvideo').hover(function toggleControls() {
if (video.hasAttribute("controls")) {
video.removeAttribute("controls")
} else {
video.setAttribute("controls", "controls")
}
})
Edit I mistakenly left the variable video in the code above. I changed it to this so that you won't have to manage variables that grab an ID.
$('#myvideo').hover(function toggleControls() {
if (this.hasAttribute("controls")) {
this.removeAttribute("controls")
} else {
this.setAttribute("controls", "controls")
}
})
HTML
<video width="300" height="auto" id="myvideo">
<source src="#" type="video/mp4" />
</video>
Update:
You mentioned that you have several videos. So you can use this same logic, and just add additional selectors into $( ). Here's an example:
$('#yourID1, #yourID2, #yourID3').hover(function toggleControls() { ...
Doing that will listen or wait until it detects that you're hovering over one of those IDs.
Updated fiddle
One issue with #EnigmaRM's answer is that if jQuery somehow misses a hover event, the controls can be toggled the "wrong" way - that is, they disappear on mouse enter and reappear on mouse leave.
Instead, we can ensure that the controls always appear and disappear correctly with event.type:
$("#myvideo").hover(function(event) {
if(event.type === "mouseenter") {
$(this).attr("controls", "");
} else if(event.type === "mouseleave") {
$(this).removeAttr("controls");
}
});
Untested, but I believe this would work. It uses JavaScript instead of CSS.
<div class="item spoon burger"><video id="videoElement" width="300" height="auto"><source src="videos/sruthi.mp4" type="video/mp4"></video></div>
<script type="text/javascript">
(function(window) {
function setupVideo()
{
var v = document.getElementById('videoElement');
v.addEventListener('mouseover', function() { this.controls = true; }, false);
v.addEventListener('mouseout', function() { this.controls = false; }, false);
}
window.addEventListener('load', setupVideo, false);
})(window);
</script>
<script>
function setupVideos() {
for (const video of document.querySelectorAll('video')) {
video.controls = false
video.addEventListener('mouseover', () => { video.controls = 'controls' })
video.addEventListener('mouseout', () => { video.controls = false })
}
}
window.addEventListener('load', setupVideos, false)
</script>
Using the code below, you don't need a separate javascript section (if that is a concern, which is the case sometimes). Just simply use onmouseover="this.play();this.setAttribute('controls','controls')" and onmouseout="this.load();this.removeAttribute('controls')"
If you don't want it to reset to a poster image, then you can get rid of the this.load.
<div class="img_placeholder">
<video width="350" height="250" loop preload="none" poster="../assets/icon-32.png" onmouseover="this.play();this.setAttribute('controls','controls')" onmouseout="this.load();this.removeAttribute('controls')">
<source src="../assets/bear.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
</div>
A previous post explained how to do it this way HTML5 video - show/hide controls programmatically
<video id="myvideo">
<source src="path/to/movie.mp4" />
</video>
<p onclick="toggleControls();">Toggle</p>
<script>
var video = document.getElementById("myvideo");
function toggleControls() {
if (video.hasAttribute("controls")) {
video.removeAttribute("controls")
} else {
video.setAttribute("controls","controls")
}
}
</script>
Check if their solution works for you! Please +1 them if so!

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.

HTML5 video onended event firing once

I am really stumped on this one.
I am trying to use the html5 video player and javascript in safari. I want to
1 play a greeting video
2 play a default looping video while the user makes a selection
3 play user selection
4 return to the default looping video.
1, 2, 3 work but 4 does not.
I call the greeting video from the body
<video id="videok" width=400 height=400 autoplay="autoplay" src="sacagreeting.mov" >
video not supported
</video>
I set my event listener up in the body
body onload="myAddListener()"
function myAddListener(){
var myVideo = document.getElementsByTagName('video')[0];
myVideo.addEventListener('ended',myNewSrc,false);
}
my function to play the looping default video is
function myNewSrc() {
myVideo = document.getElementsByTagName('video')[0];
myVideo.src="sacarest.mov";
myVideo.loop="loop";
myVideo.load();
myVideo.play();
}
I use an select element for the user to pick a video and the onchange event to call my video function
function myNewSrcii() {
myVideo = document.getElementById('videok');
myVideo.loop=""
myquest = document.getElementById('vidquest').value;
switch(myquest)
{
case "a":
myVideo.src="sacaa.mov";
break;
case "b":
myVideo.src="sacab.mov";
break;
case "c":
myVideo.src="sacac.mov";
break;
case "d":
myVideo.src="sacad.mov";
break;
case "e":
myVideo.src="sacae.mov";
break;
case "f":
myVideo.src="sacaf.mov";
}
myVideo.load();
myVideo.play();
}
I have tried dropping the looping attribute, setting the event listener again in the myNewSrcii function, using an onended event in the video tag and no luck. When I check the video event ended is true, the listener however never calls my default video function. Any help would be greatly apprectiated.
thanks
This is due to a strange bug in Safari's HTML5 video tag implementation. It can be reproduced on Safari for Windows as well. I've just found one workaround for this problem - just bind to loadedmetadata event and set the currentTime to some non-zero value. Here is an example:
<!doctype html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.0.min.js"></script>
</head>
<body>
<video id="video" width="500" height="400" controls autoplay></video>
<script>
var src = [
"http://content.adfox.ru/131007/adfox/205544/865991_11.mp4",
"http://all.rutube.ru/130627/gpmdigital/217059/805529_11.mp4"
];
var curSrc = 0;
$(function() {
$('#video').attr("src", src[curSrc % src.length]);
curSrc++;
var video = $('#video').get(0);
$('#video')
.on('loadedmetadata', function() {
video.currentTime=0.01;
video.play();
})
.on('ended', function() {
console.log('ended');
video.src = src[curSrc % src.length];
video.load();
curSrc++;
});
});
</script>
</body>
</html>
You can try this demo in this jsfiddle: http://jsfiddle.net/j2knz6sv/

Flowplayer not showing audio player

I am trying to have a video and audio in a html page. I kinda having the video working fine but the audio is not showing up. Any help would be appreciated
http://www.wholesalewealthmachine.com/abc/
<div id="video" style="border: 1px solid rgb(204, 204, 204); width: 490px; height: 385px; margin:0 auto;">
<script type="text/javascript">
flowplayer("player", "flowplayer-3.2.2.swf",{
plugins: {
controls: null
},
canvas: {backgroundColor: '#ffffff',backgroundGradient: "none"}
,
clip: {
url: 'http://wholesaletoriches.com/newthankyouvideos/wwm new thankyou final/wwm new thankyou final.mp4'
},
onLoad: function() {
this.setVolume(100);
}}
);
</script>
</div>
<div id="audio" style="width:750px;height:30px;display:block">
<script language='javascript'>
$f("audio", "http://releases.flowplayer.org/swf/flowplayer-3.2.6.swf", {
// fullscreen button not needed here
plugins: {
controls: {
fullscreen: false,
height: 30,
autoHide: false
}
},
clip: {
autoPlay: false,
// optional: when playback starts close the first audio playback
onBeforeBegin: function() {
$f("player").close();
}
}
});
</script>
</div>
You need to grab the Flowplayer Audio plugin from
http://flowplayer.org/plugins/streaming/audio.html
then add this to your plugins parameters
plugins:{ audio: { url: "http:/yourpathtotheaudioplugin/flowplayer.audio.swf"} }
Credit to GraemeLeighfield at http://flowplayer.org/forum/2/47848
$f does not work. Instead of using $f use flowplayer. So it should look like:
flowplayer("audio", "http://releases.flowplayer.org/swf/flowplayer-3.2.6.swf", {...
This problem and the fix were reported in the Flowplayer forum just about one year ago. (see link) The developers of Flowplayer have not updated their documentation as far as I can tell. I had the same problem as Graeme. The fix he posted resolved the problem for me.
I've had trouble working though off site url's. It best if down load the code from flowplayer and load them onto your server.
Audio portion: http://flash.flowplayer.org/plugins/streaming/audio.html Scroll to bottom of page and down load 3 files
flowplayer.audio-3.2.10.swf
flowplayer.audio-3.2.10.zip
flowplayer.audio-3.2.10-src.zip
Place them in root directory.(ex.) Flow-Player-Audio
Place this script in head
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js">
</script>
<script src="http://www.domain.com/Flow-Player-Audio/flowplayer-3.2.6.min.js"></script>
<!-- set up player container -->
<a id="mb" style="display:block;width:250px;height:30px;"
href="http://www.domain.com/audio/something.mp3 or mp4"></a>
<script type="text/javascript">
// install flowplayer into container
$f("mb", "http://www.domain.com/Flow-Player-Audio/flowplayer-3.2.7.swf", {
// fullscreen button not needed here
plugins: {
controls: {
fullscreen: false,
height: 30,
width: 250,
autoHide: false
}
},
clip: {
autoPlay: false,
// optional: when playback starts close the first audio playback
onBeforeBegin: function() {
$f("player").close();
}
}
});
</script>
For video
down load
http://flash.flowplayer.org/download/
grab Download ZIP and Source code
place in swf file on server
script files
<!-- 1. jquery library -->
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js">
</script>
<!-- 2. flowplayer -->
<script type="text/javascript" src="js/flowplayer.js"></script>
<!-- 3. skin -->
<link rel="stylesheet" type="text/css" href="skin/minimalist.css" />
then just add your video tags.