Javascript to automatically turn on sound volume on video after autoplay - javascript

I am coding an online psychology experiment. Participants have to watch a short movie and remember some information. To analyze the data everyone has to see the same movie, so it would be a problem if people pause it. Therefore, I disabled all controls and autoplay the video.
On Chrome this only works if the player starts mute. So I would like to turn on the sound automatically right after the video starts.
I am trying to use the following html with the video hosted here
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="user-scalable=no">
</head>
<body style="width: 1000px; height: 800px; background-color: grey;">
<div class="container">
<div id="video-player"></div>
</div>
<script src="https://muse.ai/static/js/embed-player.min.js"></script>
<script>
const player = MusePlayer({
container:'#video-player',
video: 'qhRjheS',
width: 720,
height: 480,
autoplay: true,
loop: true,
volume: 0,
style: 'no-controls',
shortcuts: false,
css: '*{pointer-events:none!important;}',
});
player.on('timeupdate', function(time) {player.setVolume(100)});
</script>
</body>
</html>
Where this line is the issue:
player.on('timeupdate', function(time) {player.setVolume(100)});
This works in the console, while the video is running, but crashes if it's put in the script.
Can anyone think of any way to turn on the sound automatically? If there is a small delay after the movie starts, that would be okay.

As an experiment (not a full solution) I'd try something like this:
setTimeout(() => player.on('timeupdate', () => player.setVolume(100)), 3000);
(I took the liberty of changing your code to use arrow functions.)
I suspect that the player isn't immediately ready to have the volume set, and takes a moment to be fully set up and ready to go. I'm not familar with MusePlayer specifically, but I'd look at the docs and see if there are other events, besides the 'timeupdate' event, that you'd want to receive first before setting up the listener for the 'timeupdate' event.

Thanks kshetline for the input. It's indeed a problem for me that chrome blocks autoplay. However, adding an event listener to start the movie on click is a workaround. I guess autostart is not possible, but this way all other controls still remain disabled once the movie starts.
document.body.addEventListener("click", function () {
player.play();
});

Related

Howlerjs playing audio twice when using once()

I'm working with Howler.js on a little alarm clock I'm working on.
For my alarm clock, I want to play 2 audio files sequentially when the current time matches a predetermined time.
I've got this code:
var play_sound = window[data.sound];
presound.play();
presound.once('end', function(){
play_sound.play();
});
The problem is, this code plays my presound 2 times, and then play_sound afterward. I do not want it to play the presound 2 times, only once.
If I change the code to
presound.play();
play_sound.play();
It seems to work, it doesn't play them at the same time, but I worry that it might in some cases. So I want to avoid these files being played at the same time, and I also want to avoid either of them playing more than once.
How can I do what I'm trying to do while utilizing events to make sure there is no overlap?
I also tried this:
presound.once('play', function() {
presound.once('end', function() {
play_sound.play();
});
});
presound.play();
but it also plays my presound twice.
Here I can see another example with end event:
// Fires when the sound finishes playing.
sound.on('end', function(){
console.log('Finished!');
});
Did you try on instead of once?
UPD:
Cannot reproduce an issue.
A code snippet that I use:
function clickme() {
var presound = new Howl({
src: ['sound.m4a'],
html5: true
});
var play_sound = new Howl({
src: ['sound2.mp3'],
html5: true
});
presound.play();
// Fires when the sound finishes playing.
presound.once('end', function() {
play_sound.play();
});
}
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.1.1/howler.core.min.js"></script>
</head>
<body>
<input type="button" onclick="clickme()" value="Hello" />
</body>
</html>

Playing and Stopping Sound with JS and JQuery

I have a way to play sound with a simple command, https://github.com/admsev/jquery-play-sound, but the audio file I am playing is about 2 minutes long. I need a way to stop/silence the audio with a javascript or jquery command. Does anyone know how I could do this? I don't really want a button that stops the sound unless it was a regular html button that could do other things besides stop the sound.
The jQuery playSound library you linked does not support pausing. I think it would be best to choose a different library that supports pausing so you don’t have to write that functionality yourself.
I used the howler.js library before and it worked fine for me. Here is how you would use howler.js:
<!-- to load the library on the page -->
<script src="howler.js">
// to create and play the sound
var backgroundMusic = new Howl({
urls: ['music.mp3', 'music.ogg'],
}).play();
// to pause the sound
// (make sure the variable `backgroundMusic` is accessible)
backgroundMusic.pause();
// to stop the sound
backgroundMusic.stop();
No jQuery, no plugins, just a browser. This is one button that plays and pauses one MP3. You didn't specify what extra things you wanted one single button to do, so I didn't add any extra functions to that one single lonely button. What other things did you want this one solitary button to do?
Btw, if you want the audio to stop instead of pause:
There's a line in the <style> block that you need to uncomment and a line to comment.
There's a line in the <script> block you need to uncomment.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
.play:before {
content: '\25b6';
}
.pause:before {
content: '\275a\275a'; /*Uncomment this line for pause */
/* content: '\25a0'; */ /*Uncomment this line for stop */
}
</style>
</head>
<body>
<button id="button" class="play">
<audio id="audio" src="http://glpjt.s3.amazonaws.com/so/av/pf-righteous.mp3"></audio>
</button>
<script>
var audio = document.getElementById('audio');
var button = document.getElementById('button');
button.addEventListener('click', playPause, false);
function playPause() {
if (!audio.paused) {
audio.pause();
// audio.currentTime = 0; // Uncomment this line for stop
button.classList.remove('pause');
button.classList.add('play');
} else {
audio.play();
button.classList.remove('play');
button.classList.add('pause');
}
}
</script>
</body>
</html>

