I have have code that allows me to input an mp3 file, and output the audio and display a visual representation of the music. (Loading the file is done manually through an input type="file")
I no longer want to load a file from my computer, but instead automatically play the music on page load. The file is called song.mp3.
I not sure how to adjust my code to allow for the automatic play (I would like the visual representation to also work on load).
window.onload = function() {
var file = document.getElementById("thefile");
var audio = document.getElementById("audio");
file.onchange = function() {
var files = this.files;
audio.src = URL.createObjectURL(files[0]);
audio.load();
audio.play();
var context = new AudioContext();
var src = context.createMediaElementSource(audio);
var analyser = context.createAnalyser();
var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext("2d");
src.connect(analyser);
analyser.connect(context.destination);
analyser.fftSize = 256;
var bufferLength = analyser.frequencyBinCount;
console.log(bufferLength);
var dataArray = new Uint8Array(bufferLength);
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
var barWidth = (WIDTH / bufferLength) * 2.5;
var barHeight;
var x = 0;
function renderFrame() {
requestAnimationFrame(renderFrame);
x = 0;
analyser.getByteFrequencyData(dataArray);
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, WIDTH, HEIGHT);
for (var i = 0; i < bufferLength; i++) {
barHeight = dataArray[i];
var r = barHeight + (25 * (i/bufferLength));
var g = 250 * (i/bufferLength);
var b = 50;
ctx.fillStyle = "rgb(" + 0 + "," + 0 + "," + 0 + ")";
ctx.fillRect(x, HEIGHT - barHeight, barWidth, barHeight);
x += barWidth + 1;
}
}
audio.play();
renderFrame();
};
};
#thefile {
position: fixed;
top: 10px;
left: 10px;
z-index: 100;
}
#canvas {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 50%;
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
-o-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
audio {
position: fixed;
left: 10px;
bottom: 10px;
width: calc(100% - 20px);
}
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>JS Audio Visualizer</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="content">
<input type="file" id="thefile" accept="audio/*" />
<canvas id="canvas"></canvas>
<audio id="audio" controls></audio>
</div>
<script src="./script.js"></script>
</body>
</html>
You just need to load and play audio file after you got audio tag from document.
var audio = document.getElementById("audio");
audio.src = URL.createObjectURL("song.mp3");
audio.load();
audio.play();
Because Chrome don't allow autoplay audio onload until user has an interactive with the webpage. So you need to add an hidden autoplay iframe with silence sound.
<iframe src="silence.mp3" allow="autoplay" id="audio" style="display:none"></iframe>
You can get silence sound file from here https://github.com/anars/blank-audio/blob/master/250-milliseconds-of-silence.mp3
Your js
window.onload = function() {
function renderVisual() {
var analyser = context.createAnalyser();
var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext("2d");
src.connect(analyser);
analyser.connect(context.destination);
analyser.fftSize = 256;
var bufferLength = analyser.frequencyBinCount;
console.log(bufferLength);
var dataArray = new Uint8Array(bufferLength);
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
var barWidth = (WIDTH / bufferLength) * 2.5;
var barHeight;
var x = 0;
function renderFrame() {
requestAnimationFrame(renderFrame);
x = 0;
analyser.getByteFrequencyData(dataArray);
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, WIDTH, HEIGHT);
for (var i = 0; i < bufferLength; i++) {
barHeight = dataArray[i];
var r = barHeight + (25 * (i/bufferLength));
var g = 250 * (i/bufferLength);
var b = 50;
ctx.fillStyle = "rgb(" + 0 + "," + 0 + "," + 0 + ")";
ctx.fillRect(x, HEIGHT - barHeight, barWidth, barHeight);
x += barWidth + 1;
}
}
renderFrame();
}
var context = new AudioContext();
var file = document.getElementById("thefile");
var audio = document.getElementById("audio");
audio.src = "song.mp3";
audio.load();
var src = context.createMediaElementSource(audio);
audio.play();
renderVisual();
file.onchange = function() {
var files = this.files;
audio.src = URL.createObjectURL(files[0]);
audio.load();
audio.play();
renderVisual();
};
};
Your html
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>JS Audio Visualizer</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="content">
<input type="file" id="thefile" accept="audio/*" />
<canvas id="canvas"></canvas>
<audio id="audio" controls></audio>
<iframe src="silence.mp3" allow="autoplay" id="silence_audio" style="display:none"></iframe>
</div>
<script src="./script.js"></script>
</body>
</html>
Note: This will get error on Chrome if you open file directly on your local because of CORS. You need to host your website to a server (Nginx or Apache).
Here is the easiest way to play mp3 on page load
You just need to add control and autoplay attributes on the audio tag and then you can play autoplay music
<audio id="myAudio" controls autoplay>
<source src="music.mp3" type="audio/mpeg">
</audio>
Note: It will not work in local you need to host your file on the server
Reference Link: https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_audio_autoplay
Related
I am trying to create a blurred face video (when there were squares)
everything is ok until I minimize the size of the square then it becomes so laggy
and slow even some times the video stop working for example when the blur = 1 ;
this is my code :
<!DOCTYPE html>
<html>
<head>
<style>
#canvas{
width: 400px;
}
</style>
</head>
<body>
<video id="video" controls width="300" height="300"></video>
<canvas id="canvas" width="1280" height="720" ></canvas>
<script>
// Get references to the video and canvas elements
var video = document.getElementById("video");
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var videoSource = "111.mp4" ;
video.src = videoSource;
video.addEventListener("play", function() {
drawVideo();
});
function drawVideo() {
context.drawImage(video, 0, 0);
let blur = 20 ;
let originalImageData = context.getImageData( 0, 0, canvas.width, canvas.height ).data;
for (let y = 0; y < canvas.height; y += blur) {
for (let x = 0; x < canvas.width; x += blur) {
const pixelIndexPosition = (x + y * canvas.width) * 4;
context.fillStyle = `rgba(
${originalImageData[pixelIndexPosition]},
${originalImageData[pixelIndexPosition + 1]},
${originalImageData[pixelIndexPosition + 2]},
${originalImageData[pixelIndexPosition + 3]})`;
context.fillRect(x, y, blur, blur);
}
}
// Continue to draw the video
if (video.paused || video.ended) {
return;
}
requestAnimationFrame(drawVideo);
}
</script>
</body>
</html>
I am trying to create an audio equalizer through the guidance of this tutorial.
This works fine until you mute the audio through the controls(as shown in the image). Muting it also stops the equalizer bars.
How would I go about implementing the equalizer bars so that the bars don't stop even when the audio is muted?
let canvas,
ctx,
source,
context,
analyser,
fbc_array,
bar_count,
bar_pos,
bar_width,
bar_height;
let audio = new Audio();
audio.src = "test.mp3";
audio.controls = true; // Show audio controls so we can pause and play at will
audio.loop = true;
audio.autoplay = true;
window.addEventListener(
"load", // only executes after loading page fully
function() {
document.getElementById("audio").appendChild(audio); // putting the audio element inside the another HTML element
audio.onplay = function() {
if (typeof(context) === "undefined") {
context = new AudioContext();
analyser = context.createAnalyser();
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d"); // returns a drawing context
source = context.createMediaElementSource(audio); // creates an audio object which can be manipulated
canvas.width = window.innerWidth * 0.80;
canvas.height = window.innerHeight * 0.60;
source.connect(analyser);
analyser.connect(context.destination); // connect the analyzer and the context(which is used to draw)
}
FrameLooper(); // will handle all the animation and output
};
},
false
);
function FrameLooper() {
window.requestAnimationFrame(FrameLooper);
fbc_array = new Uint8Array(analyser.frequencyBinCount); // array for containing frequencies
bar_count = window.innerWidth / 2;
analyser.getByteFrequencyData(fbc_array);
ctx.clearRect(0, 0, canvas.width, canvas.height); // clear old visual data
ctx.fillStyle = "#ffffff"; // fill it with white
/* For repainting */
for (let i = 0; i < bar_count; i++) {
bar_pos = i;
bar_width = 1;
bar_height = -(fbc_array[i] / 2);
ctx.fillRect(bar_pos, canvas.height, bar_width, bar_height);
}
}
body {
background: black;
padding: 0px;
margin: 0px;
}
div#player {
width: 80vw;
height: 60vh;
background: black;
margin: 20vh auto 0px auto;
display: block;
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="styles.css">
<title>Equalizer bar</title>
</head>
<body>
<div id="player">
<div id="audio"></div>
<canvas id="canvas"></canvas>
</div>
</body>
<script type="text/javascript" src="functions.js"></script>
</html>
I am trying to use an audio visualisation for the stream of my online radio using the example that I found on this page.
However, similar to the problem found in this post , my audio file (even when testing with a local file) just does not sound and of course the visualisation does nothing as well.
My HTML is the following:
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<audio src="http://50.22.218.101:38838/;steam.mp3" id="audio"
controls>HTML5 Audio element not supported</audio>
<canvas id="canvas" width="800" height="350"></canvas>
<script src="main.js"></script>
</body>
</html>
This is "main.js":
window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
window.onload = function() {
var audio = document.getElementById('audio');
var ctx = new AudioContext();
var analyser = ctx.createAnalyser();
var audioSrc = ctx.createMediaElementSource(audio);
// we have to connect the MediaElementSource with the analyser
audioSrc.connect(analyser);
analyser.connect(ctx.destination);
// we could configure the analyser: e.g. analyser.fftSize (for further infos read the spec)
// analyser.fftSize = 64;
// frequencyBinCount tells you how many values you'll receive from the analyser
var frequencyData = new Uint8Array(analyser.frequencyBinCount);
// we're ready to receive some data!
var canvas = document.getElementById('canvas'),
cwidth = canvas.width,
cheight = canvas.height - 2,
meterWidth = 10, //width of the meters in the spectrum
gap = 2, //gap between meters
capHeight = 2,
capStyle = '#fff',
meterNum = 800 / (10 + 2), //count of the meters
capYPositionArray = []; ////store the vertical position of hte caps for the preivous frame
ctx = canvas.getContext('2d'),
gradient = ctx.createLinearGradient(0, 0, 0, 300);
gradient.addColorStop(1, '#0f0');
gradient.addColorStop(0.5, '#ff0');
gradient.addColorStop(0, '#f00');
// loop
function renderFrame() {
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
var step = Math.round(array.length / meterNum); //sample limited data from the total array
ctx.clearRect(0, 0, cwidth, cheight);
for (var i = 0; i < meterNum; i++) {
var value = array[i * step];
if (capYPositionArray.length < Math.round(meterNum)) {
capYPositionArray.push(value);
};
ctx.fillStyle = capStyle;
//draw the cap, with transition effect
if (value < capYPositionArray[i]) {
ctx.fillRect(i * 12, cheight - (--capYPositionArray[i]), meterWidth, capHeight);
} else {
ctx.fillRect(i * 12, cheight - value, meterWidth, capHeight);
capYPositionArray[i] = value;
};
ctx.fillStyle = gradient; //set the filllStyle to gradient for a better look
ctx.fillRect(i * 12 /*meterWidth+gap*/ , cheight - value + capHeight, meterWidth, cheight); //the meter
}
requestAnimationFrame(renderFrame);
}
renderFrame();
audio.play();
};
Any idea what am I doing wrong?
You can usually fix this by simply adding a crossorigin option to your html audio tag
so this:
<audio src="http://50.22.218.101:38838/;steam.mp3" id="audio" controls>
becomes this:
<audio src="http://50.22.218.101:38838/;steam.mp3" crossorigin="anonymous" id="audio" controls>
Visualize stream using HTML5
Here's full example, combining #miknik's answer, your display code (which is awesome by the way), and a public web radio station
window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
let audio = document.getElementById('audio')
let ctx = ""
let audioSrc = ""
function start(){
if (!ctx){
ctx = new AudioContext();
analyser = ctx.createAnalyser();
audioSrc = ctx.createMediaElementSource(audio)
// we have to connect the MediaElementSource with the analyser
audioSrc.connect(analyser)
analyser.connect(ctx.destination)
}
// we could configure the analyser: e.g. analyser.fftSize (for further infos read the spec)
// analyser.fftSize = 64;
// frequencyBinCount tells you how many values you'll receive from the analyser
var frequencyData = new Uint8Array(analyser.frequencyBinCount);
// we're ready to receive some data!
var canvas = document.getElementById('canvas'),
cwidth = canvas.width,
cheight = canvas.height - 2,
meterWidth = 10, //width of the meters in the spectrum
gap = 2, //gap between meters
capHeight = 2,
capStyle = '#fff',
meterNum = 800 / (10 + 2), //count of the meters
capYPositionArray = []; ////store the vertical position of hte caps for the preivous frame
ctx = canvas.getContext('2d'),
gradient = ctx.createLinearGradient(0, 0, 0, 300);
gradient.addColorStop(1, '#0f0');
gradient.addColorStop(0.5, '#ff0');
gradient.addColorStop(0, '#f00');
// loop
function renderFrame() {
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
var step = Math.round(array.length / meterNum); //sample limited data from the total array
ctx.clearRect(0, 0, cwidth, cheight);
for (var i = 0; i < meterNum; i++) {
var value = array[i * step];
if (capYPositionArray.length < Math.round(meterNum)) {
capYPositionArray.push(value);
};
ctx.fillStyle = capStyle;
//draw the cap, with transition effect
if (value < capYPositionArray[i]) {
ctx.fillRect(i * 12, cheight - (--capYPositionArray[i]), meterWidth, capHeight);
} else {
ctx.fillRect(i * 12, cheight - value, meterWidth, capHeight);
capYPositionArray[i] = value;
};
ctx.fillStyle = gradient; //set the filllStyle to gradient for a better look
ctx.fillRect(i * 12 /*meterWidth+gap*/ , cheight - value + capHeight, meterWidth, cheight); //the meter
}
requestAnimationFrame(renderFrame);
}
renderFrame();
audio.play();
}
function stop(){
audio.pause()
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#container {
position: absolute;
top: 0;
left: 0;
background: #000;
width: 100%;
height: 100%;
}
#canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: black;
z-index: -1;
opacity: .8;
}
.button-container{
padding-top: 5px;
display: grid;
grid-template-columns: repeat(2,300px);
grid-gap: 1px;
width: 100%;
align-items: center;
justify-content: center;
}
button{
width: 300px;
text-align: center;
}
<html>
<link rel="stylesheet" type="text/css" href="style.css">
<body>
<audio src="https://rfcmedia.streamguys1.com/MusicPulse.mp3" crossorigin="anonymous" id="audio" >HTML5 Audio element not supported</audio>
<div class="button-container">
<button onclick="start()">Stream Radio</button>
<button onclick="stop()">Stop Radio</button>
</div>
<canvas id="canvas"></canvas>
<script src="main.js"></script>
</body>
</html>
I've got a simple page that allows you to take a picture with your phone and then upload it to the server.
To achieve that, I'm using HTML5's input as file, so when I click (or tap on) Choose File two options are displayed:
Use the phone's camera (I'm using an iPhone with iOS8)
Select a picture from the library.
If I select the picture from the library everything works just fine, as for now I'm only displaying it on screen, but if I use the camera, after taking the picture the browser crashes. I haven't been able to debug because it never hits my breakpoints since the debugging session crashes as well.
Here's the code. Any help will be highly appreciated.
<!--Seg:openPage-->
<script>
function resizeImg(img, canvas, ctx){
var MAX_WIDTH = 500;
var MAX_HEIGHT = 300;
var width = img.width;
var height = img.height;
alert(width + " " + height);
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
canvas.width = width;
canvas.height = height;
//var ctx = canvas.getContext("2d");
//var dataURL = canvas.toDataURL(img, 0.5);
//img.src = dataURL;
ctx.drawImage(img, 0, 0, width, height);
}
function drawOnCanvas(file) {
var reader = new FileReader();
reader.onload = function (e) {
var dataURL = e.target.result;
var c = document.querySelector('canvas');
var ctx = c.getContext('2d');
var img = new Image();
img.src = dataURL;
//****img.onload = function() {
//c.width = 200; //img.width;
//c.height = 200; //img.height;
if (img.complete) {
resizeImg(img, c, ctx);
//ctx.drawImage(img, 0, 0);
} else {
img.onload = function () {
resizeImg(img, c, ctx);
//ctx.drawImage(img, 0, 0);
};
}
//ctx.drawImage(img, 0, 0);
//****};
//****img.src = dataURL;
};
reader.readAsDataURL(file);
}
function upload(file){
var encodedB64 = window.btoa(file);
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend=function(){
if(file){
//reader.readAsDataURL(file);
console.log(reader);
//alert(reader.result);
$('.output').val(reader.result);
}
submit_form('f','GO');
}
}
$(document).ready(function(){
var input = document.querySelector('input[type=file]');
input.onchange = function () {
var file = input.files[0];
//upload(file);
drawOnCanvas(file);
//displayAsImage(file);
};
});
</script>
<style>
/**
#canvas-container {
width: 100%;
height: 100%;
}
#canvas-container #myCanvas{
width: 100%;
}**/
</style>
<div class="container" style="padding-top: 10px;">
<div id="page_content">
<form name="f" method="POST" action="#&PGM " class="sigPad">
<input type="hidden" name="output" class="output">
<!--Add file input-->
<p>Choose a picture from your device or capture one with your camera now:</p>
<input type="file" id="picManager" accept="image/*" capture="camera">
<!--Add canvas-->
<p>Photo:</p>
<div id="canvas-container">
<canvas id="myCanvas"></canvas>
</div>
<button type="submit" class="btn btn-primary">View</button>
</form>
</div>
</div>
<!--End:openPage-->
I want to convert a canvas to a png image and put it on a page. My problem is that if I have an image on my canvas, it does not get converted. This is my HTML:
<html>
<head>
<meta charset='UTF-8'>
<link rel="stylesheet" type="text/css" href="./assets/css/general.css">
<script type="text/javascript" src="./codetests.js"></script>
</head>
<body>
<div class="wrapper" id="wrap1">
<img id="persphoto" src="./images/nouserimage.png" style="display:none;">
<input type="hidden" id="persname" value="Test Testinen">
<input type="hidden" id="adress" value="Testgatan 1">
<input type="hidden" id="postaddr" value="12345 Teststad">
<input type="hidden" id="homephone" value="0123456789">
<input type="hidden" id="cellphone" value="0712345678">
<canvas src="" id="canvasresult" width="296px" height="420px" />
<br>
</div>
<script type="text/javascript"> drawCanvas(); </script>
<script type="text/javascript"> convertCanvasToImage(canvasresult); </script>
</body>
</html>
My JavaScript is the following:
// Converts canvas to an image
function convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL("image/png");
//return image;
document.getElementById("wrap1").appendChild(image);
}
function drawCanvas() {
var c = document.getElementById("canvasresult");
h=parseInt(document.getElementById("canvasresult").getAttribute("height"));
w=parseInt(document.getElementById("canvasresult").getAttribute("width"));
//get context
var ctx = c.getContext("2d");
//Fill the path
ctx.fillStyle = "#ffffff";
ctx.fillRect(0,0,w,h);
var img=document.getElementById("persphoto");
ih=parseInt(document.getElementById("persphoto").getAttribute("height"));
iw=parseInt(document.getElementById("persphoto").getAttribute("width"));
var maxw = 150;
var maxh = 150;
if (ih > iw) {
var newh = 150;
var neww = Math.round(150 * (iw / ih));
} else if (ih < iw) {
var newh = Math.round(150 * (ih / iw));
var neww = 150;
} else {
var newh = 150;
var neww = 150;
}
var newx = Math.round((296 - neww) / 2);
var newy = 60 + Math.round((150 - newh) / 2);
img.onload = function() {
ctx.drawImage(img,newx,newy,neww,newh);
};
ctx.fillStyle = "#000000";
ctx.font = '10pt Verdana';
ctx.textAlign = 'center';
ctx.fillText(document.getElementById("persname").value, w/2, h*0.65);
ctx.fillText(document.getElementById("adress").value, w/2, h*0.69);
ctx.fillText(document.getElementById("postaddr").value, w/2, h*0.73);
ctx.fillText(document.getElementById("homephone").value, w/2, h*0.77);
ctx.fillText(document.getElementById("cellphone").value, w/2, h*0.81);
var canvasData = c.toDataURL("image/png");
/*
document.getElementById("canvasdata").value = canvasData;
document.getElementById("hidepersphoto").value = document.getElementById("persphoto").value;
document.getElementById("hidepersname").value = document.getElementById("persname").value;
document.getElementById("hideadress").value = document.getElementById("adress").value;
document.getElementById("hidepostaddr").value = document.getElementById("postaddr").value;
document.getElementById("hidehomephone").value = document.getElementById("homephone").value;
document.getElementById("hidecellphone").value = document.getElementById("cellphone").value;
*/
}
My problem is as I said that when I call convertCanvasToImage any images currently on the canvas doesn't get converted. The result is:
Can anyone spot where the problem is?
Few Changes:
pass the string literal "canvasresult" of canvasId rather than a variable.
<script type="text/javascript"> convertCanvasToImage("canvasresult"); </script>
Get the canvas object based on the Id:
// Converts canvas to an image
function convertCanvasToImage(canvasId) {
var image = new Image();
var canvas=document.getElementById(canvasId);
image.src = canvas.toDataURL("image/png");
//return image;
document.getElementById("wrap1").appendChild(image);
}