_attach_profile_and_presence. Internal helper function. This docstring was expanded to make future maintenance easier. Returns: Varies.
()
| 10134 | canvasEl.width = w; canvasEl.height = h; |
| 10135 | } |
| 10136 | function stopLive(){ |
| 10137 | if(liveLoop){ cancelAnimationFrame(liveLoop); liveLoop = null; } |
| 10138 | try{ if(cameraActive && typeof cameraActive.stop === 'function'){ cameraActive.stop(); } }catch(e){} |
| 10139 | cameraActive = null; |
| 10140 | if(stream){ try{ stream.getTracks().forEach(t=>t.stop()); }catch(e){} } |
| 10141 | stream = null; |
| 10142 | if(videoEl.srcObject){ try{ videoEl.srcObject.getTracks().forEach(t=>t.stop()); }catch(e){} } |
| 10143 | videoEl.srcObject = null; |
| 10144 | try{ videoEl.pause(); }catch(e){} |
| 10145 | } |
| 10146 | function stopUploadMedia(){ |
| 10147 | if(uploadLoop){ cancelAnimationFrame(uploadLoop); uploadLoop = null; } |
| 10148 | if(uploadedVideo){ try{ uploadedVideo.pause(); }catch(e){} if(uploadedVideo.src && uploadedVideo.src.startsWith('blob:')){ try{ URL.revokeObjectURL(uploadedVideo.src); }catch(e){} } } |
| 10149 | if(uploadedImage && uploadedImage.src && uploadedImage.src.startsWith('blob:')){ try{ URL.revokeObjectURL(uploadedImage.src); }catch(e){} } |
| 10150 | uploadedImage = null; uploadedVideo = null; |
| 10151 | } |
| 10152 | function calcDist(p1, p2) { return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)); } |
| 10153 | function calcAngle(p1, p2) { return Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI; } |
| 10154 | function getEmotion(landmarks, faceWidth, faceHeight) { |
| 10155 | const mouthOpen = calcDist(landmarks[13], landmarks[14]) / faceHeight; |
| 10156 | const mouthWidth = calcDist(landmarks[61], landmarks[291]) / faceWidth; |
| 10157 | const browInnerDist = calcDist(landmarks[55], landmarks[285]) / faceWidth; |
| 10158 | const eyeOpen = (calcDist(landmarks[159], landmarks[145]) + calcDist(landmarks[386], landmarks[374])) / (2 * faceHeight); |
| 10159 | if (mouthOpen > 0.08 && eyeOpen > 0.045) return (I18N.emotionSurprised || 'SURPRISED') + ' 😲'; |
| 10160 | if (mouthWidth > 0.40 && mouthOpen > 0.02) return (I18N.emotionHappy || 'HAPPY') + ' 😊'; |
| 10161 | if (browInnerDist < 0.22 && eyeOpen < 0.035) return (I18N.emotionAngry || 'ANGRY') + ' 😠'; |
| 10162 | if (mouthWidth < 0.32 && mouthOpen < 0.02) return (I18N.emotionSad || 'SAD') + ' 😔'; |
| 10163 | return (I18N.emotionNeutral || 'NEUTRAL') + ' 😐'; |
| 10164 | } |
| 10165 | |
| 10166 | if (typeof FaceMesh === 'undefined') { setStatus('MediaPipe failed to load. Refresh the page and try again.'); return; } |
| 10167 | const faceMesh = new FaceMesh({ locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/face_mesh/${file}` }); |
| 10168 | faceMesh.setOptions({ maxNumFaces: 3, refineLandmarks: true, minDetectionConfidence: 0.6, minTrackingConfidence: 0.6 }); |
nothing calls this directly
no test coverage detected