Javascript: How to load updated audio file and play it - javascript

I am trying to play one audio file and so far I am able to do it by:
a = new Audio("audio.mp3");
a.load();
a.play();
But after playing it what I am trying to do is that I am creating new audio file with same name. Now again when I click one button and run this function to play audio, then it will play the previous file output rather than new one. So how I can re-upload the same file with same name so that new audio will be generated.
Thanks

The reason you keep getting the same audio file because of the browser cache, Since it's the same name the browser assumes the two files are the same. To prevent this, you can append a random query string to the filename so the browser thinks that you have a new file every time. But the down side of this is your user have to download the audio file every time, this could slow down your user loading time.
a = new Audio("audio.mp3?random=" + new Date().getTime());
a.load();
a.play();
If you have access to the uploaded time you can append that datetime instead of a random datetime, at least that force the browser to download the file only once per upload.
a = new Audio("audio.mp3?random=" + uploadDate.getTime());
a.load();
a.play();

In case to load another file with the same name (or even maybe with another name, in the same object), you need to remove the previous Object!
a.remove() will do the trick:
a = new Audio('a.mp3');
a.load();
a.play();
setTimeout(function(){a.pause();a.remove();a.load('a.mp3');a.play();},10000);
the above code loads a.mp3 plays it for 10 seconds. After 10 seconds it loads a.mp3 again whit what ever content there is in that file.
You need to be fast enough to replace the audio file with the same name in 10 seconds :D (or just raise the timeout seconds)

Related

How can I randomise a song when one has finished? [duplicate]

I'm planning out a project for a very simple audio streamer that would take a mysql database list of songs hosted on my local server, and then randomly stream a song from the list constantly throughout the day. This would be attached to a very simple frontend page that would display the name of the currently playing song.
I know how to get a random file from the database and stream it using a Javascript/HTML front end, but I'm getting lost on how to detect when a song is over - and then load the next song. Is there a simple way to do this? Can someone point me in the right direction?
EDIT: To elaborate on the frontend, I'd most likely be serving up the filename/location via PHP into the HTML5 audio tag (again I want this as simple as possible). I'm thinking the simplest way would be to play the audio file and then refresh the page and play the next file using the same audio tag and new filename - I just don't know how to cause that event to happen at the end of the song. Alternatively I could use a Javascript based player like JPlayer (http://www.jplayer.org/) if I need to.
I'm guessing there's a callback function of some kind I can use in conjunction with JQuery?
HTML5 audio tag has an event "onended" which is run when the media reaches its end, but since you wish to keep playing you should use the "onwaiting" event, which also fires when the media reaches its end, but keeps itself ready to accept a new track/data.
You can then use the XMLHttpRequest object to query for the next track to play, eg.
<script type="text/javascript">
function getNextTrack(e) {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "next_track.php", false);
xhttp.send("");
var playback = xhttp.responseXML.childNodes[0];
for(i = 0; i < playback.childNodes.length; ++i) {
if (playback.childNodes[i].nodeName != 'track') continue;
var value = playback.childNodes[i].childNodes[0].nodeValue;
e.currentTarget.src = value;
break;
}
}
</script>
<audio id="player" onwaiting="javascript: getNextTrack(e)" src="first_track.ogg"></audio>
The xml would be in the form of:
<?xml version="1.0" encoding="UTF-8" ?>
<playback>
<track>next_song.ogg</track>
</playback>

Is there a way to download an audio file of all the audio streams playing on a particular page?