Security Error while trying to play a sound in Firefox add-on?

I'm new to Firefox add-on development, and I have a problem while trying to play a sound in my add-on.
It's an add-on for timekeeping. Users can configure meetings settings (duration, participants... etc) through a Panel. There is a toolbar. It contains several buttons (Start, Next, Stop, Add Participant) and a Frame (to display how many participants haven't speaked yet). I change the document.border.style property from "green" to "red" as timers countdown.
This works fine. But I was asked to make my add-on play a sound when the document.border.style property turns "orange" and then "red" and I can't make it works.
I have tried several things :
1-Adding a property/attribute (I don't know which term is the right to use in that context, maybe both, anyway) to my TimeKeeper variable for each sound that has to be played. Meaning in my code :
orangeBorderStyle: new Audio(relativePathToMyMp3orWAVFile),
redBorderStyle: new Audio(relativePathToMyMp3orWAVFile),
and then calling their play() method in the countdown() method. But it didn't work.
2-Currently, I'm trying to play the sounds from HTML5 audio tags I added to the frame.url HTML file. But it doesn't work either.
The HTML file looks like this :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Frame</title>
</head>
<body>
<script type="text/javascript" src="../javascript/Frame_script.js"></script>
Speakers Left : <input id="speakers" size="4" value="" disabled />
<audio id="orangeSound" src="Audio/orangeBorderSoundTest.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
<audio id="redSound" src="Audio/redBorderSoundTest.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
</body>
</html>
In Frame_script.js I have :
window.addEventListener("message", reactToMessages, false);
var orangeBorderSound=document.getElementById("orangeSound");
var redBorderSound=document.getElementById("redSound");
//console.log(orangeBorderSound);
function reactToMessages(e){
if(isNaN(e.data)==false){
displaySpeakersLeft(e);
}
if(e.data=="orangeBorderSound")
{
document.getElementById("orangeSound").play();
//console.log("Je joue le son Orange.");
} else if(e.data=="redBorderSound")
{
document.getElementById("redSound").play();
//console.log("Je joue le son Rouge.");
}
}
function displaySpeakersLeft(e){
document.getElementById("speakers").value=e.data;
}
and in Timers.js I have the following calls :
Frame.get().postMessage("orangeBorderSound", Frame.get().url);
Frame.get().postMessage("redBorderSound", Frame.get().url);
Both calls trigger the right code (when the console.log() are commented out, they are displayed correctly) but there is no sound in the end.
Please, note that the value of the input tag with ID "speakers" is correctly displayed in my add-on so it seems that the document.getElementById() methods returns the right thing, and that it is the right way to do things with an input tag. Meaning, the paths are the right ones. I can't see why it would be different with audio tags.
So here comes my question : I now see the error "Security Error: Content at moz-nullprincipal:... may not load or link to resource..." (the resource path given seems to be the right one for each audio file) in the Error Console.
Is this really a security issue ? Or would I have little to change to make my code works ? What would you do ?
Any explanation or suggestion would be appreciated. I really don't see what's wrong with what I've done. Why would it cause security problems ?
Please, note that I've tried to use the audio tags method in a new add-on with just a Play button in the Panel and nothing else, but this time with the audio tags in the Panel contentURL HTML file, calling the play() method in the contentScriptFile and it worked.
No security error this time.
But I suppose I can't accept such a solution in my timekeeping add-on since I need to synchronize the call of the play() method with the change of the border style and that there is no Play button this time. It does not correspond to what I want to obtain. It was just for testing purpose.
Timers.js which is in my lib directory cannot interact with the Panel contentScriptFile which is in the data directory, so it couldn't be a solution even if the sounds were correctly loaded and ready to be played.
What do I get wrong ?

Can I synchronize a video with DOM events?

Nothing specific, E.g:
I have a video [with controls(Pause, play, forward... ) in a tag] How would you do to: when the video is in the second 30, make a div appear, then, in the second 32, make it disappear.
Thanks :)
If you're using the HTML5 <video> element you can use the ontimeupdate event to track where the playback has got to, as in this example:
// display the current and remaining times
video.addEventListener("timeupdate", function () {
// Current time
var vTime = video.currentTime;
document.getElementById("curTime").textContent = vTime.toFixed(1);
document.getElementById("vRemaining").textContent = (vLength - vTime).toFixed(1);
}, false);
Thanks to Microsoft for their reference
Here's a working example:
<!DOCTYPE html>
<html>
<head>
<title>Video demo</title>
<script>
// ontimeupdate event handler
function update(e) {
// get the video element id so that we can retrieve the current time.
el = document.getElementById('myVideo');
// set the current time in the page
document.getElementById('timer').innerHTML = el.currentTime;
// If the current time is between 10 and 15 seconds pop-up the
// second div
if (el.currentTime > 20 && el.currentTime <=25) {
document.getElementById('popup').style.display='block';
} else {
document.getElementById('popup').style.display='none';
}
}
</script>
<style>
video {width:300px;}
</style>
</head>
<body>
<video id=myVideo ontimeupdate="update()" src="http://archive.org/download/HardDriveSpinning/HardDriveWebm.webm" autoplay>Sorry - format unsupported</video>
<div id="timer"></div>
<div id="popup" style="display:none">Boo!</div>
</body>
</html>
See it at this fiddle (Works for Firefox and Chrome. IE doesn't like the WebM video format)
You could use window.setTimeout to run a function after a specified amount of time. This won't be enough by itself if the user is able to pause the video. You'd have to tell us more about how you're displaying the video in order to get a more in-depth solution.
But perhaps more importantly, you might want to go back to square one and think again about what you're really trying to accomplish. Because it seems to me that if it seems like you need to trigger DOM manipulations based on the time index of a video, there's probably a better way to do what you really want that doesn't involve that.

Prevent scrolling on HTML5 <video> element on iOS

I am trying to prevent the default scrolling within a web app which contains an HTML5 video element on Mobile Safari. Handling document.ontouchmove and calling e.preventDefault() has been the standard way that I've found to achieve this.
This seems to work everywhere except when you touch on top of the video element, where you can start pulling the page all around as if it is going to scroll. This only seems to happen when the native video controls are forced on. If you don't include the controls attribute and load the video in a way that it can be played in-line (such as on the iPad or in a UIWebView with allowsInlineMediaPlayback set), scrolling is prevented properly. So it seems like it has something to do with the native video controls (the big play button) capturing the event.
Here is a contrived example of what I am doing:
<!DOCTYPE HTML>
<html>
<head>
<title>HTML5 Video Example</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
</head>
<body style="background: blue;">
<video src="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/bbb_trailer_iphone.m4v" controls></video>
<script>
window.onload = function() {
document.ontouchmove = function(e) {
e.preventDefault();
}
}
</script>
</body>
</html>
Any ideas of workarounds to completely prohibit scrolling behavior, even on the video? I've already tried handling ontouchmove directly on the video element and it doesn't work.
Thanks!
In my test, when ommiting the "controls" attribute of the video you can get the events to work. Use a custom div in top to provide custom controls
By example....
<video src="http://192.168.1.53/videoTester/Cuatro.mp4" id="player" width="100%" height="100%" x-webkit-airplay="allow" ></video>
Like you, I couldn't prevent scrolling, so as a workaround added a JS function to fire window.scrollTo(0, 1); every second which then means the user can only scroll for a certain time before the page is jumped back.
Try:
element.addEventListener('touchmove', function(event) {
// Prevent scrolling on this element
event.preventDefault();
}, false);
for just the element in question or:
window.addEventListener('touchmove', function(event) {
// Prevent scrolling on this element
event.preventDefault();
}, false);
for the whole window.
I came up with a good solution for this after running into the same issue. I got it to work by doing the following:
//Function to trigger when every half second to check if user scrolled
$(function () {
//select video player and the current time
var myPlayer = document.getElementById('VideoID');
var whereYouAt = myPlayer.currentTime;
var current;
setInterval(function () {
current = myPlayer.currentTime;
if (current > (whereYouAt + 1)) {
myPlayer.currentTime = whereYouAt; //If current 1 whole second
//Set time to before scroll.
}
else {
whereYouAt = current; //otherwise set where to current.
}
}, 500); //500 = half a second.
});
This will only work for HTML5 video and not if it triggers the mobile video player. I hope this helps and let me know if you have any questions.

Categories