{"id":19732972,"url":"https://github.com/adelpro/face-api-detection","last_synced_at":"2026-02-12T13:37:39.836Z","repository":{"id":171047150,"uuid":"622894227","full_name":"adelpro/face-api-detection","owner":"adelpro","description":"Face detection using Face-api.js and vanilla JavaScript","archived":false,"fork":false,"pushed_at":"2024-12-17T13:56:27.000Z","size":5533,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-14T07:30:20.555Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adelpro.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-04-03T09:25:59.000Z","updated_at":"2024-12-17T13:56:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"febbd298-bdb9-4ac5-a09a-14e75f9456a7","html_url":"https://github.com/adelpro/face-api-detection","commit_stats":null,"previous_names":["adelpro/face-api-detection"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/adelpro/face-api-detection","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adelpro%2Fface-api-detection","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adelpro%2Fface-api-detection/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adelpro%2Fface-api-detection/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adelpro%2Fface-api-detection/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adelpro","download_url":"https://codeload.github.com/adelpro/face-api-detection/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adelpro%2Fface-api-detection/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267081607,"owners_count":24032930,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-25T02:00:09.625Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T00:28:41.978Z","updated_at":"2026-02-12T13:37:34.802Z","avatar_url":"https://github.com/adelpro.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"In this step by step tutorial, we will learn how to use Face-api.js and vanilla JavaScript to detect faces and expressions in real-time, all that from the browser, no back-end needed.\n\n### **What is Face-api.js?**\n\n[Face-api.js](https://justadudewhohacks.github.io/face-api.js/) is a JavaScript API for face detection and face recognition directly in the browser implemented build on top of the tensorflow.js\n\n### **What are we building?**\n\nIn this tutorial we will build a simple application that streams a video from the webcam of the PC or the camera of the phone, search for any faces present in it, and show a blue rectangle containing: the age, the gender and the expression for each face.\n\n### **List of models that we will use in our Tutorial**\n\n#### **Tiny Face Detector**\n\nVery performant, real time face detector, This model is extremely mobile and web friendly, thus it should be your GO-TO face detector on mobile devices and resource limited clients. The size of the quantized model is only 190 KB (**tiny\\_face\\_detector\\_model**).\n\n#### **68 Point Face Landmark Detection Models**\n\nThis package implements a very lightweight and fast, yet accurate 68 point face landmark detector. The default model has a size of only 350kb (**face\\_landmark\\_68\\_model**) and the tiny model is only 80kb (**face\\_landmark\\_68\\_tiny\\_model**). Both models employ the ideas of depth wise separable convolutions as well as densely connected blocks. The models have been trained on a dataset of ~35k face images labelled with 68 face landmark points.\n\n#### **Age Gender model**\n\nAge estimation and gender recognition model from detected faces ( for each face detected in the image or the video).\n\n#### **Face expression model**\n\nFace expression recognition model, can detect expressions in an image or a video of each face. \n\n### **Let’s code**\n\nOur application structure will look like this:\n\n```plaintext\n/Root\n ├─ /models\n ├─ app.js\n ├─ face-api.min.js\n ├─ styles.css\n └─ index.html\n```\n\n#### **./models**\n\nContain the files of all the trained models to use with our Face-api.js API.\n\n%[https://github.com/adelpro/face-api-detection/tree/0796c1df82306cd8b6e7e837036399559572b23c/models] \n\n#### **face-api.min.js**\n\nContain the code of our face-api API (minified), you can download this file from here:\n\n%[https://github.com/adelpro/face-api-detection/blob/0796c1df82306cd8b6e7e837036399559572b23c/face-api.min.js] \n\n#### **styles.css**\n\nA simple CSS files to style our application:\n\n```css\n.container {\n\n display: flex;\n\n justify-content: centre;\n\n flex-direction: column;\n\n align-items: centre;\n\n height: 100vh;\n\n text-align: centre;\n\n flex: 1;\n\n}\n\n\n.video-container {\n\n position: relative;\n\n}\n\n\ncanvas {\n\n position: absolute;\n\n top: 0;\n\n left: 0;\n\n}\n```\n\nAs you can see we have a canvas element that will be positioned over our video, and we will use it to draw our face detection.\n\n#### **index.html**\n\nThis file contain all the necessary HTML code for your application, we will do all the logic in our app.js\n\n```xml\n\u003c!DOCTYPE html\u003e\n\n\u003chtml lang=\"en\"\u003e\n\n\u003chead\u003e\n\n \u003cmeta charset=\"UTF-8\"\u003e\n\n \u003cmeta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"\u003e\n\n \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n\n \u003ctitle\u003eFace-API AI Real-Time Facial Detection\u003c/title\u003e\n\n \u003clink rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\"\u003e\n\n \u003cscript defer src=\"face-api.min.js\"\u003e\u003c/script\u003e\n\n \u003cscript defer src=\"app.js\"\u003e\u003c/script\u003e\n\n\u003c/head\u003e\n\n\n\u003cbody\u003e\n\n \u003cmain class=\"container\"\u003e\n\n   \u003ch1\u003eReal-Time facial detection\u003c/h1\u003e\n\n   \u003cp\u003eWe will use Javascript and Face-API to create a real time facial detection system\u003c/p\u003e\n\n   \u003cdiv id=\"video-container\" class=\"video-container\"\u003e\n\n     \u003cvideo id=\"video\" autoplay muted width=\"500\" height=\"500\"\u003e\u003c/video\u003e\n\n   \u003c/div\u003e\n\n \u003c/main\u003e\n\n\u003c/body\u003e\n\n\u003c/html\u003e\n```\n\n#### **app.js**\n\n```javascript\nconst video = document.getElementById(\"video\");\n\nconst videoContainer = document.getElementById(\"video-container\");\n\nconst MODEL_URI = \"/models\";\n\nPromise.all([\n\n faceapi.nets.tinyFaceDetector.loadFromUri(MODEL_URI),\n\n faceapi.nets.faceLandmark68Net.loadFromUri(MODEL_URI),\n\n faceapi.nets.faceRecognitionNet.loadFromUri(MODEL_URI),\n\n faceapi.nets.faceExpressionNet.loadFromUri(MODEL_URI),\n\n faceapi.nets.ageGenderNet.loadFromUri(MODEL_URI),\n\n])\n\n .then(playVideo)\n\n .catch((err) =\u003e {\n\n   console.log(err);\n\n });\nfunction playVideo() {\n\n if (!navigator.mediaDevices) {\n\n   console.error(\"mediaDevices not supported\");\n\n   return;\n\n }\n\n navigator.mediaDevices\n\n   .getUserMedia({\n\n     video: {\n\n       width: { min: 640, ideal: 1280, max: 1920 },\n\n       height: { min: 360, ideal: 720, max: 1080 },\n\n     },\n\n     audio: false,\n\n   })\n\n   .then(function (stream) {\n\n     video.srcObject = stream;\n\n   })\n\n   .catch(function (err) {\n\n     console.log(err);\n\n   });\n\n}\n\nvideo.addEventListener(\"play\", () =\u003e {\n\n // Creating the canvas\n\n const canvas = faceapi.createCanvasFromMedia(video);\n\n\n // This will force the use of a software (instead of hardware accelerated)\n\n // Enable only for low configurations\n\n canvas.willReadFrequently = true;\n\n videoContainer.appendChild(canvas);\n\n\n // Resizing the canvas to cover the video element\n\n const canvasSize = { width: video.width, height: video.height };\n\n faceapi.matchDimensions(canvas, canvasSize);\n\n\n setInterval(async () =\u003e {\n\n   const detections = await faceapi\n\n     .detectAllFaces(video, new faceapi.TinyFaceDetectorOptions())\n\n     .withFaceLandmarks()\n\n     .withFaceExpressions()\n\n     .withAgeAndGender();\n\n\n   // Set detections size to the canvas size\n\n   const DetectionsArray = faceapi.resizeResults(detections, canvasSize);\n\n   canvas.getContext(\"2d\").clearRect(0, 0, canvas.width, canvas.height);\n\n   detectionsDraw(canvas, DetectionsArray);\n\n }, 10);\n\n});\n\n\n// Drawing our detections above the video\n\nfunction detectionsDraw(canvas, DetectionsArray) {\n\n // Adjust the size of the detection canvas\n\n faceapi.draw.drawDetections(canvas, DetectionsArray);\n\n faceapi.draw.drawFaceLandmarks(canvas, DetectionsArray);\n\n faceapi.draw.drawFaceExpressions(canvas, DetectionsArray);\n\n\n // Drawing AGE and GENDER\n\n DetectionsArray.forEach((detection) =\u003e {\n\n   const box = detection.detection.box;\n\n   const drawBox = new faceapi.draw.DrawBox(box, {\n\n     label: ${Math.round(detection.age)}y, ${detection.gender},\n\n   });\n\n   drawBox.draw(canvas);\n\n });\n\n}\n\nNow we will go throw app.js, and explain different code blocks.\n\nconst MODEL_URI = \"/models\";\n\nPromise.all([\n\n faceapi.nets.tinyFaceDetector.loadFromUri(MODEL_URI),\n\n faceapi.nets.faceLandmark68Net.loadFromUri(MODEL_URI),\n\n faceapi.nets.faceRecognitionNet.loadFromUri(MODEL_URI),\n\n faceapi.nets.faceExpressionNet.loadFromUri(MODEL_URI),\n\n faceapi.nets.ageGenderNet.loadFromUri(MODEL_URI),\n\n])\n\n .then(playVideo)\n\n .catch((err) =\u003e {\n\n   console.log(err);\n\n });\n```\n\nIn this code block, we are loading our models files from the ‘/models’ folder using **Promise.all\\[\\]**, which allows us to wait for all models to load (it will take some time, depending on your hardware). \n\nThen, we call the function **playVideo** and of course catch any errors and show them in the console.\n\nOur **playVideo()** function\n\nFirst we check if the browser support [mediaDevices API](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices) , if not we stop and execution of the function and show an error in the console: “mediaDevices not supported”\n\nThen we call the mediaDevice.getUserMedia: this will show a notification to the user, asking permission to access the camera ( no sound in our case),if the user refuses, we throw an error.\n\nIf all goes well, we assign the stream to our video element:\n\nvideo.srcObject = stream;\n\nNow our video element starts showing a live stream from the camera.\n\nvideo.addEventListener(\"play\", () =\u0026gt; {\n\n // Creating the canvas\n\n const canvas = faceapi.createCanvasFromMedia(video);\n\n```javascript\nfunction playVideo() {\n\n if (!navigator.mediaDevices) {\n\n   console.error(\"mediaDevices not supported\");\n\n   return;\n\n }\n\n navigator.mediaDevices\n\n   .getUserMedia({\n\n     video: {\n\n       width: { min: 640, ideal: 1280, max: 1920 },\n\n       height: { min: 360, ideal: 720, max: 1080 },\n\n     },\n\n     audio: false,\n\n   })\n\n   .then(function (stream) {\n\n     video.srcObject = stream;\n\n   })\n\n   .catch(function (err) {\n\n     console.log(err);\n\n   });\n\n}\n // This will force the use of a software (instead of hardware accelerated)\n\n // Enable only for low configurations\n\n canvas.willReadFrequently = true;\n\n videoContainer.appendChild(canvas);\n\n\n // Resizing the canvas to cover the video element\n\n const canvasSize = { width: video.width, height: video.height };\n\n faceapi.matchDimensions(canvas, canvasSize);\n\n\n setInterval(async () =\u003e {\n\n   const detections = await faceapi\n\n     .detectAllFaces(video, new faceapi.TinyFaceDetectorOptions())\n\n     .withFaceLandmarks()\n\n     .withFaceExpressions()\n\n     .withAgeAndGender();\n\n\n   // Set detections size to the canvas size\n\n   const DetectionsArray = faceapi.resizeResults(detections, canvasSize);\n\n   canvas.getContext(\"2d\").clearRect(0, 0, canvas.width, canvas.height);\n\n   detectionsDraw(canvas, DetectionsArray);\n\n }, 10);\n\n});\n```\n\nNow come's this block of code, this will be executed when the video starts playing.\n\nIn this block of code we will start drawing our different detection: face, landmarks, expressions, age, gender. All that using the canvas element.\n\nFirst: creating the canvas and assign it to the video element\n\n```javascript\nconst canvas = faceapi.createCanvasFromMedia(video);\n\n// This will force the use of a software (instead of hardware accelerated)\n\n // Enable only for low configurations\n\n canvas.willReadFrequently = true;\n\n videoContainer.appendChild(canvas);\n```\n\nThen resize the canvas to muth the video element\n\n```javascript\n// Resizing the canvas to cover the video element\n\n const canvasSize = { width: video.width, height: video.height };\n\n faceapi.matchDimensions(canvas, canvasSize);\n\nStart a timer that will search for face detection in the video stream, and draw the results over our canvas\n\nsetInterval(async () =\u003e {\n\n   const detections = await faceapi\n\n     .detectAllFaces(video, new faceapi.TinyFaceDetectorOptions())\n\n     .withFaceLandmarks()\n\n     .withFaceExpressions()\n\n     .withAgeAndGender();\n\n\n   // Set detections size to the canvas size\n\n   const DetectionsArray = faceapi.resizeResults(detections, canvasSize);\n\n   canvas.getContext(\"2d\").clearRect(0, 0, canvas.width, canvas.height);\n\n   detectionsDraw(canvas, DetectionsArray);\n\n }, 10);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadelpro%2Fface-api-detection","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadelpro%2Fface-api-detection","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadelpro%2Fface-api-detection/lists"}