How can I get video bitrate with javascript - javascript

I want to get the bitrate of video that uploader, because the backend need it.
var video = document.createElement('video');
video.preload = 'metadata';
video.src = URL.createObjectURL(document.getElementById('fileUp').files[0]);
window.URL.revokeObjectURL(video.src);
console.log(video.bitrate);

You can get the video duration then simply divide the file size by it to get an approximation (subtitles, audio and metadata would also be included in this value), as far as i know there is no standard api for getting the bitrate directly.
Example (credits https://stackoverflow.com/a/67899188/6072029 ) :
<div>
<script>
const getVideoInfos = (file) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const media = new Audio(reader.result);
media.onloadedmetadata = () => resolve({
duration: media.duration,
file_size: file.size,
bitrate: file.size / media.duration,
});
};
reader.readAsDataURL(file);
reader.onerror = (error) => reject(error);
});
const handleChange = async (e) => {
const infos = await getVideoInfos(e.target.files[0]);
document.querySelector("#infos").innerText = `Infos : ${JSON.stringify(infos, null, 4)}`;
};
</script>
<input type="file" onchange="handleChange(event)" />
<p id="infos">infos: </p>
</div>

Related

How to add custom metadata in PDF file using react js?

I'm taking input as a PDF file and using javascript to add custom metadata, but I'm not getting a satisfactory result.
Below is a sample method code that I used to add custom metadata that is first converted to blob type and then added, but when we convert its blob data to base64 and download the file and check the properties, we cannot find it.
const blobToBase64 = (blob: any) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
const updatePDFMetaData = (file: any, metadata: any) => {
let convertBlobToBase64: any;
const selectedFile = file;
const reader = new FileReader();
reader.readAsArrayBuffer(selectedFile);
reader.onload = async (event:any) => {
const fileBuffer: any = event?.target?.result;
const blob: any = new Blob([fileBuffer], { type: selectedFile.type });
Object.keys(metadata).forEach((key: any) => {
blob[key] = metadata[key];
});
convertBlobToBase64 = await blobToBase64(blob);
console.log("convertBlobToBase64", convertBlobToBase64);
};
};

Convert multiple images to base 64 using single function

I'm working on a problem where I have to take three images as input from the user and have to send them to the backend by converting them into Base64. I know how to do it for a single input file but can't work my way around for multiple inputs.
I want to have a single function that can convert the images to Base64 & store the value of each image in a separate variable. Please help me out with this.
Following is the code I'm using for single input i.e. First Image.
HTML CODE
<div class="first_div">
<label for="first_image">First Image</label>
<input name="first_image" type="file" accept="image/*" id="first_image" class="img_file">
</div>
<div class="second_div">
<label for="second_image">Second Image</label>
<input name="second_image" type="file" accept="image/*" id="second_image" class="img_file">
</div>
<div class="third_div">
<label for="third_image">Third Image</label>
<input name="third_image" type="file" accept="image/*" id="third_image" class="img_file">
</div>
<button onclick="submitImages()">Submit</button>
JAVASCRIPT CODE
let encoded_image;
function getBase64(file) {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
console.log(reader.result);
encoded_image = reader.result;
};
reader.onerror = function (error) {
console.log('Error: ', error);
};
}
const submitImages = () => {
var files = document.getElementById('first_image').files[0];
if (files.length > 0) {
getBase64(files[0]);
}
const formData = new URLSearchParams(new FormData());
formData.append("first_image", encoded_image);
fetch(API CALL HERE)
}
I want to create a function that takes input from all three fields, converts them to Base64 & stores in a variable. So that I can append it to form data.
Select all inputs, loop and get base64 of each file
Try this
const getBase64 = (file) =>
new Promise((resolve, reject) => {
console.log(file);
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (err) => reject(err);
});
const submitImages = async () => {
const imageInputs = document.querySelectorAll("input");
const images = await Promise.all(
[...imageInputs].map((imageInput) =>
imageInput?.files?.[0] ? getBase64(imageInput.files[0]) : null
)
);
console.log(images);
};
This example is in React but you can easily modify it to standard javascript.
If it's standard javascript just change const [images, setImages] = useState([]); into let images = [].
const [images, setImages] = useState([]);
const formatImage = async() => {
try {
for (let i = 0; i < e.target.files.length; i++) {
const reader = new FileReader();
reader.readAsDataURL(e.target.files[i]);
reader.onload = (readerEvent) => {
images.push(readerEvent.target ? .result);
};
}
} catch (error) {
console.log(error);
}
};
<input type="file" multiple onChange={formatImage} />
And here is an example of putting these images on Firebase Firestore and again if it's standard javascript change setImages([]) to images = []
const addImage = async() => {
try {
Promise.all(
images.map(
async(file: any) =>
await addDoc(collection(db, "images"), {
image: file,
date: Timestamp.now(),
})
)
);
setImages([]);
} catch (error) {
console.log(error);
}
};

How to convert blob to png or jpg?

I have used react-images-zoom-print https://www.npmjs.com/package/react-images-zoom-print I am taking a photo of the API with a blob like this:
const downloadDepositMoneyInfosClickHandler = (row) => {
props.service(row.id, (status, data) => {
var blob = new Blob([data], { type: "image/png" });
var objectUrl = URL.createObjectURL(blob);
imageRef.current = objectUrl;
setImgDialogOpen(true);
});
};
> console.log(imageRef.current)==>
blob:http://localhost:3000/c85aiua36d-2fua-43a8-a881-311d287ed37e
and in Lightbox:
<Lightbox
images={[{src:"'"+imageRef.current+"'"}]}
isOpen={imgDialogOpen}
onClose={closeImgDialog}
rotatable={true}
zoomable={true}
onPrint={() => window.print()}
/>
But it does not show it, I think it should become a png or jpg.
I want to turn it into a photo with the type png or jpg.
How should I convert it?
Try this one:
const blobToImage = (blob) => {
return new Promise(resolve => {
const url = URL.createObjectURL(blob)
let img = new Image()
img.onload = () => {
URL.revokeObjectURL(url)
resolve(img)
}
img.src = url
})
}