I'm building an application using PizzicatoJS + HowlerJS. Those libraries essentially allow me to play multiple audio files at the same time. Imagine a 4 audio tracks with each track containing an instrument like guitar, bass, drums, vocals, etc..
Everything plays fine when using PizzicatoJS's Group functionality or running a forEach loop on all my Howl sounds and firing .play(). However, I would like to download the final resulting sound I am hearing from my speakers. Any idea on how to approach that?
I looked into OfflineAudioContext, but I am unsure on how to use it to generate an audio file. It looks like it needs an Audio source like an <audio> tag. Is what I'm trying to do possible? Any help is appreciated.
I think the OfflineAudioContext can help with your use case.
Let's say you want to create a file with a length of 10 seconds. It should contain one sound playing from the start up to second 8. And there is also another sound which is supposed to start at second 5 and should last until the end. Both sounds are AudioBuffers (named soundBuffer and anotherSoundBuffer) already.
You could arrange and combine the sounds as follows.
const sampleRate = 44100;
const offlineAudioContext = new OfflineAudioContext({
length: sampleRate * 10,
sampleRate
});
const soundSourceNode = new AudioBufferSourceNode({
buffer: soundBuffer
});
soundSourceNode.start(0);
soundSourceNode.stop(8);
soundSourceNode.connect(offlineAudioContext.destination);
const anotherSoundSourceNode = new AudioBufferSourceNode({
buffer: anotherSoundBuffer
});
anotherSoundSourceNode.start(5);
anotherSoundSourceNode.stop(10);
anotherSoundSourceNode.connect(offlineAudioContext.destination);
offlineAudioContext
.startRendering()
.then((audioBuffer) => {
// save the resulting buffer as a file
});
Now you can use a library to turn the resulting AudioBuffer into an encoded audio file. One library which does that is for example audiobuffer-to-wav.

Is it possible to merge multiple webm blobs/clips into one sequential video clientside?

I already looked at this question -
Concatenate parts of two or more webm video blobs
And tried the sample code here - https://developer.mozilla.org/en-US/docs/Web/API/MediaSource -- (without modifications) in hopes of transforming the blobs into arraybuffers and appending those to a sourcebuffer for the MediaSource WebAPI, but even the sample code wasn't working on my chrome browser for which it is said to be compatible.
The crux of my problem is that I can't combine multiple blob webm clips into one without incorrect playback after the first time it plays. To go straight to the problem please scroll to the line after the first two chunks of code, for background continue reading.
I am designing a web application that allows a presenter to record scenes of him/herself explaining charts and videos.
I am using the MediaRecorder WebAPI to record video on chrome/firefox. (Side question - is there any other way (besides flash) that I can record video/audio via webcam & mic? Because MediaRecorder is not supported on not Chrome/Firefox user agents).
navigator.mediaDevices.getUserMedia(constraints)
.then(gotMedia)
.catch(e => { console.error('getUserMedia() failed: ' + e); });
function gotMedia(stream) {
recording = true;
theStream = stream;
vid.src = URL.createObjectURL(theStream);
try {
recorder = new MediaRecorder(stream);
} catch (e) {
console.error('Exception while creating MediaRecorder: ' + e);
return;
}
theRecorder = recorder;
recorder.ondataavailable =
(event) => {
tempScene.push(event.data);
};
theRecorder.start(100);
}
function finishRecording() {
recording = false;
theRecorder.stop();
theStream.getTracks().forEach(track => { track.stop(); });
while(tempScene[0].size != 1) {
tempScene.splice(0,1);
}
console.log(tempScene);
scenes.push(tempScene);
tempScene = [];
}
The function finishRecording gets called and a scene (an array of blobs of mimetype 'video/webm') gets saved to the scenes array. After it gets saved. The user can then record and save more scenes via this process. He can then view a certain scene using this following chunk of code.
function showScene(sceneNum) {
var sceneBlob = new Blob(scenes[sceneNum], {type: 'video/webm; codecs=vorbis,vp8'});
vid.src = URL.createObjectURL(sceneBlob);
vid.play();
}
In the above code what happens is the blob array for the scene gets turning into one big blob for which a url is created and pointed to by the video's src attribute, so -
[blob, blob, blob] => sceneBlob (an object, not array)
Up until this point everything works fine and dandy. Here is where the issue starts
I try to merge all the scenes into one by combining the blob arrays for each scene into one long blob array. The point of this functionality is so that the user can order the scenes however he/she deems fit and so he can choose not to include a scene. So they aren't necessarily in the same order as they were recorded in, so -
scene 1: [blob-1, blob-1] scene 2: [blob-2, blob-2]
final: [blob-2, blob-2, blob-1, blob-1]
and then I make a blob of the final blob array, so -
final: [blob, blob, blob, blob] => finalBlob
The code is below for merging the scene blob arrays
function mergeScenes() {
scenes[scenes.length] = [];
for(var i = 0; i < scenes.length - 1; i++) {
scenes[scenes.length - 1] = scenes[scenes.length - 1].concat(scenes[i]);
}
mergedScenes = scenes[scenes.length - 1];
console.log(scenes[scenes.length - 1]);
}
This final scene can be viewed by using the showScene function in the second small chunk of code because it is appended as the last scene in the scenes array. When the video is played with the showScene function it plays all the scenes all the way through. However, if I press play on the video after it plays through the first time, it only plays the last scene.
Also, if I download and play the video through my browser, the first time around it plays correctly - the subsequent times, I see the same error.
What am I doing wrong? How can I merge the files into one video containing all the scenes? Thank you very much for your time in reading this and helping me, and please let me know if I need to clarify anything.
I am using a element to display the scenes
The file's headers (metadata) should only be appended to the first chunk of data you've got.
You can't make an new video file by just pasting one after the other, they've got a structure.
So how to workaround this ?
If I understood correctly your problem, what you need is to be able to merge all the recorded videos, just like if it were only paused.
Well this can be achieved, thanks to the MediaRecorder.pause() method.
You can keep the stream open, and simply pause the MediaRecorder. At each pause event, you'll be able to generate a new video containing all the frames from the beginning of the recording, until this event.
Here is an external demo because stacksnippets don't works well with gUM...
And if ever you needed to also have shorter videos from between each resume and pause events, you could simply create new MediaRecorders for these smaller parts, while keeping the big one running.

