playing multiple audio files - javascript

I am trying to create a playlist with the code below but I seem to be getting some errors. Firebug is saying that the play() is not a function. please help I have spent half of my day trying to find a solution. Here is my code:
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script>
var current, playlist;
current = 0;
function() {
current++;
var songs = Array("en_ra1.mp3", "en_ra2.mp3", "en_ra3.mp3", "en_ra0.mp3");
playlist = songs.length;
if (current == playlist) {
//do nothing or stop
} else {
this.playOptions = document.getElementById("audio").src = songs[current];
this.playOptions.play();
}
}
</script>
</head>
<body>
<audio id="audio" onended="loadplaylist()" src="ny_option1.mp3" controls ></audio>
Note:when I include the autoplay attribute it's works just fine despite the error showing in firebug console.

I'm not seeing where you declare the loadplaylist function, presumably a typo
in your function you are setting this.playOptions to the string returned from the array, not the player, I think your function should read something like this:
function loadplaylist() {
current++;
var songs = Array("en_ra1.mp3", "en_ra2.mp3", "en_ra3.mp3", "en_ra0.mp3");
playlist = songs.length;
if (current == playlist) {
//do nothing or stop
} else {
this.playOptions = document.getElementById("audio");
this.playOptions.src = songs[current];
this.playOptions.play();
}
}

Related

read the word in a dictionary page

I am not a programmer! Anyway; I am working on a dictionary app, I need the user to be able to listen to the word when he clicks (or click a small button next to it). Every word is on its own p tag.
My approach was to give the p tag an id equal to the word,so for the word apple the p id will be id="apple", and the mp3 file name is "apple.mp3".
I need a general script (for the whole page) that grabs the id of the clicked element and push it into an embed inner html function that embeds an audio tag with the src="the clicked id.mp3" and play it.
Here what I was trying, but obviously I am missing the correct syntax
<!DOCTYPE html>
<html>
<head>
<title>Get ID of Clicked Element using JavaScript</title>
</head>
<body>
<button id='cat' >cat</button>
<button id='dog' >dog</button>
<script>
document.addEventListener('click', function(e) {
alert(e.target.id);
});
function playSound(soundfile) {
document.getElementById("the grapped Id").innerHTML=
"<embed src= the grapped id""+soundfile+"\" hidden=\"false\" autostart=\"true\" loop=\"false\" />";
}
</script>
</body>
</html>
Some notes:
Instead of id use data-* as more suitable attribute for such tasks.
Create audio elements using the Audio() constructor.
Keep loaded sounds in the memory to reduce the number of server requests and improve user experience.
<!DOCTYPE html>
<html>
<head>
<title>Click a word to listen it</title>
</head>
<body>
<p data-sound="cat">cat</p>
<p data-sound="dog">dog</p>
<script>
var sounds = {};
function loadSound(name) {
if (sounds[name]) {
return sounds[name];
}
var file = '/sounds/' + name + '.mp3',
sound = new Audio(file);
sound.onerror = function() {
alert('File not found: ' + file);
};
sound.onloadedmetadata = function() {
sounds[name] = sound;
};
return sound;
}
function playSound(name) {
var sound = loadSound(name);
if (sound.currentTime > 0) {
sound.pause();
sound.currentTime = 0;
}
sound.play();
}
document.addEventListener('click', function(e) {
if (e.target.dataset && e.target.dataset.sound) {
playSound(e.target.dataset.sound);
}
});
</script>
</body>
</html>

Controlling MP4 Playback using javascript

