I have an 'browser application' where users should be able to drag and drop local mp3 files to Chrome and should see some mp3 info (without uploading files to server)...
So far, I can successfully read and display mp3 tags (with JavaScript-ID3-Reader library), but I'm struggling a bit with displaying mp3's duration. Is it possible to get that info with js/jQuery only? If not, what would you recommend for resolving this simple problem?
Code I'm using to handle dropping files to browser looks like this:
function initialize() {
var target = document;
if (target === null) {
return false;
}
target.addEventListener('drop', function(event) {
event.preventDefault();
var files = event.dataTransfer.files;
console.log(files);
for (var i = 0; i < files.length; i++) {
processFile(files[i]);
objectURL = window.URL.createObjectURL(files[i]);
console.log(objectURL);
}
}, true);
}
Thanks!
Try this
var audio = new Audio()
audio.addEventListener("timeupdate", function() {
console.log(audio.currentTime)
})
audio.addEventListener("canplaythrough", function() {
console.log(audio.duration)
})
target.on("change", function(e) {
var file = e.currentTarget.files[0]
var objectUrl = URL.createObjectURL(file)
audio.src = objectUrl
$("#duration").html(audio.duration)
})
If you are using latest browsers that support audio tag, you can load the mp3 in an <audio> element and access the duration property via the DOM.
To load a audio file to browser see: window.URL.createObjectURL
Related
I have an embedded playlist of video links from different websites like Dailymotion, YouTube, Vimeo, etc., that I would like to play back to back on a personal website that I am working on. I found a script on the internet that plays embedded videos from multiple websites, but it only plays one video randomly. I would like the script to play each video back to back once one video is finished playing, but since I have no skills whatsoever in javascript, I don't know how to adapt this script to meet my needs. Does anyone know how I can accomplish this? I would greatly appreciate any kind of help. Thanks! Here is the script:
<div id="random_player"></div>
<script>
var videos = ["https://www.dailymotion.com/embed/video/x7raxfh?queue-enable=false","https://ok.ru/videoembed/3188453542586","https://www.youtube.com/embed/X3wV5ydVewY" ];
window.onload = function () {
var playerDiv = document.getElementById("random_player");
var player = document.createElement("IFRAME");
var randomVideoUrl = videos[Math.floor(Math.random() * videos.length)];
player.setAttribute('width', '640');
player.setAttribute('height', '390');
player.setAttribute('src', randomVideoUrl);
playerDiv.appendChild(player);
};
</script>
Follow the step by step code below-
Step 1
Copy paste the below code in html file by replacing url to your desired one!-
<iframe src="url" id="videoPlayer" height="200"">
Step 2
Javascript file should look like this-
let videoSource = new Array();
videoSource[0] = 'https://www.dailymotion.com/embed/video/x7raxfh?queue-enable=false","https://ok.ru/videoembed/3188453542586';
videoSource[1] = 'https://www.youtube.com/embed/X3wV5ydVewY4';
let i = 0; // global
const videoCount = videoSource.length;
const element = document.getElementById("videoPlayer");
function videoPlay(videoNum) {
element.setAttribute("src", videoSource[videoNum]);
element.autoplay = true;
element.load();
element.play();
}
document.getElementById('videoPlayer').addEventListener('ended', myHandler, false);
videoPlay(0); // play the video
function myHandler() {
i++;
if (i == videoCount) {
i = 0;
videoPlay(i);
} else {
videoPlay(i);
}
}
Step 3
Save the file and call the javascript file on html file. Open the html file in browser and it will run according to your asked question!
I am trying to make a nodejs website that will return the length in seconds of any audio file a user chooses. So far I have it working with mp3, wav, and flac files. But it doesn't work for all .m4a or .aif files
The code for my HTML page with javascript is below:
choose audio file to get length:
<input style="cursor: pointer;" type="file" id="file" multiple="multiple" />
<script>
//when files are selected:
$("#file").change(async function (e) {
console.log('file(s) selected')
//get files
var files = e.currentTarget.files;
//get number of files
var numberOfFiles = files.length;
//for each file
for (i = 0; i < numberOfFiles; i++) {
console.log(`songs[${i}].type=`, files[i].type)
//get file length
let songLength = await getSongLength(files[i]);
console.log('songLength=', songLength)
}
});
//recieve audio file, return length
function getSongLength(song) {
return new Promise(function (resolve, reject) {
console.log('getSongLength() begin setup')
//create objectURL and audio object for ssong
objectURL = URL.createObjectURL(song);
mySound = new Audio([objectURL])
console.log('getSongLength() end setup')
//when song metadata is loaded:
mySound.addEventListener("canplaythrough", function (e) {
console.log('getSongLength() canplaythrough')
var seconds = e.currentTarget.duration;
resolve(seconds)
});
});
}
</script>
I gathered 6 different files for testing, and after running them on my above code have found out the following results:
aif: not working
flac: working
m4a_file: not working
m4a_file_from_comments_below:not working
mp3: working
wav: working
my test files for download: https://easyupload.io/m/la9xro
It seems like when I input my m4a file sample_M4A_file that it hangs inside the getSongLength() function and never enters the .addEventListener("canplaythrough" function, is there any alternative I can use to consistently get the duration in seconds for every audio file?
It's because your browser doesn't support Apple Lossless codecs. If you try in Safari, it will work.
If you attach an error event to your media element, you'll see it fires.
There is no real universal solution, apart from using an heavy machinery like mediainfo.js (2.4MB+) which should support most formats.
const input = document.querySelector( "input" );
input.onchange = async (evt) => {
const mediainfo = await new Promise( (res) => MediaInfo(null, res) );
const file = input.files[ 0 ];
const getSize = () => file.size;
const readChunk = async (chunkSize, offset) =>
new Uint8Array( await file.slice(offset, offset + chunkSize).arrayBuffer() );
const info = await mediainfo.analyzeData(getSize, readChunk);
// assumes we are only interested in audio duration
const audio_track = info.media.track.find( (track) => track[ "#type" ] === "Audio" );
console.log( audio_track.Duration );
};
<script src="https://unpkg.com/mediainfo.js#0.1.4/dist/mediainfo.min.js"></script>
<input type="file">
Ps: when using the media element solution, there is no need to wait for canplaythrough, just wait for loadedmetadata, and if you get Infinity, try this hack.
I have a electron application using jszip to create a zip file that the user is then able save. Everything works fine but my problem is my application uses the users download folder. Im guessing its making a temporary file. I've submitted my application to the mac store and they want me to use another location instead of the users downloads folder for the temporary file. Is there anyway I can specify the temporary location or maybe something else other then jszip that will do this?
Here is the code I use
savePNGButton.addEventListener('click', function(e) {
var zip = new JSZip();
if (WatermarkText == ""){
var img = zip.folder("images");
} else {
var img = zip.folder(WatermarkText);
}
$(".WatermarkPhoto").each(function(index) {
imgsrc = this.src;
var DataURL = imgsrc.replace('data:image/png;base64,','');
img.file(WatermarkText+index+".png", DataURL, {base64: true});
});
zip.generateAsync({type:"blob"})
.then(function(content) {
saveAs(content, WatermarkText+".zip");
});
});
[edit]
Looking more into this it looks like my problem is not with JSZip but with chrome or FileSaver.js using the downloads folder as a temp folder for the file before the users chooses where to place the file. Is there anyway I can change the temp location for my electron app?
If anyone comes across this, I never figured a way around the HTML5 filesystem way of moving the temp file before the users selects the download location. Instead I am using nodejs file system with electrons showSaveDialog. I also had to change JSZip to use .generateNodeStream instead of .generateAsync. Below is my function that I got working for me.
savePNGButton.addEventListener('click', function(e) {
var zip = new JSZip();
if (WatermarkText == ""){
var img = zip.folder("images");
} else {
var img = zip.folder(WatermarkText);
}
$(".WatermarkPhoto").each(function(index) {
imgsrc = this.src;
var DataURL = imgsrc.replace('data:image/png;base64,','');
img.file(WatermarkText+index+".png", DataURL, {base64: true});
});
// zip.file("file", content);
// ... and other manipulations
dialog.showSaveDialog({title: 'Test',defaultPath: '~/'+WatermarkText+'.zip',extensions: ['zip']},(fileName) => {
if (fileName === undefined){
console.log("You didn't save the file");
return;
}
zip
.generateNodeStream({type:'nodebuffer',streamFiles:true})
.pipe(fs.createWriteStream(fileName))
.on('finish', function () {
// JSZip generates a readable stream with a "end" event,
// but is piped here in a writable stream which emits a "finish" event.
console.log("zip written.");
});
});
});
I am trying to use jquery to take a picture from my comp via a form.
- So I want the entire URL out of the form in an array
It works + / - in Dreamweaver, but not in the explorer browsers not even chrome
The end goal is a calendar with picture / app for people with disabilities, but as long as I get to go through the phone gap
var foto= new Array();
var i=-1;
//foto=["toets.png"];
$('#fotouit').append("FOTO UIT");
$('#knop01').click(function(){
$('input:file[name=foto]').each(function(){
//alert($(this).val());
foto.push($(this).val());
foto.forEach( function(){
i++;
$('#fotouit').append(foto[i]);
$('#fotouit').append('<img src=" '+ foto[i] + ' " width="100" height="100" />');
});
});
})
I don't think it is possible to get the URL of the picture in you computer's local filesystem, but you can use Javascript's FileReader API to read the contents of the uploaded file (in your case, the picture). The read contents can be used in the src of the img element as you did in your example code.
This is an in depth explanation of what you're trying to accomplish: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications
Example:
function handleFiles(files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var imageType = /image.*/;
if (!file.type.match(imageType)) {
continue;
}
var img = document.createElement("img");
img.classList.add("obj");
img.file = file;
preview.appendChild(img); // Assuming that "preview" is a the div output where the content will be displayed.
var reader = new FileReader();
reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
reader.readAsDataURL(file);
}
}
Note:
You can use the multiple attribute on a file input to allow selecting many files with one input
You can use the file inputs change event to immediately capture the files rather than providing a second button to click
I want to display the image using the upload form and submit button.
But the problem though, I can't make the image appear.
Here's what I did.
function myFunction() {
var x = document.getElementById("myFile").value;
document.getElementById('myImg').src = document.getElementById("myFile").name;
<form>Select a file to upload:
<input type="file" id="myFile" name=filename>
</form>
<button type="button" onclick="myFunction()">Upload This</button>
<img id="myImg" src="">
I just don't know what seems to be the problem with this.
Thank you for helping me out.
The browser does NOT allow javascript full access to the .value property of an input tag with type="file". This is for security reasons so no local path information is made available to javascript.
Thus, you can't set a .src value on an image tag based on a file input value that the end-user specified.
If you don't want to upload the image to server side, you have a possibility to do it only in the client side.
add a div to your html (dom):
<div id='bottom'>
<div id='drag-image' class='holder-file-uploader bottom-asset'> Drag here an image</div>
</div>
add this javascript:
<script>
var holder = document.getElementById('drag-image');
holder.ondragover = function () { return false; };
holder.ondragend = function () { return false; };
holder.ondrop = function (event) {
event.preventDefault && event.preventDefault();
//do something with:
var files = event.dataTransfer.files;
console.log(files);
bottomFileAdd(files, 0);
return false;
};
//Recursive function to add files in the bottom div
//this code was adapted from another code, i didn't test it
var bottomFileAdd = function (files, i) {
if(!i) i=0;
if (!files || files.length>=i) return;
var file = files.item(i);
var img = document.createElement('img');
var bottom = document.getElementById('bottom'); //this string should not be static
bottom.appendChild(img);
var reader = new FileReader();
reader.onload = function (event) {
console.log(event.target);
img.src = event.target.result;
bottomFileAdd(files, i+1);
};
reader.readAsDataURL(file);
}
</script>
note: It may not work in older browsers.
I hope it helps.
You tried to set the src attribute of the <img> tag to a local file path. However, the web browser doesn't expose the local file URL (file://...) in the value property of the <input> tag. The browser implementation may vary; Chrome, for example, gives you a fake path.
You can load the image by the FileReader API into a data URI and show it by setting the src attribute of the <img> tag:
function myFunction() {
var myFile = document.getElementById("myFile");
if (myFile.files && myFile.files.length) {
if (typeof FileReader !== "undefined") {
var fileReader = new FileReader();
fileReader.onload = function(event) {
document.getElementById("myImg").src = event.target.result;
};
fileReader.readAsDataURL(myFile.files[0]);
} else {
alert("Your browser doesn't support the FileReader API.")
}
} else {
alert("No file was selected.")
}
}
You need a fairly modern web browser for this to work:
Browser Firefox Chrome IE Opera Safari
Version 3.6 7 10 12.02 6.0.2
You can have a look at a working sample page. The final implementation of such image preview should set the <img> element to a fixed size, but your markup with my function is enough as a simple demonstration.