Programm that tracks changes on web page

I have a web page that has several images on it and a script in it which changes picture of one random image once in some time interval. Script changes the image by rewtiting its file in the cash an updating it on the page. So url of the image picture doesnt chage in html code:
socket.on("banner", function(info) {
banName = "banner" + info.bid;
ban = document.getElementById(banName).getContext('2d');
var img = new Image();
img.src = 'data:image/jpg;base64,' + info.image;
img.onload = function(){ban.drawImage(img, 0, 0);};
});
How can I track image change using for example C#, when the page is in the browser?
As a last resort, retrieve the image periodically and load it into a byte array. Checking changes is just a matter of checking if the byte array has changed.
edit:
It seems the hard part is about how can one retrieve the image data. Without any javascript code in the browser, use C# to establish a websocket connection to mimic the behavior of javascript.
But I think it would be easier done by modifying the javascript code in the browser.

JavaScript FileReader using a lot of memory

I have a problem with my little project.
Every time the music player is loading new songs into playlist or you are pressing a song on the list to get it playing, it's using a lot of memory, and it stays high until you shut it down. I think its every time I'm using the filereader API that it uses memory, but I'm also loading ID3 information with the jDataView.js script which I also think is taking a lot of memory.
Do you guys have any suggestion, to load,store and play songs with the FileReader, without taking up memory? I've tried to see if it was possible to clear the fileReader after using, but I couldn't find anything. I've only tested in Chrome.
UPDATE:
I have tested my project,and found out, that its when im trying to load the datastring it takes up memory.
reader.onloadend = function(evt) {
if(typeof(e) != "undefined"){
e.pause();
}
e = new Audio();
e.src = evt.target.result; // evt.target.result call takes the memory
e.setAttribute("type", songs[index]["file"].type);
e.play();
e.addEventListener("ended", function() { LoadAudioFile(index + 1) }, false);
};
Is there another way to load the data into the audio element?
This is not because of FileReader but because you are making the src attribute of audio element a 1.33 * mp3filesize string. So instead of the src attribute being a nice short url pointing to a mp3 resource, it's the whole mp3 file in base64 encoding. It's a wonder your browser didn't crash.
You should not read the file with FileReader at all, but create a blob URL from the file and use that as src.
var url = window.URL || window.webkitURL;
//Src will be like "blob:http%3A//stackoverflow.com/d13eb575-4863-4f86-8727-6400119f4afc"
//A very short string that is pointing to the original resource in hard drive
var src = url.createObjectURL( mp3filereference );
audioElement.src = src;

Categories

Resources