Skip to content

Commit

Permalink
Add Browser Camera App
Browse files Browse the repository at this point in the history
  • Loading branch information
rishabh217 committed Oct 22, 2021
1 parent 4f572c6 commit b8ce06b
Show file tree
Hide file tree
Showing 5 changed files with 451 additions and 0 deletions.
24 changes: 24 additions & 0 deletions Browser Camera/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<h1>Browser Camera App</h1>

<p>Simple Camera App written in HTML, CSS, and JavaScript which can be used to record and capture images.</p>

<h3>Used Technologies</h3>
<ul>
<li>HTML5</li>
<li>CSS3</li>
<li>JavaScript</li>
</ul>

#### Steps to Use:

---

- Download or clone the repository

```
git clone https://github.com/Ayushparikh-code/Web-dev-mini-projects.git
```

- Go to the 'Browser Camera' directory
- Run the index.html file
- Start using the camera!!
49 changes: 49 additions & 0 deletions Browser Camera/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Camera</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<link rel="stylesheet" href="style.css">
</head>

<body>

<div class="video-container">
<video autoplay></video>
</div>
<div class="ui-filter filter-6"></div>

<div class="filter-container">
<div class="filter filter-1"></div>
<div class="filter filter-2"></div>
<div class="filter filter-3"></div>
<div class="filter filter-4"></div>
<div class="filter filter-5"></div>
<div class="filter filter-6"></div>
</div>

<div class="timing-container"><div class="timing">00:00:00</div></div>

<div class="zoom-container">
<i class="fas fa-plus icon"></i>
<i class="fas fa-minus icon"></i>
</div>

<div class="button-container">
<div class="record"><button id="record-video"></button></div>
<div class="click"><button id="click-image"></button></div>
</div>

<!-- <div class="gallery-container">
<a href="gallery.html" class="gallery"><i class="fab fa-envira"></i></a>
</div> -->

<script src="indexedDBScript.js" defer></script>
<script src="script.js" defer></script>
</body>

</html>
30 changes: 30 additions & 0 deletions Browser Camera/indexedDBScript.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
let request = indexedDB.open("camera", 1);
let db;

request.onsuccess = function (e) {
// if exist then will get db from here
db = request.result;
}
request.onerror = function (err) {
console.log(err)
}
request.onupgradeneeded = function () {
// 1st time creation
db = request.result;
db.createObjectStore("images", { keyPath: "mid" });
db.createObjectStore("videos", { keyPath: "mid" });
}

function addMediaToDB(data, table) {
if (db) {
// you need to get transaction
let tx = db.transaction(table, "readwrite");
// get table refer
let store = tx.objectStore(table);
// add
store.add({ mid: Date.now(), media: data });

} else {
alert("db is loading")
}
}
166 changes: 166 additions & 0 deletions Browser Camera/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
let video = document.querySelector("video");

let constraints = {
video: true,
audio: true
};

let mediaRecorder;
let buffer = [];

let recordState = false;

let videoRecorder = document.querySelector("#record-video");
let captureButton = document.querySelector("#click-image");

let timingELem = document.querySelector(".timing");
let clearObj;

let allFilters = document.querySelectorAll(".filter");
let uiFilter = document.querySelector(".ui-filter");

let zoomIn = document.querySelector(".fa-plus");
let zoomOut = document.querySelector(".fa-minus");

let scale = 1.0;

// Video recorder listeners
navigator.mediaDevices
.getUserMedia(constraints)
.then(function (mediaStream) {
video.srcObject = mediaStream;

mediaRecorder = new MediaRecorder(mediaStream);
mediaRecorder.addEventListener('dataavailable', function (e) {
buffer.push(e.data);
});
mediaRecorder.addEventListener('stop', function (e) {
let blob = new Blob(buffer, { type: "video/mp4" });
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.download = `VID_${getTimeStamp()}.mp4`;
a.href = url;
a.click();
a.remove();
addMediaToDB(url, "videos");
buffer = [];
});
}).catch(function (err) {
console.log(err);
});

// Recording Video
videoRecorder.addEventListener('click', function () {
if (!mediaRecorder) {
alert("Permissions not given");
return;
}
if (!recordState) {
mediaRecorder.start();
videoRecorder.style.animation = "buttonAnimation 0.75s infinite";
recordState = true;
startClock();
} else {
mediaRecorder.stop();
videoRecorder.style.animation = "none";
recordState = false;
stopClock();
}
});

// Capturing Image
captureButton.addEventListener("click", function () {
if (!mediaRecorder) {
alert("Permissions not given");
return;
}
// Create a canvas element equal to video frame
let canvas = document.createElement("canvas");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
let tool = canvas.getContext("2d");
// Zoom from center
tool.scale(scale, scale);
let x = (tool.canvas.width / scale - video.videoWidth) / 2;
let y = (tool.canvas.height / scale - video.videoHeight) / 2;
// Draw a frame on that canvas
tool.drawImage(video, x, y);
// translucent
tool.globalAlpha = 0.25;
tool.fillStyle = getFilter(document.querySelector(".ui-filter").classList[1]);
// things are drawn on above layer
tool.fillRect(0, 0, canvas.width, canvas.height);
// toDataUrl
let link = canvas.toDataURL();
// Download
let anchor = document.createElement("a");
anchor.href = link;
anchor.download = `IMG_${getTimeStamp()}.png`;
anchor.click();
anchor.remove();
canvas.remove();
addMediaToDB(link, "images");
captureButton.style.animation = "buttonAnimation 0.5s 1";
setTimeout(() => {
captureButton.style.animation = "none";
}, 1000);
});

// Get current time stamp for file name
function getTimeStamp() {
return new Date().getTime();
}

// Filter helper
function getFilter(filter) {
switch (filter) {
case "filter-1": return "#cc3838ad";
case "filter-2": return "#0fbbbbad";
case "filter-3": return "#8ddb18ad";
case "filter-4": return "#ee82eead";
case "filter-5": return "#b8870bad";
case "filter-6": return "#ffffff00";
}
}

// Video Recorder Timers
function startClock() {
timingELem.classList.add("timing-active");
let timeCount = 0;
clearObj = setInterval(function () {
let seconds = (timeCount % 60) < 10 ? `0${timeCount % 60}` : `${timeCount % 60}`;
let minutes = (timeCount / 60) < 10 ? `0${Number.parseInt(timeCount / 60)}` : `${Number.parseInt(timeCount / 60)}`;
let hours = (timeCount / 3600) < 10 ? `0${Number.parseInt(timeCount / 3600)}` : `${Number.parseInt(timeCount / 3600)}`;
timingELem.innerText = `${hours}:${minutes}:${seconds}`;
timeCount++;
}, 1000);
}
function stopClock() {
timingELem.classList.remove("timing-active");
timingELem.innerText = "00:00:00";
clearInterval(clearObj);
}

// Filter apply
for (let i = 0; i < allFilters.length; i++) {
allFilters[i].addEventListener("click", function () {
uiFilter.classList.remove(uiFilter.classList[1]);
uiFilter.classList.add(allFilters[i].classList[1]);
})
}

// Zoom apply
zoomIn.addEventListener("click", function () {
if (scale > 1.9)
return;
scale += 0.1;
// -x for mirroring
video.style.transform = `scale(-${scale}, ${scale})`;
})
zoomOut.addEventListener("click", function () {
if (scale < 0.5)
return;
scale -= 0.1;
// -x for mirroring
video.style.transform = `scale(-${scale}, ${scale})`;
})
Loading

0 comments on commit b8ce06b

Please sign in to comment.