I am trying to stream video using links that expire every 2 minutes.
Basically, I use this function to replace the URL, and it works great:
function test(){
var videoFile = 'new.mp4';
var $video = $('#m video');
var curtime = $video[0].currentTime;
videoSrc = $('source', $video).attr('src', videoFile);
$video[0].load();
$video[0].currentTime = (curtime);
$video[0].play();
}
The question I have is how do I fire this function every time the video starts playing/after someone seeks in it? If i fire the ok(); function using a play event then it starts a loop since the function itself causes a play event.
Does anyone have any ideas on how to fix this in a good way?
The solution would be to register the play event once the video has actually started playing. That way it will react after a pause or a seek.
If you need to disable the event on other conditions then you simply disable the play event (as done in the start of the playing function)...
function test(){
var videoFile = 'trailer.mp4';
var $video = $('#video');
var curtime = $video[0].currentTime;
videoSrc = $('source', $video).attr('src', videoFile);
$video[0].load();
$video[0].currentTime = (curtime);
$video[0].play();
$video.on('playing', function () {
$video.off('play') // remove existing Play event if there is one
console.log("Play event bound")
$video.on('play', function () {
console.log("Video play. Current time of videoplay: " + $video[0].currentTime );
});
});
}
Related
I create websocket server in python to handle notification event. Now, i can receive notification, the problem is i can't play sound because new autoplay policy changed, if i play sound using javascript it give me domexception. Any suggestion please ?
As i know, playing sound is simple in html-javascript. like this example: https://stackoverflow.com/a/18628124/7514010
but it depend to your browsers and how you load and play, so issues is:
Some of browsers wait till user click something, then let you play it (Find a way for it)
In some case browsers never let you play till the address use SSL (means the HTTPS behind your url)
The loading be late so the playing be late / or even not start.
So i usually do this:
HTML
<audio id="notifysound" src="notify.mp3" autobuffer preload="auto" style="visibility:hidden;width:0px;height:0px;z-index:-1;"></audio>
JAVASCRIPT (Generally)
var theSound = document.getElementById("notifysound");
theSound.play();
And the most safe if i want sure it be played when i notify is :
JAVASCRIPT (In your case)
function notifyme(theTitle,theBody) {
theTitle=theTitle || 'Title';
theBody=theBody || "Hi. \nIt is notification!";
var theSound = document.getElementById("notifysound");
if ("Notification" in window && Notification) {
if (window.Notification.permission !== "granted") {
window.Notification.requestPermission().then((result) => {
if (result != 'denied') {
return notifyme(theTitle,theBody);
} else {
theSound.play();
}
});
} else {
theSound.play();
try {
var notification = new Notification(theTitle, {
icon: 'icon.png',
body: theBody
});
notification.onclick = function () {
window.focus();
};
}
catch(err) {
return;
}
}
} else {
theSound.play();
}
}
(and just hope it be played. because even possible to volume or some customization make it failed.)
to bypass new autoplay policy :
create a button that can play the sound, hide it and trigger the sound with :
var event = new Event('click');
playBtn.dispatchEvent(event);
EDIT
assuming you have :
let audioData = 'data:audio/wav;base64,..ᴅᴀᴛᴀ...'; // or the src path
you can use this function to trigger whenever you want without appending or create element to the DOM:
function playSound() {
let audioEl = document.createElement('audio');
audioEl.src = audioData;
let audioBtn = document.createElement('button');
audioBtn.addEventListener('click', () => audioEl.play(), false);
let event = new Event('click');
audioBtn.dispatchEvent(event);
}
usage :
just playSound()
EDIT 2
I re test my code and it does'nt work hum ... weird
I have used javascript Audio() before, but now I need to add some reverb effect in the audio and I am using reverb.js which uses the AudioContext api. I have the start property available, but no pause property? How do I pause or stop the audio??
Here is my code:
<script src="http://reverbjs.org/reverb.js"></script>
<script>
// 1) Setup your audio context (once) and extend with Reverb.js.
var audioContext = new (window.AudioContext || window.webkitAudioContext)();
reverbjs.extend(audioContext);
// 2) Load the impulse response; upon load, connect it to the audio output.
var reverbUrl = "http://reverbjs.org/Library/SaintLawrenceChurchMolenbeekWersbeekBelgium.m4a";
var reverbNode = audioContext.createReverbFromUrl(reverbUrl, function() {
reverbNode.connect(audioContext.destination);
});
// 3) Load a test sound; upon load, connect it to the reverb node.
var sourceUrl = "./sample.mp3";
var sourceNode = audioContext.createSourceFromUrl(sourceUrl, function() {
sourceNode.connect(reverbNode);
});
</script>
Play
Stop
Also, I tried using stop(), and it works, but when I fire start() after clicking on stop, the start() doesn't work. Can you you help me out with a solution??
You can use the suspend() and resume() methods of AudioContext to pause and resume your audio: https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/suspend
One way to implement this with a single button for play/pause/resume, would be to add a function that controls the player state. For example:
let started = false;
function pauseOrResume() {
if (!started) {
sourceNode.start();
started = true;
document.getElementById("pauseButton").innerHTML = 'Pause';
} else if (audioContext.state === 'running') {
audioContext.suspend().then(function () {
document.getElementById("pauseButton").innerHTML = 'Resume';
});
} else if (audioContext.state === 'suspended') {
audioContext.resume().then(function () {
document.getElementById("pauseButton").innerHTML = 'Pause';
});
}
}
And replace your existing "Play" button with:
<a id="pauseButton" href="javascript:pauseOrResume()">Play</a>
This does the following:
If the audio hasn't yet been started, the link will say "Play".
If the user clicks "Play", the audio will start playing and the text of the link will change to "Pause".
If the user clicks "Pause" while the audio is playing, it will be paused, and the text of the link will change to "Resume".
I am trying to make a custom video. I can get my functions to work. However when I have two event listeners together:
e.g. video.ontimeupdate
only the bottom one will operate when I play the video. Is there a better way for me to write my functions, so that I do not have this problem?
Event listeners
time.addEventListener("timeupdate", currentTime, true);
video.ontimeupdate = function() {currentTime()};
seek.addEventListener("timeupdate", progressBarUpdate, true);
video.ontimeupdate = function() {progressBarUpdate()};
Function code example
// Updating the progress bar function
function progressBarUpdate() {
// Calculate the progress bar value
var value = (100 / video.duration) * video.currentTime;
// Update the progress bar value
seek.value = value;
}
There are two different JavaScript mechanisms for registering event handlers:
time.addEventListener("timeupdate", currentTime, true); // W3C DOM Standard
video.ontimeupdate = function() { currentTime() }; // Event handling property
When you use a property (ontimeupdate) and you give it a value, that value will be overwritten when you set that property to another value.
So, when you do this:
video.ontimeupdate = function() {currentTime()};
It gets overridden by this later:
video.ontimeupdate = function() { progressBarUpdate() };
To prevent this from happening, use the more modern W3C DOM Level 2 event handling model that uses addEventListener
video.addEventListener("timeupdate", currentTime);
video.addEventListener("timeupdate", progressBarUpdate);
This will register both functions as callbacks to the timeupdate event.
Additionally, there is a third parameter for addEventListener (a boolean) which indicates whether you want the callback to fire during the capture phase (true) or the bubbling phase (false). It's rather unusual to need the capture phase (it's not supported in IE until IE 9), so you may want to modify your existing true values to false or just omit the third argument as false is the default.
Here's a working example that actually shows 3 event handlers all tied into the timeupdate event (make sure to scroll down in the snippet window to see the messages):
var videoElement = null;
var current = null
var duration = null;
var div1, div2;
window.addEventListener("DOMContentLoaded", function(){
// Get DOM References to media element:
videoElement = document.getElementById('bikeSafe');
// ...to video span elements:
current = document.getElementById('current');
duration = document.getElementById('duration');
div1 = document.getElementById("timeUpdate1");
div2 = document.getElementById("timeUpdate2");
// Wire Up Video to use its API:
videoElement.addEventListener("play", setCounter);
videoElement.addEventListener("ended", endVideo);
videoElement.addEventListener("durationchange", updateStatus);
videoElement.addEventListener("timeupdate", setCounter);
videoElement.addEventListener("timeupdate", updateDiv1);
videoElement.addEventListener("timeupdate", updateDiv2);
});
// Video API:
function updateDiv1(){ div1.innerHTML = "Hello from timeupdate event handler!" }
function updateDiv2(){ div2.innerHTML = "Hello from different timeupdate event handler!" }
// Set the value for the current position in the video
function setCounter() {
// This function is wired up to the video element's timeupdate event, which
// fires when the current time value changes.
current.innerHTML = (videoElement.duration - videoElement.currentTime).toFixed(3);
}
function endVideo() {
// Reset video back to beginning when it ends
videoElement.currentTime = 0;
};
function updateStatus() {
// This will fire when the video's durationchange event fires
// and that will happen upon the successful loading of the image
// for the first time when it becomes known how long the duration
// of the video is.
current.innerHTML = videoElement.duration.toFixed(3);
duration.innerHTML = videoElement.duration.toFixed(3);
};
video { width:40%; }
<video id="bikeSafe" width="400" controls>
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
<p>Your browser does not support HTML5 video.</p>
</video>
<p>
Time Remaining: <span id="current"></span> |
Total Length: <span id="duration"></span>
</p>
<div id="timeUpdate1"></div>
<div id="timeUpdate2"></div>
video.ontimeupdate is similar to window.onload. They are properties that are updated. The most recent function definition for them will be executed. Use addEventListener()
video.addEventListener("timeupdate", currentTime, true);
video.addEventListener("timeupdate", progressBarUpdate, true);
Here is a snippet showing the problem with using window.onload syntax.
window.onload = function(){
console.log('Window loaded #1'); // Will not excecute
}
window.onload = function(){
console.log('Window loaded #2'); // Window loaded #2
}
I have an HTML audio player like this:
<audio id="audioPlayer" controls>
<source src="test.mp3">
</audio>
I want to display some images in sync the audio file, including when the user is moving the seekbar.
However, I can't find a way to check whether user is currently using the audio seekbar.
I have tried to use the timeupdateevent with no success: the code below works only when user seeks back in time.
var audioPlayer = document.getElementById('audioPlayer');
var lastUpdateTime;
audioPlayer.addEventListener('timeupdate', function() {update();});
function update() {
if ( audioPlayer.currentTime - lastUpdateTime < 0 )
console.log("seeking");
lastUpdateTime = audioPlayer.currentTime;
}
I am looking for something working on "recent" browsers (e.g. IE10+).
It's a bit hacky but works:
Version with jQuery:
var $audio = $( '#myAudio' );
var onPause = false;
// Pause event helps us to know is player playing or not
$audio.on( 'pause', function() {
onPause = true;
setTimeout(function() {
onPause = false;
});
});
$audio[0].on( 'timeupdate', function(e) {
// trick to get current pause state
setTimeout(function(){
// checks if player paused and not last timeupdate event call
if ( $audio[0].paused && !onPause ) {
// Fire event then user is changing seek bar
$audio.trigger( 'userSeeking' );
}
});
});
$audio.on( 'userSeeking', function(){
// do some magic
});
Version with pure javascript:
var audio = document.getElementById( 'myAudio' );
var onPause = false;
var seek = false;
// Pause event helps us to know is player playing or not
audio.addEventListener( 'pause', function(e) {
onPause = true;
setTimeout(function() {
onPause = false;
});
});
audio.addEventListener( 'timeupdate', function(e) {
// trick to get current pause state
setTimeout(function(){
seek = false;
// checks if player paused and not last timeupdate event call
if ( $audio[0].paused && !onPause ) {
seek = true;
// Fire event then user is changing seek bar
}
// or you can return current state of seeking here
});
});
And here is working example ( codepen using jQuery version ):
http://codepen.io/GomatoX/pen/ZYpWbN
In order to get an HTML5 animation playing with sound on an idevice, I've made a div the size of the entire browser named "theScreen", and use the following code:
audioCont.prototype.iCrapLoadPlayThrough = function () {
if (this.supported) {
theScreen = document.getElementById("theScreen");
var self = this;
theScreen.addEventListener('touchstart', function(){self.iCrapClickedLoadPlayThrough();}, false);
return(1);
} else {
return(0); // Not supported
}
};
audioCont.prototype.iCrapClickedLoadPlayThrough = function () { // Check if supported, then load the audio file
var self = this;
theScreen.removeEventListener('touchstart', function(){self.iCrapClickedLoadPlayThrough();}, false);
this.addCanPlayThrough();
this.load();
}
Now this works, and the sound/animation starts when the user taps on the screen. The problem is, if they tap on it again the sound stops, and each repeat tap you hear a few ms of audio. Does anyone know why?
It's not removing the event listener because it's an anonymous function. Remove the anonymous function and just have the function name instead
theScreen.addEventListener('touchstart',self.iCrapClickedLoadPlayThrough,false)
theScreen.removeEventListener('touchstart',self.iCrapClickedLoadPlayThrough,true)
I've found a solution to the problem:
theScreen.addEventListener('touchstart', eventID=function() {self.iCrapClickedLoadPlayThrough();}, false);
then
theScreen.removeEventListener('touchstart', eventID, false);