I FIGURED OUT A FIX FOR THIS MYSELF, PLEASE DISREGARD THIS.
I am working on a website that contains a video player with toggleable subtitles. Since I found out that VTT files cannot be displayed with local files, I decided to use a different set of code to get around it.
I have a button that is supposed to turn the subtitles on or off. While pressing the button once creates a subtitle line as it should, turning it off a second time doesn't make them disappear, it just triggers this error:
VM513:84 Uncaught DOMException: Failed to execute 'removeCue' on 'TextTrack': The specified cue is not listed in the TextTrack's list of cues.
at <anonymous>:84:8
at Array.map (<anonymous>)
at subtitles (<anonymous>:79:51)
at HTMLButtonElement.onclick (https://www.w3schools.com/html/tryit.asp?filename=tryhtml5_audio_all:1:220)
As a result, a third click results in a second copy of the subtitle track spawning, and so on.
Please help me find a way to fix this!
Code:
<html>
<head>
<title>Subtitle Toggle</title>
</head>
<center>
<video controls id="movie">
<source src="https://www.w3schools.com/html/movie.mp4" type="video/mp4">
</video><br/><br/>
<button onclick="subtitles()">Toggle Subtitles</button>
</center>
<!-- Subtitles -->
<script type="text/vtt" id="sub">
WEBVTT
1
00:00:01.000 --> 00:00:03.000
Subtitle line 1
2
00:00:04.000 --> 00:00:05.000
Subtitle line 2
3
00:00:06.000 --> 00:00:10.000
Subtitle lines 3
and 4
</script>
<script>
var subs = 0;
var trk = movie.addTextTrack('subtitles');
trk.mode = "showing";
// Get around "VTT not displaying" bug
function parse_timestamp(s)
{
// Relaxing the timestamp format:
var match = s.match(/^(?:([0-9]+):)?([0-5][0-9]):([0-5][0-9](?:[.,][0-9]{0,3})?)/);
if (match == null)
{
throw 'Invalid timestamp format: ' + s;
}
var hours = parseInt(match[1] || "0", 10);
var minutes = parseInt(match[2], 10);
var seconds = parseFloat(match[3].replace(',', '.'));
return seconds + 60 * minutes + 60 * 60 * hours;
}
function quick_and_dirty_vtt_or_srt_parser(vtt)
{
var lines = vtt.trim().replace('\r\n', '\n').split(/[\r\n]/).map(function(line)
{
return line.trim();
});
var cues = [];
var start = null;
var end = null;
var payload = null;
for (var i = 0; i < lines.length; i++)
{
if (lines[i].indexOf('-->') >= 0)
{
var splitted = lines[i].split(/[ \t]+-->[ \t]+/);
if (splitted.length != 2)
{
throw 'Error when splitting "-->": ' + lines[i];
}
// Already ignoring anything past the "end" timestamp (i.e. cue settings).
start = parse_timestamp(splitted[0]);
end = parse_timestamp(splitted[1]);
}
else if (lines[i] == '')
{
if (start && end)
{
var cue = new VTTCue(start, end, payload);
cues.push(cue);
start = null;
end = null;
payload = null;
}
}
else if (start && end)
{
if (payload == null)
{
payload = lines[i];
}
else
{
payload += '\n' + lines[i];
}
}
}
if (start && end)
{
var cue = new VTTCue(start, end, payload);
cues.push(cue);
}
return cues;
}
function subtitles()
{
subs ++;
quick_and_dirty_vtt_or_srt_parser(sub.innerHTML).map(function(cue)
{
if (subs == 1) trk.addCue(cue); else
{
subs = 0;
trk.removeCue(cue);
}
});
}
</script>
</html>
this is my first question here!
im trying to make a website that show videos that i make and i want my viewers can see a preview of video when they hover mouse on the a element or element .
i just do it but i have some problems and questions. lemme show you code example first and then i ask my questions.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="thumbs" style="width:216px;height:468px;border: 5px solid blue;background-color:red;"><canvas onmouseover="getid1(this);" onmouseout="getid2(this);" id="canvas1"></canvas></div>
<script>
var thumbsList = [];
var delay = 100;
var i = 0;
var video = document.createElement("video");
var a = 0;
var m = document.getElementById("canvas1");
var mtx = m.getContext("2d");
var generate = true;
var animstop = false;
var vidFrames = 64;
m.width = 216;
m.height = 468;
video.preload = "auto";
video.src = "aaaa.mp4";
function stranim(bb){
if(generate){
animstop = false;
video.currentTime = i;
generateVid();
generate = false;
}else{
animstop = false;
startAnim();
}
}
function stpanim(bb) {
clearTimeout();
animstop = true;
mtx.drawImage(thumbsList[0], 0, 0);
}
// if i replace this section with generateVid() the code is working
/*video.addEventListener('seeked', function() {
var d = (video.duration / vidFrames) * 2;
generateThumbnail();
i += video.duration / vidFrames;
if (i <= video.duration) {
video.currentTime = i;
generateVid()
if(d == i){
startAnim();
}
}
});*/
function generateVid() {
var d = (video.duration / vidFrames) * 2;
generateThumbnail();
i += video.duration / vidFrames;
if (i <= video.duration) {
video.currentTime = i;
generateVid();
if(d == i){
startAnim();
}
}
}
function generateFirstThumbnail() {
var c = document.createElement("canvas");
var ctx = c.getContext("2d");
c.width = 216;
c.height = 468;
ctx.drawImage(video, 0, 0, 216, 468);
thumbsList.push(c);
thumbs.appendChild(m);
mtx.drawImage(thumbsList[0], 0, 0);
i += video.duration / vidFrames;
}
function generateThumbnail() {
var c = document.createElement("canvas");
var ctx = c.getContext("2d");
c.width = 216;
c.height = 468;
ctx.drawImage(video, 0, 0, 216, 468);
thumbsList.push(c);
}
function startAnim() {
var currentFrame = 0;
function anim() {
if(currentFrame != (vidFrames - 1) && animstop == false){
currentFrame = (currentFrame + 1) % thumbsList.length;
mtx.drawImage(thumbsList[currentFrame], 0, 0);
setTimeout(anim, delay);
}
}
anim();
}
function getid1(obj) {
stranim(obj.id)
}
function getid2(obj) {
stpanim(obj.id)
}
window.onload = function(){
generateFirstThumbnail();
};
</script>
</body>
</html>
the questions are :
1- why my generatevid() function is not working? this function is just like that eventlistener.
2- i want to add this code on a class to use it on multiple videos but idk how and i think this cant be done with js classes.( i search so many sites for it)
3-i can use 2d arrays for saving my video previews but is it dont make my site lower on load speed or it dont fill the ram of user?
4-there is any way that i make this code better and easyer?(i dont want to use jquery for no reason).
For a pure js approach you can check this not mine btw: https://codepen.io/tepexic/pen/BazYgJe
html:
<input type="file" accept="video/*" id="input-tag"/>
<hr>
<video controls id="video-tag">
<source id="video-source" src="splashVideo">
Your browser does not support the video tag.
</video>
JS
const videoSrc = document.querySelector("#video-source");
const videoTag = document.querySelector("#video-tag");
const inputTag = document.querySelector("#input-tag");
inputTag.addEventListener('change', readVideo)
function readVideo(event) {
console.log(event.target.files)
if (event.target.files && event.target.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
console.log('loaded')
videoSrc.src = e.target.result
videoTag.load()
}.bind(this)
reader.readAsDataURL(event.target.files[0]);
}
}
But for other approach i would probably use http://ffmpeg.org/ library to generate a preview video (e.g 10 seconds video) and https://videojs.com library for video player so you have a control when user hover the player.
I just did some test on your code, your video is getting seeked only once. No event is raised after that, which means your thumbnail will remain same.
Here is how I was able to fix it
function generateVid() {
var d = (video.duration / vidFrames) * 2;
generateThumbnail();
i += video.duration / vidFrames;
if (i <= video.duration) {
video.currentTime = i;
console.log("starting seeking");
if(d == i){
startAnim();
}
}
}
video.onseeked = (event) => {
if (animstop == false)
{
setTimeout(generateVid, delay);
}
console.log("seeked");
};
I am trying to write a function that will take an id of a div and play a given video from for example 2/10th of the way through to 3/10th of the way through and return an event so I can do something else.
I am not to clever with events as yet, and the video duration is not working out for me, any help appreciated. I have jQuery installed.
Some improvement since last time...
Updated, just need the listener to work next.
var finished_event = new Event('finished');
$(document).ready(function(){
class Player {
constructor(pos, vid, part, parts){
this.pos = pos;
this.vid = vid;
this.part = part;
this.parts = parts;
}
start(){
var it = this;
var html = '<video class="video-fit" controls>';
html += '<source src="';
html += it.vid;
html += '" type="video/mp4">';
html += '</video>';
$(it.pos).html(html);
var video = $(it.pos + ' video')[0];
video.addEventListener('loadeddata', function(){
var dur = video.duration;
var fra = dur / it.parts;
var beg = it.part * fra;
var end = it.part * (fra + 1);
video.currentTime = beg;
video.play();
video.addEventListener('timeupdate', function() {
if (video.currentTime >= end) {
video.pause();
this.dispatchEvent(finished_event);
}
}, false);
}, false);
return it;
}
}
$('body').click(function(){
let player_1 = new Player('#pos-1', 'videos/576p.mp4', 5, 10);
player_1.start();
let player_2 = new Player('#pos-2', 'videos/576p.mp4', 5, 10);
player_2.start();
let player_3 = new Player('#pos-3', 'videos/576p.mp4', 5, 10);
player_3.start();
let player_4 = new Player('#pos-4', 'videos/576p.mp4', 5, 10);
player_4.start();
//.addEventListener('finished', function(){ console.log('Finished'); }, false)
});
});
The timeupdate event fires a lot, so it could fire multiple times within the this.currentTime >= end check.
Not changing your code too much, you would want to set a playing state/var and on canplay event change timestamp and then play, this would, in turn, trigger a seeked event which then you can set the video as playing, then on timeupdate, check your timing plus is the video playing.. and for the last video you would need to check ended event as it won't enter into your check this.currentTime >= end as end is +1 second.
Then to separate the event functions from the Player class, id would use an array and watch it for changes, then by pushing a function to the array/stack you can then do a check within the function each time its invoked if the stack matches the video length, suppose you could do it other ways.
(function () {
let video =
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/twitter_cat.mp4';
let videos = [
{ id: '#pos-1', video, part: 1, parts: 10 },
{ id: '#pos-2', video, part: 2, parts: 10 },
{ id: '#pos-3', video, part: 3, parts: 10 },
{ id: '#pos-4', video, part: 4, parts: 10 },
];
const playqueue = [];
Object.defineProperty(playqueue, 'push', {
value: function (...args) {
var arr = Array.prototype.push.apply(this, args)
if (typeof args[0] === 'function') args[0]();
return arr;
}
});
function finished_event() {
if (playqueue.length === videos.length) {
console.log('Do something, all videos have stopped playing');
}
}
function video_finished_event(player) {
console.log(
'Do something, ' + JSON.stringify(player) + ' has stopped playing'
);
playqueue.push(finished_event);
}
class Player {
constructor(pos, vid, part, parts) {
this.pos = pos;
this.vid = vid;
this.part = part;
this.parts = parts;
}
start() {
var it = this;
var html = '<video class="video-fit" data-vid="' + it.pos + '" controls>';
html += '<source src="';
html += it.vid;
html += '" type="video/mp4">';
html += '</video>';
$(it.pos).html(html);
var video = $('[data-vid="' + it.pos + '"]')[0];
video.addEventListener(
'loadeddata',
function () {
var fra = video.duration / it.parts;
var beg = it.part * fra;
var end = it.part * (fra + 1);
video.addEventListener('canplay', function () {
if (!this.playing) {
this.currentTime = beg;
this.play();
}
});
video.addEventListener('seeked', function () {
this.playing = true;
});
video.addEventListener('timeupdate', function () {
if (this.playing && this.currentTime >= end) {
this.pause();
this.playing = false;
video_finished_event(it);
}
});
video.addEventListener('ended', function () {
if (this.playing) {
this.pause();
this.playing = false;
video_finished_event(it);
}
})
},
false
);
return it;
}
}
videos.forEach(video => {
video.player = new Player(video.id, video.video, video.part, video.parts);
video.player.start();
});
})();
.videos div {
display: inline-block;
width: calc(25vw - 15px);
height: 100%;
}
.videos div video {
width: 100%;
height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="videos">
<div id="pos-1"></div>
<div id="pos-2"></div>
<div id="pos-3"></div>
<div id="pos-4"></div>
</div>
I suggest you to put an unique id on video, here i choose vpos-1/2/3/4/...
and i display video from beg to end:
var html = '<video ' + 'id="v' + it.pos + '" class="video-fit">';
html += '<source src="';
html += it.vid;
html += '" type="video/mp4">';
html += '</video>';
$(it.pos).html(html);
var video = document.getElementById('v' + it.pos);
$(video).bind('timeupdate', function() {
if(video.currentTime > end){
video.pause();
}
});
$(video).on('play', function() {
video.playbackRate = 1.0;
//calcul the value of beg
video.currentTime = beg;
video.play();//suppress if you have autoplay
});
$(video).bind('ended', function() {
// nothing yet
});
if you want to autoplay and/or display controls i suggest you to add
controls="controls" autoplay
to tag video
if you want to remove video: just do src=''
It stops the video and it saves the memory
I'am working a video tag in angular and HTML5 I can control the timer and tab in HTML5 Now I want to control the circular bar timer in angular js when I click the new tab the circular tab should not move even I mute the sound it should not run.
HTML
<circular-progress id="timer_label" value="value" max="max" iterations="{{iteration}}" animation="{{animation}}" label="{{label}}" ng-click="acceptOrder()"></circular-progress>
<video autoplay onplay="clickplayer()" style="width: 100%;" id="player" ng-style="{ 'width' : width, 'height':height}" onended="endplayer()" fullscreen="true" controls ng-src="{{videoSource | trustUrl }}" onvolumechange="myFunction()" ontimeupdate="document.getElementById('tracktime').innerHTML = Math.floor(this.currentTime) + ' / ' + Math.floor(this.duration);"></video>
Angular JS code
controller
var vm = this,timeout;
vm.value = 0;
vm.max = ($rootScope.durationSize);
vm.animation = "linearEase";
vm.iterations = 60; // Accelerate animation to fit the 1 second timeout function
vm.label = "";
var disp = vm.max;
vm.start = function() {
vm.label = disp;
timeout = $timeout(function() {
disp = disp-1;
vm.value++;
if(disp == 0){
//console.log(disp);
userService.closeCampaign(userId, cid , hIPaddress, browserInfo ,function(response){
console.log(response);
if(response.status == "success"){
console.log($rootScope.videoSource);
if($scope.res.campaigns.type=="appdownload"){
// if($scope.res.campaigns.type=="link" || $scope.res.campaigns.type=="appdownload"){ //cutDown to open new window as empty after click the open link option
$rootScope.redirectlink($scope.res.campaigns.link);
}
$window.location.reload();
}
else{
console.log('error redirect poster');
$window.location.reload();
}
});
}
vm.start();
}, 1000);
};
vm.acceptOrder = function() {
$interval.cancel(disp);
// disp = vm.max - vm.value;
disp = null;
}
vm.start();
I want my web page to beep whenever a user exceeds the maximum character limit of my <textarea>.
Solution
You can now use base64 files to produce sounds when imported as data URI. The solution is almost the same as the previous ones, except you do not need to import an external audio file.
function beep() {
var snd = new Audio("data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
snd.play();
}
beep();
Compatibility
Data URI is supported on almost every browser now. More information on http://caniuse.com/datauri
Demo
http://jsfiddle.net/7EAgz/
Conversion Tool
And here is where you can convert mp3 or wav files into Data URI format:
https://dopiaza.org/tools/datauri/index.php
It's not possible to do directly in JavaScript. You'll need to embed a short WAV file in the HTML, and then play that via code.
An Example:
<script>
function PlaySound(soundObj) {
var sound = document.getElementById(soundObj);
sound.Play();
}
</script>
<embed src="success.wav" autostart="false" width="0" height="0" id="sound1"
enablejavascript="true">
You would then call it from JavaScript code as such:
PlaySound("sound1");
This should do exactly what you want - you'll just need to find/create the beep sound yourself, which should be trivial.
/*if you want to beep without using a wave file*/
var context = new AudioContext();
var oscillator = context.createOscillator();
oscillator.type = "sine";
oscillator.frequency.value = 800;
oscillator.connect(context.destination);
oscillator.start();
// Beep for 500 milliseconds
setTimeout(function () {
oscillator.stop();
}, 100);
The top answer was correct at the time but is now wrong; you can do it in pure javascript. But the one answer using javascript doesn't work any more, and the other answers are pretty limited or don't use pure javascript.
I made my own solution that works well and lets you control the volume, frequency, and wavetype.
//if you have another AudioContext class use that one, as some browsers have a limit
var audioCtx = new (window.AudioContext || window.webkitAudioContext || window.audioContext);
//All arguments are optional:
//duration of the tone in milliseconds. Default is 500
//frequency of the tone in hertz. default is 440
//volume of the tone. Default is 1, off is 0.
//type of tone. Possible values are sine, square, sawtooth, triangle, and custom. Default is sine.
//callback to use on end of tone
function beep(duration, frequency, volume, type, callback) {
var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
if (volume){gainNode.gain.value = volume;}
if (frequency){oscillator.frequency.value = frequency;}
if (type){oscillator.type = type;}
if (callback){oscillator.onended = callback;}
oscillator.start(audioCtx.currentTime);
oscillator.stop(audioCtx.currentTime + ((duration || 500) / 1000));
};
Someone suggested I edit this to note it only works on some browsers. However Audiocontext seems to be supported on all modern browsers, as far as I can tell. It isn't supported on IE, but that has been discontinued by Microsoft. If you have any issues with this on a specific browser please report it.
I wrote a function to beep with the new Audio API.
var beep = (function () {
var ctxClass = window.audioContext ||window.AudioContext || window.AudioContext || window.webkitAudioContext
var ctx = new ctxClass();
return function (duration, type, finishedCallback) {
duration = +duration;
// Only 0-4 are valid types.
type = (type % 5) || 0;
if (typeof finishedCallback != "function") {
finishedCallback = function () {};
}
var osc = ctx.createOscillator();
osc.type = type;
//osc.type = "sine";
osc.connect(ctx.destination);
if (osc.noteOn) osc.noteOn(0); // old browsers
if (osc.start) osc.start(); // new browsers
setTimeout(function () {
if (osc.noteOff) osc.noteOff(0); // old browsers
if (osc.stop) osc.stop(); // new browsers
finishedCallback();
}, duration);
};
})();
jsFiddle.
Using Houshalter's suggestion, I made this simple tone synthesizer demo.
Screenshot
Here is a screenshot. Try the live demo further down in this Answer (click Run code snippet).
Demo code
audioCtx = new(window.AudioContext || window.webkitAudioContext)();
show();
function show() {
frequency = document.getElementById("fIn").value;
document.getElementById("fOut").innerHTML = frequency + ' Hz';
switch (document.getElementById("tIn").value * 1) {
case 0: type = 'sine'; break;
case 1: type = 'square'; break;
case 2: type = 'sawtooth'; break;
case 3: type = 'triangle'; break;
}
document.getElementById("tOut").innerHTML = type;
volume = document.getElementById("vIn").value / 100;
document.getElementById("vOut").innerHTML = volume;
duration = document.getElementById("dIn").value;
document.getElementById("dOut").innerHTML = duration + ' ms';
}
function beep() {
var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
gainNode.gain.value = volume;
oscillator.frequency.value = frequency;
oscillator.type = type;
oscillator.start();
setTimeout(
function() {
oscillator.stop();
},
duration
);
};
frequency
<input type="range" id="fIn" min="40" max="6000" oninput="show()" />
<span id="fOut"></span><br>
type
<input type="range" id="tIn" min="0" max="3" oninput="show()" />
<span id="tOut"></span><br>
volume
<input type="range" id="vIn" min="0" max="100" oninput="show()" />
<span id="vOut"></span><br>
duration
<input type="range" id="dIn" min="1" max="5000" oninput="show()" />
<span id="dOut"></span>
<br>
<button onclick='beep();'>Play</button>
You can clone and tweak the code here:
Tone synthesizer demo on JS Bin
Have fun!
Compatible browsers:
Chrome mobile & desktop
Firefox mobile & desktop
Opera mobile, mini & desktop
Android browser
Microsoft Edge browser
Safari on iPhone or iPad
Not Compatible
Internet Explorer version 11 (but does work on the Edge browser)
This will enable you to play the sound multiple times, in contrast to the top-voted answer:
var playSound = (function beep() {
var snd = new Audio("data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
return function() {
snd.play();
}
})();
playSound(); // Play first time
playSound(); // Play second time
As we read in this answer, HTML5 will solve this for you if you're open to that route. HTML5 audio is supported in all modern browsers.
Here's a copy of the example:
var snd = new Audio("file.wav"); // buffers automatically when created
snd.play();
Now it easy enough with JavaScript AudioContext API. It fully supported by major desktop and mobile web browsers...
let context = null;
const beep = (freq = 520, duration = 200, vol = 100) => {
const oscillator = context.createOscillator();
const gain = context.createGain();
oscillator.connect(gain);
oscillator.frequency.value = freq;
oscillator.type = "square";
gain.connect(context.destination);
gain.gain.value = vol * 0.01;
oscillator.start(context.currentTime);
oscillator.stop(context.currentTime + duration * 0.001);
}
document.querySelector('button').addEventListener('click', function () {
context = new AudioContext();
beep();
});
I wrote a small application that plays music from the Mario game without any audio file, just runtime. In my opinion it’s interesting, you can see the source code and listen it.
Using CSS you can do it if you add the following style to a tag, but you will need a wav file:
<style type="text/css">
.beep {cue: url("beep.wav") }
</style>
var body=document.getElementByTagName("body");
body.className=body.className + " " + "beep";
Here's how I get it to beep using HTML5:
First I copy and convert the windows wav file to mp3, then I use this code:
var _beep = window.Audio("Content/Custom/Beep.mp3")
function playBeep() { _beep.play()};
It's faster to declare the sound file globally and refer to it as needed.
This code supports sequencing of multiple beeps, as well as gradual change in frequency ('ramp' flag). Both examples are given below.
<script>
var audioContext = null;
var oscillatorNode = null;
var stopTime = 0;
function beep (frequency, durationSec, ramp=false)
{
if (oscillatorNode == null) {
audioContext = new (window.AudioContext || window.webkitAudioContext) ();
stopTime = audioContext.currentTime;
oscillatorNode = audioContext.createOscillator();
oscillatorNode.type = "sine";
oscillatorNode.connect (audioContext.destination);
if (ramp) {
oscillatorNode.frequency.setValueAtTime (frequency, stopTime);
}
oscillatorNode.start ();
oscillatorNode.onended = function() {
oscillatorNode = null;
audioContext = null;
}
}
if (ramp) {
oscillatorNode.frequency.linearRampToValueAtTime (frequency, stopTime); // value in hertz
} else {
oscillatorNode.frequency.setValueAtTime (frequency, stopTime); // value in hertz
}
stopTime += durationSec;
oscillatorNode.stop (stopTime);
}
function test1()
{
beep (250, 0.5);
beep (1000, 0.2);
beep (550, 0.5);
}
function test2()
{
beep (50, 2, true);
beep (5000, 2, true);
beep (50, 0, true);
}
</script>
<button onclick='test1()'>Beep!</button>
<button onclick='test2()'>Beep(ramped)!</button>
There's no crossbrowser way to achieve this with pure javascript. Instead you could use a small .wav file that you play using embed or object tags.
function beep(wavFile){
wavFile = wavFile || "beep.wav"
if (navigator.appName == 'Microsoft Internet Explorer'){
var e = document.createElement('BGSOUND');
e.src = wavFile;
e.loop =1;
document.body.appendChild(e);
document.body.removeChild(e);
}else{
var e = document.createElement('AUDIO');
var src1 = document.createElement('SOURCE');
src1.type= 'audio/wav';
src1.src= wavFile;
e.appendChild(src1);
e.play();
}
}
Works on Chrome,IE,Mozilla using Win7 OS.
Requires a beep.wav file on the server.
function Sound(url, vol, autoplay, loop)
{
var that = this;
that.url = (url === undefined) ? "" : url;
that.vol = (vol === undefined) ? 1.0 : vol;
that.autoplay = (autoplay === undefined) ? true : autoplay;
that.loop = (loop === undefined) ? false : loop;
that.sample = null;
if(that.url !== "")
{
that.sync = function(){
that.sample.volume = that.vol;
that.sample.loop = that.loop;
that.sample.autoplay = that.autoplay;
setTimeout(function(){ that.sync(); }, 60);
};
that.sample = document.createElement("audio");
that.sample.src = that.url;
that.sync();
that.play = function(){
if(that.sample)
{
that.sample.play();
}
};
that.pause = function(){
if(that.sample)
{
that.sample.pause();
}
};
}
}
var test = new Sound("http://mad-hatter.fr/Assets/projects/FreedomWings/Assets/musiques/freedomwings.mp3");
test.play();
http://jsfiddle.net/sv9j638j/
Note:put this code in your javascript at the point you want the beep to occur.
and remember to specify the directory or folder where the beep sound is stored(source).
<script>
//Appending HTML5 Audio Tag in HTML Body
$('<audio id="chatAudio"><source src="sound/notify.ogg" type="audio/ogg"><source src="sound/notify.mp3" type="audio/mpeg"><source src="sound/notify.wav" type="audio/wav"></audio>').appendTo('body');
$('#chatAudio')[0].play();
</script>
Reference:http://www.9lessons.info/2013/04/play-notification-sound-using-jquery.html.
I implemented this in a social media i am developing and it works find, a notification like that of facebook when chatting, notifying you that you have a new chat message
<html>
<head>
<script src='https://surikov.github.io/webaudiofont/npm/dist/WebAudioFontPlayer.js'></script>
<script src='https://surikov.github.io/webaudiofontdata/sound/0000_JCLive_sf2_file.js'></script>
<script>
var selectedPreset=_tone_0000_JCLive_sf2_file;
var AudioContextFunc = window.AudioContext || window.webkitAudioContext;
var audioContext = new AudioContextFunc();
var player=new WebAudioFontPlayer();
player.loader.decodeAfterLoading(audioContext, '_tone_0000_JCLive_sf2_file');
</script>
</head>
<body>
<p>Play a note</p>
<hr/>
<p>source</p>
</body>
listen here
https://jsbin.com/lamidog/1/edit?html,output
function beep(freq = 660, duration = 90, vol = 50) {
var context = new(window.AudioContext || window.webkitAudioContext);
const oscillator = context.createOscillator();
const gain = context.createGain();
gain.gain.setValueAtTime(0, context.currentTime);
gain.gain.linearRampToValueAtTime(1, context.currentTime + 0.002);
oscillator.connect(gain);
oscillator.frequency.value = freq;
oscillator.type = "square";
gain.connect(context.destination);
oscillator.start(context.currentTime);
oscillator.stop(context.currentTime + duration * .001);
oscillator.onended = () => context.close();
}
<br>
<center><button onclick="beep()">Beep!</button></center>
You need a sound file to be served from somewhere. Here's the code from Scriptaculous's Sound library:
//Default:
<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>
//For Gecko:
if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>');
else if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('Windows Media') != -1 }))
Sound.template = new Template('<object id="sound_#{track}_#{id}" type="application/x-mplayer2" data="#{url}"></object>');
else if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('RealPlayer') != -1 }))
Sound.template = new Template('<embed type="audio/x-pn-realaudio-plugin" style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>');
else
Sound.play = function(){};
}