How can I read the data in the excel file with reactjs or javascript using the path to the file

I want to read the contents of the file directly by using the file path. I can do this by having the file selected. But I don't know how to do it using the direct file path. I could not find any examples or sources for this. Below is how I read the file by selecting it from the input.
import * as XLSX from 'xlsx';
var items = [];
readExcel = (file) => {
const promise = new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsArrayBuffer(file);
fileReader.onload = (e) => {
const bufferArray = e.target.result;
const wb = XLSX.read(bufferArray, { type: "buffer" });
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
const data = XLSX.utils.sheet_to_json(ws);
resolve(data);
};
fileReader.onerror = (error) => {
reject(error);
};
});
promise.then((d) => {
this.items = d;
console.log(this.items)
// fill dictionary
this.dictionary = Object.assign({}, ...this.items.map((x) => ({ [x.PartNumber]: x.Cost })));
console.log(this.dictionary)
});
};
<input
type="file"
onChange={(e) => {
const file = e.target.files[0];
this.readExcel(file);
}}
/>
I beleive it should work:
const req = new XMLHttpRequest();
req.responseType = "arraybuffer";
req.open("GET", "https://.../MyExcelFile.xlsx", true);
req.onload = () => {
const bufferArray = req.response;
const wb = XLSX.read(bufferArray, { type: "buffer" });
...
I couldn't find a direct read operation. I converted the excel file to json format and got my job done.

How I can know audio/video duration before uploading?

I need to upload file (audio/video) using default input type='file' and the I should pass duration of the video in api request, how i ca do this?
const uploadFile = async (event) => {
let file = await event.target.files[0];
//here api POST request where i should pass duration
}:
You can get the audio duration with HTMLMediaElement.duration:
async function getDuration(file) {
const url = URL.createObjectURL(file);
return new Promise((resolve) => {
const audio = document.createElement("audio");
audio.muted = true;
const source = document.createElement("source");
source.src = url; //--> blob URL
audio.preload= "metadata";
audio.appendChild(source);
audio.onloadedmetadata = function(){
resolve(audio.duration)
};
});
}
Then in your function:
const uploadFile = async (event) => {
let file = event.target.files[0];
//here api POST request where i should pass duration
const duration = await getDuration(file);
}:
You just need to create an element based on user input(video/audio) and get the duration property -
const VIDEO = "video",
AUDIO = "audio";
const uploadApiCall = (file, data = {}) => {
// ----- YOUR API CALL CODE HERE -----
document.querySelector("#duration").innerHTML = `${data.duration}s`;
document.querySelector("#type").innerHTML = data.type;
};
let inputEl = document.querySelector("#fileinput");
inputEl.addEventListener("change", (e) => {
let fileType = "";
let file = inputEl.files[0];
if (file.type.startsWith("audio/")) {
fileType = AUDIO;
} else if (file.type.startsWith("video/")) {
fileType = VIDEO;
} else {
alert("Unsupported file");
return;
}
let dataURL = URL.createObjectURL(file);
let el = document.createElement(fileType);
el.src = dataURL;
el.onloadedmetadata = () => {
uploadApiCall(file, {
duration: el.duration,
type: fileType
});
};
});
<form>
<input type="file" accept="video/*,audio/*" id="fileinput" />
<hr />
Type:<span id="type"></span>
<br />
Duration:<span id="duration"></span>
</form>
In Vue 3 JS, I had to create a function first:
const getDuration = async (file) => {
const url = URL.createObjectURL(file);
return new Promise((resolve) => {
const audio = document.createElement("audio");
audio.muted = true;
const source = document.createElement("source");
source.src = url; //--> blob URL
audio.preload = "metadata";
audio.appendChild(source);
audio.onloadedmetadata = function(){
resolve(audio.duration)
};
});
}
The user would select an MP3 file. Then when it was submitted I could call that function in the Submit function:
const handleAudioSubmit = async () => {
console.log('Your Epsiode Audio is being stored... please stand by!')
if (file.value) {
// returns a number that represents audio seconds
duration.value = await getDuration(file.value)
// remove the decimals by rounding up
duration.value = Math.round(duration.value)
console.log("duration: ", duration.value)
// load the audio file to Firebase Storage using a composable function
await uploadAudio(file.value)
.then((downloadURL) => {
// composable function returns Firebase Storage location URL
epAudioUrl.value = downloadURL
})
.then(() => {
console.log("uploadAudio function finished")
})
.then(() => {
// Set the Album Fields based on the album id to Firestore DB
const updateAudio = doc(db, "artist", artistId.value, "albums, albumID.value);
updateDoc(updateAudio, {
audioUrl: audioUrl.value,
audioDuration: duration.value
})
console.log("Audio URL and Duration added to Firestore!")
})
.then(() => {
console.log('Episode Audio has been added!')
router.push({ name: 'Next' })
})
} else {
file.value = null
fileError.value = 'Please select an audio file (MP3)'
}
}
This takes some time to run and needs refactoring, but works provided you allow the async functions the time to finish. Hope that helps!

Categories

Resources