Programming/Web

Mediapipe를 활용한 vision-depending-display 제작: 에러모음(업데이트중)

stein 2021. 9. 19. 17:51

1.  npm 을 사용하여 media-pipe 사용하기

설명에 들어가기에 앞서, media-pipe는 javascript를 별로 좋아하지 않는 것 같다는 필자의 생각을 먼저 말한다. (공식 문서도 없고 원본 코드도 찾을 수가 없다...)

 

https://google.github.io/mediapipe/solutions/face_mesh.html#javascript-solution-api

위 링크로 들어가면 javascript 버전의 face_mesh 코드가 적혀져있다. 다만, CDN 사용법 기준으로 적혀져있기 때문에 조금 찝찝하기 때문에 설명에 적혀져있는 npm을 다운받아보았다.

 

...?

 

그리고 npm 코드를 어떤 식으로 사용해야하는지는 공식문서 어디에도 적혀져있지 않았다.

어쨌든 npm이 있다는건 동작하는 것일 테니, cdn코드라도 참고해보자.

...
const faceMesh = new FaceMesh({locateFile: (file) => {
  return `https://cdn.jsdelivr.net/npm/@mediapipe/face_mesh/${file}`;
}});
...

 FaceMesh라는 객체만 어떻게든 선언하면 될 듯하다. module을 import 해보자.

모듈 임포트, 그리고 console.log로 찍어보았다.
제대로 import 한 듯 하다. 특히 우리가 필요한 setOptions, onResults등의 코드도 저기에 보인다.

자 여기서 javascript의 특징을 짚고 넘어가자. javascript는 객체지향 언어이지만 class가 없다!(ECMA6에서 class가 추가되긴 했다)

그러면 어떤식으로 객체지향을 구현한단 말인가? 저기 위에있는 new는 무엇인가?

 

이 질문에 답하기 위해서는 prototype에 대한 이해가 필요하다. 다만 여기서는 'new 함수()'의 형태로 class와 같이 사용할 수 있다는 것만 말하고 넘어간다. 더 자세한 설명이 필요하면 아래의 포스트를 읽는 것을 추천한다

https://medium.com/@bluesh55/javascript-prototype-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-f8e67c286b67

 

 

[Javascript ] 프로토타입 이해하기

자바스크립트는 프로토타입 기반 언어라고 불립니다. 자바스크립트 개발을 하면 빠질 수 없는 것이 프로토타입인데요. 프로토타입이 거의 자바스크립트 그 자체이기때문에 이해하는 것이 어렵

medium.com

다음과 같이 코드를 사용하면 된다

코드 내용으로 보아하니, cdn을 코드 중간에서 받아온다. 우리는 이미 npm을 통해 미리 파일들을 받아놓았으니 import 한 FaceMesh의 FaceMesh 함수를 가져와 객체를 생성한다.

onResult 내부도 마찬가지로 수정해준다

위 내용만 인지하면 cdn코드에서 npm 코드로 변환은 문제없다!

 

2. JavaScript에서 device를 받아올 때, No navigator.mediaDevices.getUserMedia exists 에러

MediaPipe의 camera utils를 사용하는데 localhost에서는 작동하고 private ip로 직접 접근하니 다음과 같은 에러가 뜬다.

찾아보니 javascript에서 카메라, 마이크 device를 가져올 때, MediaDevices.getUserMedia(constraints)을 사용하는데, @mediapipe/camera_utils 내부 코드중 MediaDevices쪽 코드가 문제가 있다고 생각했다.

 

그래서 직접 MediaDevices.getUserMedia 코드를 돌려봤다.

undefined?

navigator를 console로 찍어봐도 mediaDevices는 보이지 않는다. 그래서 해당 키워드로 검색하니

https://velog.io/@juna-dev/navigator.mediaDevices-undefined-%ED%95%B4%EA%B2%B0

 

navigator.mediaDevices undefined 해결

최신 크롬에선 https가 아닐 경우, mediaDevices 를 제공하지 않는다

velog.io

https가 아니면 사용자의 device를 주지 않는다고 한다. (생각해보니 엄청 중요한 기능이다)

 

그리고 다시 공식문서를 가보니 다음과 같이 적혀져있다.

참고: 현재 문서를 안전하게 불러온 경우가 아니라면 navigator.mediaDevices는 undefined이므로 getUserMedia()도 사용할 수 없습니다. 개인정보와 보안 항목에서 getUserMedia()와 관련된 보안 문제를 자세히 살펴보세요.

(안전하게 불러온 경우를 https라고 적어놨으면 얼마나 좋을까)

 

크롬에서 이를 해결하려면

chrome://flags/#unsafely-treat-insecure-origin-as-secure

에서 보안 정책을 무시할려는 주소를 포트까지 작성하고 재시작 하면 된다고 한다.

 

 

3.  face_mesh 관련 .js 를 못 받아오는 에러

형태를 보아하니 static serve쪽 같다

매번 편하게 vue, nuxt와 같이 잘 만들어진 hight-level application들에서만 개발하다가, low level에서 직접 webpack으로 사용하니 생각지도 못한 곳에서 계속 에러를 만난다.

 

일단 에러를 보자. 내가 host 하고 있는 서버에 .js 파일을 요청했고, 404 not found 에러가 떴다. face_mesh가 저걸 어디서 불러온건지 확인해보기 위해 node_modules 내부로 가보았다.

역시 여기 있었다.
난독화가 되어있지만, url 형태로 박혀있다는 건 확실하다.

일단 node_modules밑에 파일들이 존재하니, 해당 파일들을 webpack-server가 static으로 같이 serve해주면 문제가 해결될 것이다.

기존에 .dist를 static으로 serve하고 있던 webpack
필요한 파일들이 있는 디렉토리를 추가로 연결해준다.

다행히 array 형태로 경로가 추가가 되었고, http://localhost:8080/face_mesh_solution_packed_assets_loader.js 로 접근하면 정상적으로 static file이 serve되는 것을 확인할 수 있다. 당연히 본 에러도 해결!

야호