I am trying to clone the following site:
https://www.apple.com/mac-pro/
I am still in the prototyping phase and the big ticket item I am trying to figure out is how they are playing their MP4 file backwards when you scroll up the page. If you scroll down the page a few steps and then back up, you will see what I mean.
So far I have tried the following techniques:
Tweening currentTime property of video element
Using requestAnimationFrame and using the timestamp in the callback to update the currentTime property to the desired value
Using the requestAnimationFrame technique, I am now getting a partially usable result in every browser other than Chrome. Chrome is ok if you want to rewind maybe .5 seconds, but any more than that and it will get jumpy.
I have also made the following discoveries:
Chrome hates trying to rewind an MP4 file
As much as Chrome hates rewinding MP4 files, also make sure that you don't have an audio track on your video file. It will make it even slower.
So I feel I have a pretty good understanding of the options available to me, but the one thing that makes me think I am missing something is that the Apple website functions ok in Chrome.
I have started debugging their code which is located at:
https://images.apple.com/v/mac-pro/home/b/scripts/overview.js
And from what I can tell they seem to be using requestAnimationFrame, but I can't understand why they are getting a better result.. Does anyone have any ideas on how to achieve this effect?
BTW - I understand that videos are not really meant to be played backwards and they will never play predictably backwards. I have even had occasions on the Apple website where the rewinding can be jerky. But they still have good 2-3 second rewind transitions and the result is definitely acceptable.
Here is my relevant javascript and HTML so far..
var envyVideo, currentVideoTrigger = 0,
currentIndicator, startTime, vid, playTimestamp, playTo, playAmount, triggeredTime, rewindInterval;
$(function() {
vid = document.getElementById("envy-video");
$("#play-button").click(function() {
vid.play();
});
$("#rewind-button").click(function() {
vid.pause();
playTo = parseFloat($("#play-to-time").val());
playAmount = playTo - vid.currentTime;
triggeredTime = vid.currentTime;
requestAnimationFrame(rewindToPointInTime);
});
});
function rewindToPointInTime(timestamp) {
if (!playTimestamp) playTimestamp = timestamp;
var timeDifference = (timestamp - playTimestamp) / 1000;
vid.currentTime = triggeredTime + (playAmount * (timeDifference / Math.abs(playAmount)));
if (vid.currentTime > playTo) {
requestAnimationFrame(rewindToPointInTime);
} else {
playTimestamp = null;
playAmount = null;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Rhino Envy</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="./js/envy.js"></script>
<link rel="stylesheet" href="./css/envy.css">
</head>
<body;
<div id="envy-video-container">
<video id="envy-video" src="./videos/prototype_animation.mp4"></video>
</div>
<div id="video-controls">
<p id="video-current-time"></p>
<div class="video-control"><button id="rewind-button">rewind to</button><input type="text" id="play-to-time" placeholder="forward time" value="0"></div>
<button id="play-button">play</button>
</div>
<ul id="envy-steps">
<li id="envy-step-indicator-1"></li>
<li id="envy-step-indicator-2"></li>
<li id="envy-step-indicator-3"></li>
</ul>
<section id="envy-full-range">
<div id="envy-1-door-link"></div>
<div id="envy-2-door-link"></div>
<div id="envy-3-door-link"></div>
</section>
</body>
</html>
One solid way I can think of, would be to use two videos : one in normal direction, and the other one reversed.
You could then simply switch between which video is to be played, and only update the currentTime of the hidden one in the background.
With this solution, you can even rewind audio !
To reverse a video, you can use ffmpeg's command
ffmpeg -i input.mp4 -vf reverse -af areverse reversed.mp4
Note: You may feel some gaps at the switch, which could probably be leveraged by using a single visible video element, fed from the other's element streams, but I'll leave it for an update, I'm short on time r.n.
const vids = document.querySelectorAll('video');
vids.forEach(v => {
v.addEventListener('loadedmetadata', canplay);
v.addEventListener('timeupdate', timeupdate);
});
let visible = 0;
function timeupdate(evt) {
if (this !== vids[visible]) return;
let other = (visible + 1) % 2;
vids[other].currentTime = this.duration - this.currentTime;
}
document.getElementById('switch').onclick = e => {
visible = (visible + 1) % 2;
show(vids[visible]);
}
// waith both vids have loaded a bit
let loaded = 0;
function canplay() {
if (++loaded < vids.length) return;
hide(vids[1]);
show(vids[0]);
}
function show(el) {
el.muted = false;
const p = el.play();
el.style.display = 'block';
const other = vids[(visible + 1) % 2];
// only newest chrome and FF...
if (p && p.then) {
p.then(_ => hide(other));
} else {
hide(other);
}
}
function hide(el) {
el.muted = true;
el.pause();
el.style.display = 'none';
}
document.getElementById('pause').onclick = function(e) {
if (vids[visible].paused) {
this.textContent = 'pause';
vids[visible].play();
} else {
this.textContent = 'play';
vids[visible].pause();
}
}
<button id="switch">switch playing direction</button>
<button id="pause">pause</button>
<div id="vidcontainer">
<video id="normal" src="https://dl.dropboxusercontent.com/s/m2htty4a8a9fel1/tst.mp4?dl=0" loop="true"></video>
<video id="reversed" src="https://dl.dropboxusercontent.com/s/lz85k8tftj2j8x6/tst-reversed.mp4?dl=0" loop="true"></video>
</div>

Display several background videos

I'm trying to display different background videos with Javascript and with createElement method to only have one video tag node. By clicking on a link, the video is well displayed but not the others. I also checked the DOM Elements and both elements (id and src) of both <video> + <source> tags have been well switched (movie1 > movie2). It looks like the browser keep the first video even if the elements have been well modified in the DOM Elements.
<head>
<script>
var movieNow = "";
function playVideo(movie, mp4) {
if (movieNow!="") {
document.getElementById(movieNow).pause();
document.getElementById(movieNow).style.display="none";
document.getElementById(movieNow).id = movie;
document.getElementById('mysource').src = "videos/"+mp4+".mp4";
document.getElementsByTagName("Video").play();
document.getElementsByTagName("Video").style.display="block";
} else {
bckMovie = document.createElement("video");
bckMovie.id = movie;
bckMovie.className = "myvideo";
bckMovie.innerHTML = "<source src='videos/"+mp4+".mp4' type='video/mp4' id='mysource'>";
document.body.appendChild(bckMovie);
document.getElementById(movie).style.display="block";
document.getElementById(movie).play();
}
movieNow = movie;
}
</script>
<body>
Movie 1
Movie 2
...
</body>
Well you have some logical problems... Please examine this code at JsFiddle, that seems works as you need. https://jsfiddle.net/o5fdqurw/2/
<head>
<script>
var movieNow = "";
function playVideo(mp4) {
var movieNow = document.getElementById("movie");
if (movieNow !== null) {
movieNow.pause();
movieNow.style.display="none";
document.getElementById('mysource').src = "videos/"+mp4+".mp4";
movieNow.play();
movieNow.style.display="block";
} else {
bckMovie = document.createElement("video");
bckMovie.id = "movie";
bckMovie.className = "myvideo";
bckMovie.innerHTML = "<source src='videos/"+mp4+".mp4' type='video/mp4' id='mysource'>";
document.body.appendChild(bckMovie);
document.getElementById("movie").style.display="block";
document.getElementById("movie").play();
}
}
movieNow = movie;
</script>
<body>
Movie 1
Movie 2
...
</body>

Audio up and down and .currentTime HTML5 / Javascript

Have an issue with some code.. I can't find anything wrong with it and appears to be identical with my other code that does work. Just the volume up and volume down and the goToChorus that i'm having trouble. Any help is appreciated!
<!DOCTYPE html>
<html>
<head>
<title>Slider + Play/Pause</title>
<script>
"use strict";
/*function playMusic() {
document.getElementById("mediaClip").play();
}*/
var mediaClip = document.getElementbyId("mediaClip");
var volume1 = document.getElementbyId("volume1").value;
function playPause() {
var mediaClip = document.getElementById("mediaClip");
if (mediaClip.paused) {
mediaClip.play();
} else {
mediaClip.pause();
}
}
function change() {
var button1 = document.getElementById("button1");
if (button1.value==="Play") button1.value = "Pause";
else button1.value = "Play";
}
function setVolume() {
var mediaClip = document.getElementById("mediaClip");
mediaClip.volume = document.getElementById("volume1").value;
}
function backStart() {
document.getElementById("mediaClip").currentTime = 0;
}
function upVolume() {
if (mediaClip.volume < 1)
{
mediaClip.volume += 0.1;
}
}
function downVolume() {
if (mediaClip.volume > 0)
{
mediaClip.volume -= 0.1;
}
}
function goToChorus() {
mediaClip.currenTime = 55;
}
</script>
</head>
<body onload="init()">
<audio id="mediaClip" src="takeMeToChurchHozier.mp3" controls>
<p>Your browser does not support the audio element</p>
</audio>
<br/>
<input onclick="change();playPause()" type="button" value="Play" id="button1">
<input type="range" onchange="setVolume()" id='volume1' min=0 max=1 step=0.01 value='1'/>
<br/>
<button onclick ="backStart()">Reset</button>
<br/>
<button onclick="upVolume()">Volume up 10%</button>
<button onclick="downVolume()">Volume down 10%</button>
<br/>
<input type="button" value="Click for chorus" onclick="goToChorus()">
</body>
</html>
Okay, first things first. Take your JavaScript code and get it out of the <head> element. This breaks things like
var mediaClip = document.getElementbyId("mediaClip");
because it tries to look for the element "mediaClip" before the browser has even gotten down to that line of code and created that DOM element. Having the JavaScript AFTER the HTML code will allow the DOM elements to be created by the browser, then your code will run.
Second, you have a few typos in your JavaScript. Twice you try to use the method getElementbyId (notice the lower-case b). Changing these to getElementById should fix it.
Okay, so now your code will run after DOM load, and will find the elements properly. This should allow the rest of your functions to run, since they all rely on the variable mediaClip being set properly at the beginning.
One more thing: you need to add something inside of upVolume() and downVolume() to change the value of the slider volume1. Right now, when you click the up/down buttons the volume will update, but the slider doesn't move.
Here's a JSFiddle of your code that I got to work after the above modifications: http://jsfiddle.net/vcxsn6q7/

How can I get a list of video cameras attached in my computer using JavaScript?

I want to display a list of video cameras attached to the user's computer, and when they select one, display streaming video from that camera in an HTML5 <video> tag.
How can I get a list of the video cameras attached to the user's computer?
Only works in chrome and edge
<script>
navigator.mediaDevices.enumerateDevices().then(function (devices) {
for(var i = 0; i < devices.length; i ++){
var device = devices[i];
if (device.kind === 'videoinput') {
var option = document.createElement('option');
option.value = device.deviceId;
option.text = device.label || 'camera ' + (i + 1);
document.querySelector('select#videoSource').appendChild(option);
}
};
});
</script>
<select id="videoSource"></select>
Perhaps Navigator.getUserMedia() (uses WebRTC under the hood) is what you're looking for, though I don't see anything that will directly tell you what devices are available (the list of devices isn't exposed to your codeā€”it's presented to the user when asking for permission to access available hardware).
Also note the browser support: Chrome 21+, Firefox 20+, Opera 12+, no support for IE and possibly Safari.
try out this...
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="author" content="Victor Stan">
<meta name="description" content="Get multiple video streams on one page. Adapted from code by Muaz Khan">
<title>Video Camera</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js" ></script>
<style type="text/css" media="screen">
video {
border:1px solid gray;
}
</style>
</head>
<body>
<script>
if (!MediaStreamTrack) document.body.innerHTML = '<h1>Incompatible Browser Detected. Try <strong style="color:red;">Chrome Canary</strong> instead.</h1>';
var videoSources = [];
MediaStreamTrack.getSources(function(media_sources) {
console.log(media_sources);
alert('media_sources : '+media_sources);
media_sources.forEach(function(media_source){
if (media_source.kind === 'video') {
videoSources.push(media_source);
}
});
getMediaSource(videoSources);
});
var get_and_show_media = function(id) {
var constraints = {};
constraints.video = {
optional: [{ sourceId: id}]
};
navigator.webkitGetUserMedia(constraints, function(stream) {
console.log('webkitGetUserMedia');
console.log(constraints);
console.log(stream);
var mediaElement = document.createElement('video');
mediaElement.src = window.URL.createObjectURL(stream);
document.body.appendChild(mediaElement);
mediaElement.controls = true;
mediaElement.play();
}, function (e)
{
alert('Hii');
document.body.appendChild(document.createElement('hr'));
var strong = document.createElement('strong');
strong.innerHTML = JSON.stringify(e);
alert('strong.innerHTML : '+strong.innerHTML);
document.body.appendChild(strong);
});
};
var getMediaSource = function(media) {
console.log(media);
media.forEach(function(media_source) {
if (!media_source) return;
if (media_source.kind === 'video')
{
// add buttons for each media item
var button = $('<input/>', {id: media_source.id, value:media_source.id, type:'submit'});
$("body").append(button);
// show video on click
$(document).on("click", "#"+media_source.id, function(e){
console.log(e);
console.log(media_source.id);
get_and_show_media(media_source.id);
});
}
});
}
</script>
</body>
</html>
JavaScript cannot access your cameras to return a list. You will need to use a Flash SWF to get the camera information and pass it back to your page's JavaScript.
EDIT:
to those who downvoted. These methods will not give him a dropdown list of available cameras. If it does, please post a link or code. At the current date, the only way to get a list of cameras (which is what his questions was) is to use Flash (or possibly silverlight, but Flash has much broader install coverage). I've edited my question to be a little more specific in terms of getting the list versus accessing a camera.

Categories