Instascan: IOS ์‚ฌํŒŒ๋ฆฌ 11.4- ํ›„๋ฉด ์นด๋ฉ”๋ผ ์—ด๋ฆผ ๋ฌธ์ œ

์— ๋งŒ๋“  2018๋…„ 09์›” 27์ผ  ยท  44์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: schmich/instascan

์•ˆ๋…•ํ•˜์„ธ์š”,
Instascan์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ios safari์— ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
instascan์—์„œ๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์ง€๋งŒ ๋ฐฑ ์นด๋ฉ”๋ผ๋ฅผ ์—ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ „๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์—ด ๋•Œ๋งˆ๋‹ค.
Android(Chrome, Firefox)์—์„œ๋„ ๋™์ผํ•œ ์ฝ”๋“œ๊ฐ€ ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

 ์ž๊ธฐ ์ž์‹ ;
 isQRScannerInitialised = ๊ฑฐ์ง“;
 ํ•จ์ˆ˜ testQrCode(textBoxId,DivWidth){
 ์ž๊ธฐ = ์ดˆ๊ธฐํ™”QRScanner(DivWidth);

 self.scanner.addListener('์Šค์บ”', ํ•จ์ˆ˜(๋‚ด์šฉ, ์ด๋ฏธ์ง€) {
 if(textBoxId == $("#hiddenTextBox").val()){
 ์˜ค๋””์˜ค.์žฌ์ƒ();
 var ์ฝ”๋“œ = ๋‚ด์šฉ;
 $("#"+textBoxId).val(์ฝ”๋“œ);
 isQRScannerInitialised = ๊ฑฐ์ง“;

 }

 }, ๊ฑฐ์ง“);

 }

 ํ•จ์ˆ˜ ์ดˆ๊ธฐํ™”QRScanner(DivWidth){

 ์ž๊ธฐ = ์ด๊ฒƒ;

 if(isQRScannerInitialised == ๊ฑฐ์ง“){

 var ์ž„์‹œ ๋น„๋””์˜ค = document.getElementsByTagName("๋น„๋””์˜ค")[0];
 tempVideo.width=DivWidth;
 ์ž„์‹œ ๋น„๋””์˜ค.๋†’์ด=480;

 self.scanner = new Instascan.Scanner({ ๋น„๋””์˜ค: document.getElementsByTagName("๋น„๋””์˜ค")[0],mirror:false, scanPeriod: 1});

 Instascan.Camera.getCameras().then(ํ•จ์ˆ˜(์นด๋ฉ”๋ผ) {
 self.cameras = ์นด๋ฉ”๋ผ;
 if (self.cameras.length > 0) {
 if(์นด๋ฉ”๋ผ[0].name.match(/back/) || ์นด๋ฉ”๋ผ[0].name.match(/Back/)){
 self.activeCameraId = ์นด๋ฉ”๋ผ[0].id;
 self.scanner.start(์นด๋ฉ”๋ผ[0]);
 } else if(์นด๋ฉ”๋ผ[1].name.match(/back/) || ์นด๋ฉ”๋ผ[1].name.match(/Back/)){
 self.activeCameraId = ์นด๋ฉ”๋ผ[1].id;
 self.scanner.start(์นด๋ฉ”๋ผ[1]);
 }
 isQRScannerInitialised = true;

 } ๋˜ ๋‹ค๋ฅธ {

 alert('์นด๋ฉ”๋ผ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
 isQRScannerInitialised = ๊ฑฐ์ง“;
 ๋ฐ˜ํ’ˆ;
 }
 }).catch(ํ•จ์ˆ˜(e) { 
 isQRScannerInitialised = ๊ฑฐ์ง“;
 alert("QR ์˜ค๋ฅ˜ ์ด๋ฆ„:-"+e.name + " & QR ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€:-"+e.message); console.error(e); 
 });

 }
 ์ž๊ธฐ ๋ฐ˜ํ™˜;
 }

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์ด๊ฒƒ์€ ํ›Œ๋ฅญํ•œ ์ œํ’ˆ์ด๊ณ  ์ •๋ง ์œ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋ฉ‹์ง€๊ฒŒ ๋งŒ๋“ค์–ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ์—ฐ๊ตฌ์—์„œ์ด instascan์˜ ๋ฌธ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • getCameras๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ Camera ํด๋ž˜์Šค๋Š” navigator.mediaDevices.enumerateDevices() ํ˜ธ์ถœ์„ ํ†ตํ•ด ์ˆ˜์ง‘๋œ MediaDeviceInfo ๊ฐ์ฒด์—์„œ ์ƒ์„ฑ๋œ Camera ๊ฐ์ฒด ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์Šค์บ๋„ˆ๋ฅผ ์‹œ์ž‘ํ•  ๋•Œ ์‚ฌ์šฉ๋œ ์นด๋ฉ”๋ผ์˜ ์‹ค์ œ ์ŠคํŠธ๋ฆผ์„ ํฌํ•จํ•˜๋Š” MediaStream ๊ฐœ์ฒด๊ฐ€ id _ ๋ฐ _ name _ ์†์„ฑ๋งŒ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. Camera ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์„ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

_scanner.start(camera)_๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์นด๋ฉ”๋ผ ์—์„œ _camera.start()_ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š”

  • ์˜ MediaStream์˜ Arrary๋ฅผ ๋ฐ˜ํ™˜ _camera.start () _ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ _navigator.mediaDevices.getUserMedia (์ œ์•ฝ ์กฐ๊ฑด)๋ฅผ ํ˜ธ์ถœ _๋Š” ๋ฐฉ๋ฒ•์— ๋‚˜์—ด๋œ ์ฃผ์–ด์ง„ ์ œ์•ฝ ์กฐ๊ฑด์— ๋”ฐ๋ผ ๊ฐ์ฒด.
  • _scanner.start()_๋Š” _scanner._enableScan(camera)_์„ ํ˜ธ์ถœํ•˜์—ฌ ์นด๋ฉ”๋ผ์—์„œ ์œ„์˜ ํ˜ธ์ถœ์—์„œ ๋ฐ˜ํ™˜๋œ ์ฒซ ๋ฒˆ์งธ MediaStream ๊ฐœ์ฒด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์„ค์ •
                  **This Part Is the Disconnect and what is messing it all up!**

์ œ์•ฝ ๋ฌธ์ œ:

์ „๋‹ฌ๋œ Camera ๊ฐœ์ฒด๋Š” ์ œ์•ฝ ์กฐ๊ฑด์—์„œ ํ•ด๋‹น ID ๋ฅผ ์žฅ์น˜ ๊ฒ€์ƒ‰์— _"ํ•„์ˆ˜"_๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ฐพ์„ ์ˆ˜ ์—†์œผ๋ฉด ๋น„๋””์˜ค๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋‹ค๋ฅธ "ํ•„์ˆ˜" ์ œ์•ฝ ์กฐ๊ฑด์ด ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์žฅ์น˜๋Š” ์‚ฌ์šฉ๋œ ์ œ์•ฝ ์กฐ๊ฑด์„ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค!
์‚ฌ์šฉํ•˜๋ ค๋Š” ์žฅ์น˜์—์„œ ์ด ๋งํฌ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์ง€์›ํ•˜๋Š” ์ œ์•ฝ ์กฐ๊ฑด์ด ๋ฌด์—‡์ธ์ง€ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints

์‚ฌ์šฉํ•˜๋ ค๋Š” ์žฅ์น˜์—์„œ ์ด ๋งํฌ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์ œ์•ฝ ์กฐ๊ฑด์„ ์ž…๋ ฅํ•˜์‹ญ์‹œ์˜ค. ์ง€์› ์—ฌ๋ถ€๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackSupportedConstraints/deviceId

Ipad/Iphone/IOS ์ง€์› ์ œ์•ฝ:

aspectRatio, facesMode, _deviceId * _ , ๋†’์ด, ๋„ˆ๋น„, aspectRatio ๋“ฑ.

_๋‚ด๊ฐ€ ์ด๊ฒƒ์„ ํ…Œ์ŠคํŠธํ•  ๋•Œ _deviceId๋Š” ์ œ์•ฝ ์กฐ๊ฑด์œผ๋กœ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค._ ์ œ์•ฝ ์กฐ๊ฑด ์— ๋Œ€ํ•ด ์œ„์˜ ๋งํฌ์—์„œ ์ด๊ฒƒ์„ ์‹œ๋„ํ•˜๋ฉด deviceId = ""๋กœ ์„ค์ •๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž๋ฐ” ์Šคํฌ๋ฆฝํŠธ์—์„œ ์žก์•„์„œ ํ‘œ์‹œํ–ˆ์„ ๋•Œ iphone์€ ํ•ญ์ƒ ๋นˆ deviceId๋ฅผ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ Iphone์—์„œ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์žก์œผ๋ ค๋ฉด deviceId๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  faceMode๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Android ์ง€์› ์ œ์•ฝ:

deviceId, _facingMode * _, aspectRatio, ๋†’์ด, ๋„ˆ๋น„ ๋“ฑ.

๋‚˜๋Š” ์ด๊ฒƒ์„ ์‚ผ์„ฑ ํƒœ๋ธ”๋ฆฟ๊ณผ ์•ˆ๋“œ๋กœ์ด๋“œ ํฐ์—์„œ ํ…Œ์ŠคํŠธํ–ˆ๋‹ค. faceMode์˜ ๊ธฐ๋ณธ๊ฐ’์€ "์‚ฌ์šฉ์ž" ์ „๋ฉด ์นด๋ฉ”๋ผ์ž…๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋ฅผ ์‹คํ—˜ํ•œ ๊ฒฐ๊ณผ ์•„์ง๊นŒ์ง€ ๋ฐœ๊ฒฌํ•œ ์–ด๋–ค ์ด์œ ๋กœ Android์šฉ facesMode๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์œ„์˜ ๋งํฌ์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ ๋ถ€๋ถ„์„ ๊ณ„์† ์กฐ์‚ฌํ•  ๊ฒƒ์ด๊ณ  ์•„๋งˆ๋„ ์ด ์ฝ”๋“œ๊ฐ€ facesMode ๋ฐ android์—์„œ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋„๋ก ์ˆ˜์ •ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

* * Android ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋‹ต๋ณ€ * * *
์ด ํ”„๋กœ์ ํŠธ์˜ Gulp ๋นŒ๋“œ์—๋Š” Android Chrome์—์„œ facesMode๋ฅผ ์—‰๋ง์œผ๋กœ ๋งŒ๋“œ๋Š” webrtc-adapter ๋ฒ„์ „ ^1.4.0์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ์‹ค์ œ๋กœ ์ง๋ฉด ๋ชจ๋“œ๋ฅผ ์‚ญ์ œํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ์ด ํ”„๋กœ์ ํŠธ์—์„œ ์ˆ˜์ •ํ•˜๋ ค๋ฉด - _index.js_์—์„œ 2ํ–‰ require('webrtc-adapter'); ์ œ๊ฑฐํ•œ ๋‹ค์Œ ์•„๋ž˜ ๋นŒ๋“œ ์ ˆ์ฐจ๋ฅผ ๋”ฐ๋ฅด์„ธ์š”. Chrome์—์„œ ํƒœ๋ธ”๋ฆฟ๊ณผ 4๊ฐœ์˜ ๋‹ค๋ฅธ Android ํœด๋Œ€์ „ํ™”์—์„œ ํ…Œ์ŠคํŠธํ–ˆ์„ ๋•Œ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์žก๊ธฐ ์œ„ํ•ด ๋ชจ๋‘ ๋‹ค์‹œ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด instascan ์ฝ”๋“œ๋กœ Android์˜ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์žก์œผ๋ ค๋ฉด deviceId๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
deviceId๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ _video_ ์ œ์•ฝ ์กฐ๊ฑด์ธ์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.

video: {
  devideId: this.id
}

์นด๋ฉ”๋ผ ์ œ์•ฝ ์ฝ”๋“œ:

๋‹ค์Œ์€ ์ œ์•ฝ ์กฐ๊ฑด์„ ์„ค์ •ํ•˜๊ณ  MediaStream ๊ฐœ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํ”„๋กœ์ ํŠธ์˜ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.
์ด ์ฝ”๋“œ๊ฐ€ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” _video ์ œ์•ฝ ์กฐ๊ฑด _ ์˜ sourceId๊ฐ€ _Android_ ๋˜๋Š” _Iphone_์—์„œ ์ง€์›๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ deviceId ๋กœ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค . ๋˜ํ•œ ๋ชจ๋“  ํ•„์ˆ˜ ํ•ญ๋ชฉ์€ ์žฅ์น˜๊ฐ€ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์ด๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

async start() {
    let constraints;
    var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

    if (iOS) {
      constraints = {
        audio: false,
        video: {
          facingMode: 'environment',
          mandatory: {
            sourceId: this.id,
            minWidth: 600,
            maxWidth: 800,
            minAspectRatio: 1.6
          },
          optional: []
        }
      };
    } else {
      constraints = {
        audio: false,
        video: {
          mandatory: {
            sourceId: this.id,
            minWidth: 600,
            maxWidth: 800,
            minAspectRatio: 1.6
          },
          optional: []
        }
      };
    }

    this._stream = await Camera._wrapErrors(async () => {
      return await navigator.mediaDevices.getUserMedia(constraints);
});

InstaScan์„ ์ˆ˜์ •ํ•˜๊ณ  ์ถ•์†Œํ•˜๋Š” ๋ฐฉ๋ฒ•:

์ด๊ฒƒ์„ ์–ป๊ณ  ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด VSCode๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
1) Node.js์™€ vsCode๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
2) ๋‹ค์šด๋กœ๋“œํ•˜๋ ค๋Š” ๋””๋ ‰ํ† ๋ฆฌ์˜ ํ„ฐ๋ฏธ๋„์—์„œ ๋‹ค์Œ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
git clone https://github.com/JoseCDB/instascan.git

3) ํ„ฐ๋ฏธ๋„ cd์—์„œ instascan ๋””๋ ‰ํ† ๋ฆฌ๋กœ:
cd instascan

4) ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  gulp๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.
gulp release

5) ์ด๊ฒƒ์€ _dist_ ํด๋”์— ์ƒˆ๋กœ์šด ์ถ•์†Œ๋œ instascan.min.js ํ•ญ๋ชฉ์„ ์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋ฒˆ ์ฃผ๋ง์— ์ด Android ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๋ฉ‹์ง„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ํ–ฅํ›„ ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ ์ถฉ๋ถ„ํ•œ ํ†ต์ฐฐ๋ ฅ์„ ์–ป์„ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋ชจ๋“  44 ๋Œ“๊ธ€

Apple ์žฅ์น˜์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋ฐ๋ชจ๊ฐ€ ์ž‘๋™ํ•˜๋Š”์ง€ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

์ด๊ฒƒ์€ iOS ์‚ฌํŒŒ๋ฆฌ์— ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ ์‚ฌ๋žŒ๋“ค์ด ๋ฉ”ํƒ€ ํƒœ๊ทธ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ด ๋ฌธ์ œ๋ฅผ ๊ทน๋ณตํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ํฌ๋Ÿผ์„ ๋‘˜๋Ÿฌ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋น„์Šทํ•œ ์ผ์„ ํ•˜๊ณ  ์žˆ์–ด์„œ ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ €๋ฅผ ๋ง์„ค์ด๊ฒŒ ํ•˜๋Š” ๊ฒƒ์€ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์น˜๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

iPhone์—์„œ ๋ฐ๋ชจ๋ฅผ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์ž‘๋™ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๋„ค, ์ด ์ผ์„ ํ•˜๊ณ  ์žˆ๋Š”๋ฐ ์ž‘๋™์ด ์•ˆ ๋ผ์š”. ๋Œ์•„๊ฐ€์„œ ์Šค๋ ˆ๋“œ๋ฅผ ๋‹ค์‹œ ์ฝ์œผ๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค. ์ตœ์‹  ์›น RTC ์–ด๋Œ‘ํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ๋น„๋””์˜ค ํƒœ๊ทธ์— _playsinline_ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ „๋ฉด ์นด๋ฉ”๋ผ๊ฐ€ ์ž‘๋™ํ•˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. ์นด๋ฉ”๋ผ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ์ง€๋งŒ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋กœ ๊ต์ฒดํ•  ๋•Œ ์•„๋ฌด ์ž‘์—…๋„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋น„๋””์˜ค ํƒœ๊ทธ ์•ˆ์— ์†์„ฑ์„ ์ถ”๊ฐ€ํ–ˆ๊ณ  ๋ฉ”ํƒ€ ํƒœ๊ทธ๋„ ์–ธ๊ธ‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋น„๋””์˜ค ํƒœ๊ทธ ์•ˆ์—playsinline ์†์„ฑ์„ ์ถ”๊ฐ€ํ–ˆ๊ณ  ๋ฉ”ํƒ€ ํƒœ๊ทธ๋„ ์–ธ๊ธ‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ˆ„๊ตฐ๊ฐ€ ์‹ค์ œ๋กœ ์Šค๋ ˆ๋“œ ์ค‘ ํ•˜๋‚˜์—์„œ ์ด๊ฒƒ์„ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ์‹œ๋„ํ•˜๊ณ  ์žˆ์ง€๋งŒ iPhone์„ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ์ด ์ž‘๋™ํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ด, ๋‚˜๋Š” ์ด๊ฒƒ์„ ์ž‘๋™ ์‹œ์ผฐ์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๋”๋ผ๋„ ๊ธฐ๋ณธ๊ฐ’์€ ํ•ญ์ƒ ํ›„๋ฉด ํ›„๋ฉด ์นด๋ฉ”๋ผ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ „๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ ๋‚ด๊ฐ€ ํ•œ ์ผ์ด ์žˆ์Šต๋‹ˆ๋‹ค!

๋ฉ”ํƒ€ ํƒœ๊ทธ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.
<meta name="apple-mobile-web-app-capable" content="yes">

์ด ์†์„ฑ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.
<video id="scanner" class="video-back" playsinline></video>

์ด JS ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.
<script type="text/javascript" src="https://webrtc.github.io/adapter/adapter-latest.js"></script>

๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด๊ฒƒ์„ ํŒจํ‚ค์ง•ํ•˜์—ฌ ๋ฆด๋ฆฌ์Šคํ•ฉ๋‹ˆ๋‹ค: https://github.com/JoseCDB/instascan/tree/ios-rear-camera. node.js์™€ ํ•จ๊ป˜ Gulp๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ ์‰ฝ์Šต๋‹ˆ๋‹ค. 15๋ถ„๋งŒ์— ๋ฒŒ์—ˆ์–ด์š”! ๋‚˜๋Š” Instascan์˜ ์ด ์‚ฌ๋žŒ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Š” ๋ฌธ์ œ๋ฅผ ์•Œ๊ณ  ์žˆ์—ˆ๊ณ  ๊ณ ์น  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋„์›€์ด ๋˜์—ˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ํ–‰์šด์„ ๋น•๋‹ˆ๋‹ค.

๋ฉ”ํƒ€ ํƒœ๊ทธ, ๋น„๋””์˜ค ํƒœ๊ทธ ๋ฐ adapter-latest.js๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋‚˜๋Š” instscan.min.js๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ".js - scanner.js - camara.js"๋ฅผ ๋ณ„๋„๋กœ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฉ”ํƒ€ ํƒœ๊ทธ, ๋น„๋””์˜ค ํƒœ๊ทธ ๋ฐ adapter-latest.js๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋‚˜๋Š” instscan.min.js๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ".js - scanner.js - camara.js"๋ฅผ ๋ณ„๋„๋กœ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

node.js๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ชจ๋“  ํŒŒ์ผ์„ ํ•จ๊ป˜ ํŒจํ‚ค์ง€ํ•˜๋Š” ๋ช…๋ น ํ”„๋กฌํ”„ํŠธ๊ฐ€ ์žˆ์œผ๋ฉฐ ์ตœ์ข… ์ถœ๋ ฅ์€ instascanner์˜ ์ถ•์†Œ๋œ JS ํŒŒ์ผ์ด ๋ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ํ›Œ๋ฅญํ•œ ์ œํ’ˆ์ด๊ณ  ์ •๋ง ์œ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋ฉ‹์ง€๊ฒŒ ๋งŒ๋“ค์–ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ์—ฐ๊ตฌ์—์„œ์ด instascan์˜ ๋ฌธ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • getCameras๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ Camera ํด๋ž˜์Šค๋Š” navigator.mediaDevices.enumerateDevices() ํ˜ธ์ถœ์„ ํ†ตํ•ด ์ˆ˜์ง‘๋œ MediaDeviceInfo ๊ฐ์ฒด์—์„œ ์ƒ์„ฑ๋œ Camera ๊ฐ์ฒด ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์Šค์บ๋„ˆ๋ฅผ ์‹œ์ž‘ํ•  ๋•Œ ์‚ฌ์šฉ๋œ ์นด๋ฉ”๋ผ์˜ ์‹ค์ œ ์ŠคํŠธ๋ฆผ์„ ํฌํ•จํ•˜๋Š” MediaStream ๊ฐœ์ฒด๊ฐ€ id _ ๋ฐ _ name _ ์†์„ฑ๋งŒ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. Camera ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์„ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

_scanner.start(camera)_๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์นด๋ฉ”๋ผ ์—์„œ _camera.start()_ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š”

  • ์˜ MediaStream์˜ Arrary๋ฅผ ๋ฐ˜ํ™˜ _camera.start () _ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ _navigator.mediaDevices.getUserMedia (์ œ์•ฝ ์กฐ๊ฑด)๋ฅผ ํ˜ธ์ถœ _๋Š” ๋ฐฉ๋ฒ•์— ๋‚˜์—ด๋œ ์ฃผ์–ด์ง„ ์ œ์•ฝ ์กฐ๊ฑด์— ๋”ฐ๋ผ ๊ฐ์ฒด.
  • _scanner.start()_๋Š” _scanner._enableScan(camera)_์„ ํ˜ธ์ถœํ•˜์—ฌ ์นด๋ฉ”๋ผ์—์„œ ์œ„์˜ ํ˜ธ์ถœ์—์„œ ๋ฐ˜ํ™˜๋œ ์ฒซ ๋ฒˆ์งธ MediaStream ๊ฐœ์ฒด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์„ค์ •
                  **This Part Is the Disconnect and what is messing it all up!**

์ œ์•ฝ ๋ฌธ์ œ:

์ „๋‹ฌ๋œ Camera ๊ฐœ์ฒด๋Š” ์ œ์•ฝ ์กฐ๊ฑด์—์„œ ํ•ด๋‹น ID ๋ฅผ ์žฅ์น˜ ๊ฒ€์ƒ‰์— _"ํ•„์ˆ˜"_๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ฐพ์„ ์ˆ˜ ์—†์œผ๋ฉด ๋น„๋””์˜ค๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋‹ค๋ฅธ "ํ•„์ˆ˜" ์ œ์•ฝ ์กฐ๊ฑด์ด ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์žฅ์น˜๋Š” ์‚ฌ์šฉ๋œ ์ œ์•ฝ ์กฐ๊ฑด์„ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค!
์‚ฌ์šฉํ•˜๋ ค๋Š” ์žฅ์น˜์—์„œ ์ด ๋งํฌ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์ง€์›ํ•˜๋Š” ์ œ์•ฝ ์กฐ๊ฑด์ด ๋ฌด์—‡์ธ์ง€ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints

์‚ฌ์šฉํ•˜๋ ค๋Š” ์žฅ์น˜์—์„œ ์ด ๋งํฌ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์ œ์•ฝ ์กฐ๊ฑด์„ ์ž…๋ ฅํ•˜์‹ญ์‹œ์˜ค. ์ง€์› ์—ฌ๋ถ€๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackSupportedConstraints/deviceId

Ipad/Iphone/IOS ์ง€์› ์ œ์•ฝ:

aspectRatio, facesMode, _deviceId * _ , ๋†’์ด, ๋„ˆ๋น„, aspectRatio ๋“ฑ.

_๋‚ด๊ฐ€ ์ด๊ฒƒ์„ ํ…Œ์ŠคํŠธํ•  ๋•Œ _deviceId๋Š” ์ œ์•ฝ ์กฐ๊ฑด์œผ๋กœ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค._ ์ œ์•ฝ ์กฐ๊ฑด ์— ๋Œ€ํ•ด ์œ„์˜ ๋งํฌ์—์„œ ์ด๊ฒƒ์„ ์‹œ๋„ํ•˜๋ฉด deviceId = ""๋กœ ์„ค์ •๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž๋ฐ” ์Šคํฌ๋ฆฝํŠธ์—์„œ ์žก์•„์„œ ํ‘œ์‹œํ–ˆ์„ ๋•Œ iphone์€ ํ•ญ์ƒ ๋นˆ deviceId๋ฅผ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ Iphone์—์„œ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์žก์œผ๋ ค๋ฉด deviceId๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  faceMode๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Android ์ง€์› ์ œ์•ฝ:

deviceId, _facingMode * _, aspectRatio, ๋†’์ด, ๋„ˆ๋น„ ๋“ฑ.

๋‚˜๋Š” ์ด๊ฒƒ์„ ์‚ผ์„ฑ ํƒœ๋ธ”๋ฆฟ๊ณผ ์•ˆ๋“œ๋กœ์ด๋“œ ํฐ์—์„œ ํ…Œ์ŠคํŠธํ–ˆ๋‹ค. faceMode์˜ ๊ธฐ๋ณธ๊ฐ’์€ "์‚ฌ์šฉ์ž" ์ „๋ฉด ์นด๋ฉ”๋ผ์ž…๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋ฅผ ์‹คํ—˜ํ•œ ๊ฒฐ๊ณผ ์•„์ง๊นŒ์ง€ ๋ฐœ๊ฒฌํ•œ ์–ด๋–ค ์ด์œ ๋กœ Android์šฉ facesMode๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์œ„์˜ ๋งํฌ์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ ๋ถ€๋ถ„์„ ๊ณ„์† ์กฐ์‚ฌํ•  ๊ฒƒ์ด๊ณ  ์•„๋งˆ๋„ ์ด ์ฝ”๋“œ๊ฐ€ facesMode ๋ฐ android์—์„œ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋„๋ก ์ˆ˜์ •ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

* * Android ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋‹ต๋ณ€ * * *
์ด ํ”„๋กœ์ ํŠธ์˜ Gulp ๋นŒ๋“œ์—๋Š” Android Chrome์—์„œ facesMode๋ฅผ ์—‰๋ง์œผ๋กœ ๋งŒ๋“œ๋Š” webrtc-adapter ๋ฒ„์ „ ^1.4.0์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ์‹ค์ œ๋กœ ์ง๋ฉด ๋ชจ๋“œ๋ฅผ ์‚ญ์ œํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ์ด ํ”„๋กœ์ ํŠธ์—์„œ ์ˆ˜์ •ํ•˜๋ ค๋ฉด - _index.js_์—์„œ 2ํ–‰ require('webrtc-adapter'); ์ œ๊ฑฐํ•œ ๋‹ค์Œ ์•„๋ž˜ ๋นŒ๋“œ ์ ˆ์ฐจ๋ฅผ ๋”ฐ๋ฅด์„ธ์š”. Chrome์—์„œ ํƒœ๋ธ”๋ฆฟ๊ณผ 4๊ฐœ์˜ ๋‹ค๋ฅธ Android ํœด๋Œ€์ „ํ™”์—์„œ ํ…Œ์ŠคํŠธํ–ˆ์„ ๋•Œ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์žก๊ธฐ ์œ„ํ•ด ๋ชจ๋‘ ๋‹ค์‹œ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด instascan ์ฝ”๋“œ๋กœ Android์˜ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์žก์œผ๋ ค๋ฉด deviceId๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
deviceId๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ _video_ ์ œ์•ฝ ์กฐ๊ฑด์ธ์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.

video: {
  devideId: this.id
}

์นด๋ฉ”๋ผ ์ œ์•ฝ ์ฝ”๋“œ:

๋‹ค์Œ์€ ์ œ์•ฝ ์กฐ๊ฑด์„ ์„ค์ •ํ•˜๊ณ  MediaStream ๊ฐœ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํ”„๋กœ์ ํŠธ์˜ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.
์ด ์ฝ”๋“œ๊ฐ€ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” _video ์ œ์•ฝ ์กฐ๊ฑด _ ์˜ sourceId๊ฐ€ _Android_ ๋˜๋Š” _Iphone_์—์„œ ์ง€์›๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ deviceId ๋กœ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค . ๋˜ํ•œ ๋ชจ๋“  ํ•„์ˆ˜ ํ•ญ๋ชฉ์€ ์žฅ์น˜๊ฐ€ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์ด๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

async start() {
    let constraints;
    var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

    if (iOS) {
      constraints = {
        audio: false,
        video: {
          facingMode: 'environment',
          mandatory: {
            sourceId: this.id,
            minWidth: 600,
            maxWidth: 800,
            minAspectRatio: 1.6
          },
          optional: []
        }
      };
    } else {
      constraints = {
        audio: false,
        video: {
          mandatory: {
            sourceId: this.id,
            minWidth: 600,
            maxWidth: 800,
            minAspectRatio: 1.6
          },
          optional: []
        }
      };
    }

    this._stream = await Camera._wrapErrors(async () => {
      return await navigator.mediaDevices.getUserMedia(constraints);
});

InstaScan์„ ์ˆ˜์ •ํ•˜๊ณ  ์ถ•์†Œํ•˜๋Š” ๋ฐฉ๋ฒ•:

์ด๊ฒƒ์„ ์–ป๊ณ  ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด VSCode๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
1) Node.js์™€ vsCode๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
2) ๋‹ค์šด๋กœ๋“œํ•˜๋ ค๋Š” ๋””๋ ‰ํ† ๋ฆฌ์˜ ํ„ฐ๋ฏธ๋„์—์„œ ๋‹ค์Œ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
git clone https://github.com/JoseCDB/instascan.git

3) ํ„ฐ๋ฏธ๋„ cd์—์„œ instascan ๋””๋ ‰ํ† ๋ฆฌ๋กœ:
cd instascan

4) ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  gulp๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.
gulp release

5) ์ด๊ฒƒ์€ _dist_ ํด๋”์— ์ƒˆ๋กœ์šด ์ถ•์†Œ๋œ instascan.min.js ํ•ญ๋ชฉ์„ ์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋ฒˆ ์ฃผ๋ง์— ์ด Android ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๋ฉ‹์ง„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ํ–ฅํ›„ ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ ์ถฉ๋ถ„ํ•œ ํ†ต์ฐฐ๋ ฅ์„ ์–ป์„ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š”, ์ด๊ฒƒ์€ ์ž˜ ์ž‘๋™ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
๋จผ์ € https://github.com/webrtc/adapter ์—์„œ adapter.js ๋ฅผ ์ถ”๊ฐ€ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ ํ›„์— ์ด๊ฒƒ์„ ๋ณต์ œํ•˜์‹ญ์‹œ์˜ค.
git clone https://github.com/quocthai95/instascan.git
์šด์˜:
npm i
ํ•„์ˆ˜ํ’ˆ์„ ์„ค์น˜ํ•˜๊ธฐ ์œ„ํ•ด

gulp๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ตœ์ข… ์ฝ”๋“œ๋ฅผ ๋ฆด๋ฆฌ์Šคํ•ฉ๋‹ˆ๋‹ค.
gulp release

Iphone 6 plus(iOS 11.4) ๋ฐ Iphone 8 plus(iOS 11.3)์—์„œ ํ™•์ธํ–ˆ๋Š”๋ฐ ์ž˜ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค. ์นด๋ฉ”๋ผ๋ฅผ ์ •์ƒ์ ์œผ๋กœ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š”, ์ด๊ฒƒ์€ ์ž˜ ์ž‘๋™ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
๋จผ์ € https://github.com/webrtc/adapter ์—์„œ adapter.js ๋ฅผ ์ถ”๊ฐ€ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ ํ›„์— ์ด๊ฒƒ์„ ๋ณต์ œํ•˜์‹ญ์‹œ์˜ค.
git clone https://github.com/quocthai95/instascan.git
์šด์˜:
npm i
ํ•„์ˆ˜ํ’ˆ์„ ์„ค์น˜ํ•˜๊ธฐ ์œ„ํ•ด

gulp๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ตœ์ข… ์ฝ”๋“œ๋ฅผ ๋ฆด๋ฆฌ์Šคํ•ฉ๋‹ˆ๋‹ค.
gulp release

Iphone 6 plus(iOS 11.4) ๋ฐ Iphone 8 plus(iOS 11.3)์—์„œ ํ™•์ธํ–ˆ๋Š”๋ฐ ์ž˜ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค. ์นด๋ฉ”๋ผ๋ฅผ ์ •์ƒ์ ์œผ๋กœ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

ํ•„์ˆ˜ํ’ˆ์„ ์„ค์น˜ํ•  ๋•Œ "์ทจ์•ฝ์  12๊ฐœ(๋‚ฎ์Œ 1๊ฐœ, ๋ณดํ†ต 5๊ฐœ, ๋†’์Œ 6๊ฐœ)"๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.
์ผ๋ถ€ "$ npm install --save-dev [package-name]" ๋ช…๋ น์€ ์ด๋Ÿฌํ•œ ์ทจ์•ฝ์ ์„ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ด์ง€๋งŒ ๋‹ค์Œ ์˜ˆ์™ธ๋กœ ์ธํ•ด ๋นŒ๋“œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

$ gulp release assert.js:351 throw err; ^ AssertionError [ERR_ASSERTION]: ์ž‘์—… ๊ธฐ๋Šฅ์€ Gulp.set [as _setTask]์— ์ง€์ •๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(C:\Users\John\Downloads\instascan-ios-rear-camera\instascan-ios-rear-camera\node_modules\undertaker\lib \set-task.js:10:3)

์—ฌ๊ธฐ์—์„œ ์–ด๋–ป๊ฒŒ ์‹œ์ž‘ํ•ฉ๋‹ˆ๊นŒ? ์ด ๋นŒ๋“œ๋ฅผ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•ด๋ณด๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๋‚ด ์•ˆ๋“œ๋กœ์ด๋“œ ํฐ๊ณผ ์ž˜ ์–ด์šธ๋ฆฌ๋‚˜์š”?

/๋‚จ์ž

์•ˆ๋…•ํ•˜์„ธ์š” @johnatitide ,
gulp ์ตœ์‹  ๋ฒ„์ „(4.0.0)์„ ์„ค์น˜ํ•˜์…จ์Šต๋‹ˆ๊นŒ? ๊ทธ๋ ‡๋‹ค๋ฉด 3.9.1๋กœ ์ œํ•œํ•˜์‹ญ์‹œ์˜ค. ์ฐธ๊ณ ๋กœ:
https://github.com/ampproject/docs/issues/793#issuecomment -354836162
๋˜๋Š” ๋นŒ๋“œํ•˜๊ธฐ ์œ„ํ•ด ์ˆ˜ํ–‰ํ•œ ๋ช…๋ น์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” @quocthai95

๋นŒ๋“œ๋Š” ๋‹ค์Œ ๋ช…๋ น์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.
์ž์‹ ํด๋ก  https://github.com/quocthai95/instascan.git
npm ์„ค์น˜ [email protected]
npm ๋‚˜๋Š”
๊ฟ€๊บฝ๊ฟ€๊บฝ

์ด์ œ iPad ๋ฐ iPhone์˜ Safari์—์„œ ์นด๋ฉ”๋ผ๋ฅผ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฉ‹์ง„.

์ œ์•ฝ ์กฐ๊ฑด ์ˆ˜์ •์ด schmich์˜ ์ €์žฅ์†Œ์— ๋‹ค์‹œ ๋ณ‘ํ•ฉ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ œ์•ฝ ์กฐ๊ฑด ์ˆ˜์ •์ด schmich์˜ ์ €์žฅ์†Œ์— ๋‹ค์‹œ ๋ณ‘ํ•ฉ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ƒˆ๋กœ์šด pull ์š”์ฒญ์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์ ‘์ˆ˜๋ฅผ ๊ธฐ๋‹ค๋ฆฌ์„ธ์š”^^

@quocthai95 ์•ˆ๋…•ํ•˜์„ธ์š”, ive๋Š” https://github.com/schmich/instascan/issues/182#issuecomment -447198290์—์„œ ๊ท€ํ•˜์˜ ๋‹จ๊ณ„๋ฅผ ๋”ฐ๋ž์Šต๋‹ˆ๋‹ค.

๋‚ด ์•ˆ๋“œ๋กœ์ด๋“œ ํฌ๋กฌ์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ „๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์–ป๊ณ  ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. ํ›„๋ฐฉ์นด๋ฉ”๋ผ๋ฅผ ๊ธฐ๋ณธ์œผ๋กœ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์ œ ์ฝ”๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

@fariskas ,
regexp๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ /back/๊ณผ ์ผ์น˜ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•œ ๋‹ค์Œ ์‹œ์ž‘ํ•˜๋ฉด ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ๊ธฐ๋ณธ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

`Instascan.Camera.getCameras().then(ํ•จ์ˆ˜(์นด๋ฉ”๋ผ) {
if(์นด๋ฉ”๋ผ[0].name.match(/back/i)){
Scanner.start(์นด๋ฉ”๋ผ[0]);
} else if(์นด๋ฉ”๋ผ[1].name.match(/back/i)){
Scanner.start(์นด๋ฉ”๋ผ[1]);
}
}

์ด๊ฒƒ์€ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: cameras[i].name ์—์„œ "๋’ค๋กœ"๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด for ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€๋งŒ cameras[i].name ๋ฅผ console.log ์“ธ ๋•Œ๊นŒ์ง€ iPad์—์„œ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์—†์—ˆ๊ณ  ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ iOS์—์„œ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๋Š” ๋ฐ ์‹คํŒจํ•˜๋ฉด "back"์„ ๋ฒˆ์—ญํ•˜๊ฑฐ๋‚˜ cameras[i].name ๋ฅผ console.log ๋กœ ์ž‘์„ฑํ•˜์—ฌ ํ›„๋ฉด ์นด๋ฉ”๋ผ์˜ ์ด๋ฆ„์ด ๋ฌด์—‡์ธ์ง€ ์•Œ์•„๋ณด์„ธ์š”.

๋ฐ๋ชจ๊ฐ€ ์ „๋ฉด ์นด๋ฉ”๋ผ์—์„œ๋งŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ iOS 12.2์˜ Safari์™€ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

iOS 12+์—์„œ Safari์™€ ํ•จ๊ป˜ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‚ธ ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

iOS 12+์—์„œ Safari์™€ ํ•จ๊ป˜ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‚ธ ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ €๋Š” ์•ฝ 7๊ฐœ์›” ๋™์•ˆ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ˆ˜์ •๋œ ๋ฒ„์ „์„ 30๊ฐœ ์ด์ƒ์˜ ์œ ํ˜•์˜ ios ๋ฐ Android ํœด๋Œ€ํฐ ๋ฐ ํƒœ๋ธ”๋ฆฟ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ž‘์—… ์ค‘์ธ OS์—์„œ ์นด๋ฉ”๋ผ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์ˆ˜์ •๋œ ๋ฒ„์ „์— ๋Œ€ํ•ด ์œ„์— ๋‚จ๊ธด ๋Œ“๊ธ€์„ ํ™•์ธํ•˜์„ธ์š”. ๋Œ“๊ธ€์€ ์ดํ›„์— webrtc๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ๊ณ„์† ์ด์•ผ๊ธฐํ•˜๋Š”๋ฐ, ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ „์ฒด ๋ฌธ์ œ์ธ ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ์—์„œ webrtc๋ฅผ ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜๊ณ  ๋‹ค์‹œ ์ปดํŒŒ์ผํ–ˆ์Šต๋‹ˆ๋‹ค. webrtc๋Š” es5 ์ด์ƒ์œผ๋กœ ํŠธ๋žœ์ŠคํŒŒ์ผ๋  ๋•Œ ์ด ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ webrtc๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ฝ”๋”ฉ ๋ฐฉ์‹์œผ๋กœ ์ธํ•ด ์˜ฌ๋ฐ”๋ฅธ ์นด๋ฉ”๋ผ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•œ๋™์•ˆ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๊ณ ์ • ๋ฐ ํŠธ๋žœ์ŠคํŒŒ์ผ๋œ ์ผ๋ฐ˜ ๋ฐ ์ถ•์†Œ๋œ js ํŒŒ์ผ์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ํ•™์ƒ๊ณผ ๊ต์‚ฌ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ชจ๋“  ์ „ํ™”๊ธฐ์—์„œ QrCode๋กœ ํ•™๊ต ์ถœ์„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ์ „ํ™”๊ธฐ๋Š” ํ˜„์žฌ ์•ฝ 30๊ฐœ ์ด์ƒ์˜ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์นด๋ฉ”๋ผ๋ฅผ ์žก์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒŒ ๋„์›€์ด ๋˜๊ธธ ๋ฐ”๋ž€๋‹ค.

ํ›„๋ฉด ์นด๋ฉ”๋ผ ์ฝ”๋“œ
```
์Šค์บ๋„ˆ = ์ƒˆ๋กœ์šด Instascan.Scanner({ ๋น„๋””์˜ค: ๋น„๋””์˜ค, scanPeriod: 4, ๋ฏธ๋Ÿฌ: false })
.then(handleSuccess)
.catch(ํ•ธ๋“ค์˜ค๋ฅ˜);
//์Šค์บ” ์‹œ์ž‘
Scanner.addListener('scan', foundCode);

            Instascan.Camera.getCameras().then(function (cameras) {
                if (cameras.length > 0) {
                    scanner.start(cameras[0]);
                }
                else {
           ...        
                }
            }).catch (function (e) {
             ...  
            });

```
instascan.min.zip

https://github.com/schmich/instascan/issues/182#issuecomment -443388022

์ด๊ฒƒ์€ ํ›Œ๋ฅญํ•œ ์ œํ’ˆ์ด๊ณ  ์ •๋ง ์œ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋ฉ‹์ง€๊ฒŒ ๋งŒ๋“ค์–ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ์—ฐ๊ตฌ์—์„œ์ด instascan์˜ ๋ฌธ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • getCameras๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ Camera ํด๋ž˜์Šค๋Š” navigator.mediaDevices.enumerateDevices() ํ˜ธ์ถœ์„ ํ†ตํ•ด ์ˆ˜์ง‘๋œ MediaDeviceInfo ๊ฐ์ฒด์—์„œ ์ƒ์„ฑ๋œ Camera ๊ฐ์ฒด ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์Šค์บ๋„ˆ๋ฅผ ์‹œ์ž‘ํ•  ๋•Œ ์‚ฌ์šฉ๋œ ์นด๋ฉ”๋ผ์˜ ์‹ค์ œ ์ŠคํŠธ๋ฆผ์„ ํฌํ•จํ•˜๋Š” MediaStream ๊ฐœ์ฒด๊ฐ€ id _ ๋ฐ _ name _ ์†์„ฑ๋งŒ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. Camera ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์„ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

_scanner.start(camera)_๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์นด๋ฉ”๋ผ ์—์„œ _camera.start()_ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š”

  • ์˜ MediaStream์˜ Arrary๋ฅผ ๋ฐ˜ํ™˜ _camera.start () _ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ _navigator.mediaDevices.getUserMedia (์ œ์•ฝ ์กฐ๊ฑด)๋ฅผ ํ˜ธ์ถœ _๋Š” ๋ฐฉ๋ฒ•์— ๋‚˜์—ด๋œ ์ฃผ์–ด์ง„ ์ œ์•ฝ ์กฐ๊ฑด์— ๋”ฐ๋ผ ๊ฐ์ฒด.
  • _scanner.start()_๋Š” _scanner._enableScan(camera)_์„ ํ˜ธ์ถœํ•˜์—ฌ ์นด๋ฉ”๋ผ์—์„œ ์œ„์˜ ํ˜ธ์ถœ์—์„œ ๋ฐ˜ํ™˜๋œ ์ฒซ ๋ฒˆ์งธ MediaStream ๊ฐœ์ฒด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. src ์š”์†Œ๋ฅผ ์ด ๋ฏธ๋””์–ด ์ŠคํŠธ๋ฆผ ๊ฐœ์ฒด๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    **This Part Is the Disconnect and what is messing it all up!**

์ œ์•ฝ ๋ฌธ์ œ:

์ „๋‹ฌ๋œ Camera ๊ฐœ์ฒด๋Š” ์ œ์•ฝ ์กฐ๊ฑด์—์„œ ํ•ด๋‹น ID ๋ฅผ ์žฅ์น˜ ๊ฒ€์ƒ‰์— _"ํ•„์ˆ˜"_๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ฐพ์„ ์ˆ˜ ์—†์œผ๋ฉด ๋น„๋””์˜ค๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋‹ค๋ฅธ "ํ•„์ˆ˜" ์ œ์•ฝ ์กฐ๊ฑด์ด ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์žฅ์น˜๋Š” ์‚ฌ์šฉ๋œ ์ œ์•ฝ ์กฐ๊ฑด์„ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค!
์‚ฌ์šฉํ•˜๋ ค๋Š” ์žฅ์น˜์—์„œ ์ด ๋งํฌ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์ง€์›ํ•˜๋Š” ์ œ์•ฝ ์กฐ๊ฑด์ด ๋ฌด์—‡์ธ์ง€ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints

์‚ฌ์šฉํ•˜๋ ค๋Š” ์žฅ์น˜์—์„œ ์ด ๋งํฌ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์ œ์•ฝ ์กฐ๊ฑด์„ ์ž…๋ ฅํ•˜์‹ญ์‹œ์˜ค. ์ง€์› ์—ฌ๋ถ€๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackSupportedConstraints/deviceId

Ipad/Iphone/IOS ์ง€์› ์ œ์•ฝ:

aspectRatio, facesMode, _deviceId * _ , ๋†’์ด, ๋„ˆ๋น„, aspectRatio ๋“ฑ.

_๋‚ด๊ฐ€ ์ด๊ฒƒ์„ ํ…Œ์ŠคํŠธํ•  ๋•Œ _deviceId๋Š” ์ œ์•ฝ ์กฐ๊ฑด์œผ๋กœ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค._ ์ œ์•ฝ ์กฐ๊ฑด ์— ๋Œ€ํ•ด ์œ„์˜ ๋งํฌ์—์„œ ์ด๊ฒƒ์„ ์‹œ๋„ํ•˜๋ฉด deviceId = ""๋กœ ์„ค์ •๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž๋ฐ” ์Šคํฌ๋ฆฝํŠธ์—์„œ ์žก์•„์„œ ํ‘œ์‹œํ–ˆ์„ ๋•Œ iphone์€ ํ•ญ์ƒ ๋นˆ deviceId๋ฅผ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ Iphone์—์„œ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์žก์œผ๋ ค๋ฉด deviceId๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  faceMode๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Android ์ง€์› ์ œ์•ฝ:

deviceId, _facingMode * _, aspectRatio, ๋†’์ด, ๋„ˆ๋น„ ๋“ฑ.

๋‚˜๋Š” ์ด๊ฒƒ์„ ์‚ผ์„ฑ ํƒœ๋ธ”๋ฆฟ๊ณผ ์•ˆ๋“œ๋กœ์ด๋“œ ํฐ์—์„œ ํ…Œ์ŠคํŠธํ–ˆ๋‹ค. faceMode์˜ ๊ธฐ๋ณธ๊ฐ’์€ "์‚ฌ์šฉ์ž" ์ „๋ฉด ์นด๋ฉ”๋ผ์ž…๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋ฅผ ์‹คํ—˜ํ•œ ๊ฒฐ๊ณผ ์•„์ง๊นŒ์ง€ ๋ฐœ๊ฒฌํ•œ ์–ด๋–ค ์ด์œ ๋กœ Android์šฉ facesMode๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์œ„์˜ ๋งํฌ์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ ๋ถ€๋ถ„์„ ๊ณ„์† ์กฐ์‚ฌํ•  ๊ฒƒ์ด๊ณ  ์•„๋งˆ๋„ ์ด ์ฝ”๋“œ๊ฐ€ facesMode ๋ฐ android์—์„œ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋„๋ก ์ˆ˜์ •ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

* _ * Android ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋‹ต๋ณ€ * _ **
์ด ํ”„๋กœ์ ํŠธ์˜ Gulp ๋นŒ๋“œ์—๋Š” Android Chrome์—์„œ facesMode๋ฅผ ์—‰๋ง์œผ๋กœ ๋งŒ๋“œ๋Š” webrtc-adapter ๋ฒ„์ „ ^1.4.0์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ์‹ค์ œ๋กœ ์ง๋ฉด ๋ชจ๋“œ๋ฅผ ์‚ญ์ œํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ์ด ํ”„๋กœ์ ํŠธ์—์„œ ์ˆ˜์ •ํ•˜๋ ค๋ฉด - _index.js_์—์„œ 2ํ–‰ require('webrtc-adapter'); ์ œ๊ฑฐํ•œ ๋‹ค์Œ ์•„๋ž˜ ๋นŒ๋“œ ์ ˆ์ฐจ๋ฅผ ๋”ฐ๋ฅด์„ธ์š”. Chrome์—์„œ ํƒœ๋ธ”๋ฆฟ๊ณผ 4๊ฐœ์˜ ๋‹ค๋ฅธ Android ํœด๋Œ€์ „ํ™”์—์„œ ํ…Œ์ŠคํŠธํ–ˆ์„ ๋•Œ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์žก๊ธฐ ์œ„ํ•ด ๋ชจ๋‘ ๋‹ค์‹œ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด instascan ์ฝ”๋“œ๋กœ Android์˜ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์žก์œผ๋ ค๋ฉด deviceId๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
deviceId๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ _video_ ์ œ์•ฝ ์กฐ๊ฑด์ธ์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.

video: {
  devideId: this.id
}

์นด๋ฉ”๋ผ ์ œ์•ฝ ์ฝ”๋“œ:

๋‹ค์Œ์€ ์ œ์•ฝ ์กฐ๊ฑด์„ ์„ค์ •ํ•˜๊ณ  MediaStream ๊ฐœ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํ”„๋กœ์ ํŠธ์˜ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.
์ด ์ฝ”๋“œ๊ฐ€ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” _video ์ œ์•ฝ ์กฐ๊ฑด _ ์˜ sourceId๊ฐ€ _Android_ ๋˜๋Š” _Iphone_์—์„œ ์ง€์›๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ deviceId ๋กœ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค . ๋˜ํ•œ ๋ชจ๋“  ํ•„์ˆ˜ ํ•ญ๋ชฉ์€ ์žฅ์น˜๊ฐ€ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์ด๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

async start() {
    let constraints;
    var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

    if (iOS) {
      constraints = {
        audio: false,
        video: {
          facingMode: 'environment',
          mandatory: {
            sourceId: this.id,
            minWidth: 600,
            maxWidth: 800,
            minAspectRatio: 1.6
          },
          optional: []
        }
      };
    } else {
      constraints = {
        audio: false,
        video: {
          mandatory: {
            sourceId: this.id,
            minWidth: 600,
            maxWidth: 800,
            minAspectRatio: 1.6
          },
          optional: []
        }
      };
    }

    this._stream = await Camera._wrapErrors(async () => {
      return await navigator.mediaDevices.getUserMedia(constraints);
});

InstaScan์„ ์ˆ˜์ •ํ•˜๊ณ  ์ถ•์†Œํ•˜๋Š” ๋ฐฉ๋ฒ•:

์ด๊ฒƒ์„ ์–ป๊ณ  ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด VSCode๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

  1. Node.js ๋ฐ vsCode๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
  2. ๋‹ค์šด๋กœ๋“œํ•˜๋ ค๋Š” ๋””๋ ‰ํ† ๋ฆฌ์˜ ํ„ฐ๋ฏธ๋„์—์„œ ๋‹ค์Œ์„ ์‹คํ–‰ํ•˜์‹ญ์‹œ์˜ค.
    git clone https://github.com/JoseCDB/instascan.git
  3. ํ„ฐ๋ฏธ๋„ cd์—์„œ instascan ๋””๋ ‰ํ† ๋ฆฌ๋กœ:
    cd instascan
  4. ์ž๋ฐ” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  gulp๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ํ•ด์ œํ•˜์‹ญ์‹œ์˜ค.
    gulp release
  5. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด _dist_ ํด๋”์— ์ถ•์†Œ๋œ ์ƒˆ instascan.min.js ํ•ญ๋ชฉ์ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

์ด๋ฒˆ ์ฃผ๋ง์— ์ด Android ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๋ฉ‹์ง„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ํ–ฅํ›„ ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ ์ถฉ๋ถ„ํ•œ ํ†ต์ฐฐ๋ ฅ์„ ์–ป์„ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์œ„์˜ ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•œ ๋‹ค์Œ ํŒŒ์ผ camera.js (29ํ–‰)๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ํŽธ์ง‘ํ•ฉ๋‹ˆ๋‹ค.
facingMode: { exact: "environment" },
๊ทธ๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. @apchandler ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

๋‹น์‹ ์„ ์œ„ํ•ด ์ผํ•  ์ผ์ด ์ƒ๊ฒจ์„œ ๊ธฐ์ฉ๋‹ˆ๋‹ค! ์ด ์ˆ˜์ • ์‚ฌํ•ญ์„ ๊ฒŒ์‹œํ•ด ์ฃผ์‹  @glorynguyen์—๊ฒŒ๋„ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

๋ถˆํ–‰ํžˆ๋„ ์ด๋Ÿฌํ•œ ์†”๋ฃจ์…˜์€ iOS 13์—์„œ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹จ์ˆœํžˆ ๋น„์–ด ์žˆ์Šต๋‹ˆ๋‹ค(๊ฒ€์€์ƒ‰๋„ ์•„๋‹˜).
Safari๋ฅผ ์›๊ฒฉ ๋””๋ฒ„๊น…ํ•  ๋•Œ๋„ ์ฝ˜์†”์— ์˜ค๋ฅ˜๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

iOS 12+์—์„œ Safari์™€ ํ•จ๊ป˜ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‚ธ ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ €๋Š” ์•ฝ 7๊ฐœ์›” ๋™์•ˆ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ˆ˜์ •๋œ ๋ฒ„์ „์„ 30๊ฐœ ์ด์ƒ์˜ ์œ ํ˜•์˜ ios ๋ฐ Android ํœด๋Œ€ํฐ ๋ฐ ํƒœ๋ธ”๋ฆฟ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ž‘์—… ์ค‘์ธ OS์—์„œ ์นด๋ฉ”๋ผ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์ˆ˜์ •๋œ ๋ฒ„์ „์— ๋Œ€ํ•ด ์œ„์— ๋‚จ๊ธด ๋Œ“๊ธ€์„ ํ™•์ธํ•˜์„ธ์š”. ๋Œ“๊ธ€์€ ์ดํ›„์— webrtc๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ๊ณ„์† ์ด์•ผ๊ธฐํ•˜๋Š”๋ฐ, ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ „์ฒด ๋ฌธ์ œ์ธ ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ์—์„œ webrtc๋ฅผ ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜๊ณ  ๋‹ค์‹œ ์ปดํŒŒ์ผํ–ˆ์Šต๋‹ˆ๋‹ค. webrtc๋Š” es5 ์ด์ƒ์œผ๋กœ ํŠธ๋žœ์ŠคํŒŒ์ผ๋  ๋•Œ ์ด ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ webrtc๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ฝ”๋”ฉ ๋ฐฉ์‹์œผ๋กœ ์ธํ•ด ์˜ฌ๋ฐ”๋ฅธ ์นด๋ฉ”๋ผ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•œ๋™์•ˆ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๊ณ ์ • ๋ฐ ํŠธ๋žœ์ŠคํŒŒ์ผ๋œ ์ผ๋ฐ˜ ๋ฐ ์ถ•์†Œ๋œ js ํŒŒ์ผ์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ํ•™์ƒ๊ณผ ๊ต์‚ฌ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ชจ๋“  ์ „ํ™”๊ธฐ์—์„œ QrCode๋กœ ํ•™๊ต ์ถœ์„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ์ „ํ™”๊ธฐ๋Š” ํ˜„์žฌ ์•ฝ 30๊ฐœ ์ด์ƒ์˜ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์นด๋ฉ”๋ผ๋ฅผ ์žก์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒŒ ๋„์›€์ด ๋˜๊ธธ ๋ฐ”๋ž€๋‹ค.

ํ›„๋ฉด ์นด๋ฉ”๋ผ ์ฝ”๋“œ

scanner = new Instascan.Scanner({ video: video, scanPeriod: 4, mirror:false })
                .then(handleSuccess)
                .catch(handleError);
             //Start scanning
             scanner.addListener('scan', foundCode);

             Instascan.Camera.getCameras().then(function (cameras) {
                 if (cameras.length > 0) {
                     scanner.start(cameras[0]);
                 }
                 else {
            ...        
                 }
             }).catch (function (e) {
              ...  
             });

instascan.min.zip

#182(๋Œ“๊ธ€)

์ด๊ฒƒ์€ ๋‚ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์ด์— ๋Œ€ํ•œ ์ตœ์‹  ์ˆ˜์ • ์‚ฌํ•ญ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์Šค๋ ˆ๋“œ์—์„œ ๋ช‡ ๊ฐ€์ง€๋ฅผ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์ „๋ฉด ์นด๋ฉ”๋ผ๋งŒ ์–ป๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
Gulp๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์‹ค์ œ๋กœ .js .git ํ”„๋กœ์ ํŠธ๋ฅผ ์ปดํŒŒ์ผํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค. ์ €๋Š” ์ฃผ๋กœ C#/Asp.net Mvc๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฏ€๋กœ ์ด๊ฒƒ์€ ์ €์—๊ฒŒ ์•ฝ๊ฐ„ ์ƒˆ๋กญ์Šต๋‹ˆ๋‹ค.
apchandler์˜ ์†”๋ฃจ์…˜์€ ๋‚˜์—๊ฒŒ ์˜ค๋ฅ˜๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. (๋™์˜์ƒ์ด ์ •์˜๋˜์ง€ ์•Š์Œ)
ํ˜„์žฌ Android ๊ธฐ๊ธฐ์šฉ "๊ณ ์ •" instascan.min.js์™€ IOS์šฉ ๋ฒ„์ „์„ ๋กœ๋“œํ•˜๊ณ  ์žˆ์ง€๋งŒ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ด์— ๋Œ€ํ•œ ์ตœ์‹  ์ˆ˜์ • ์‚ฌํ•ญ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์Šค๋ ˆ๋“œ์—์„œ ๋ช‡ ๊ฐ€์ง€๋ฅผ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์ „๋ฉด ์นด๋ฉ”๋ผ๋งŒ ์–ป๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
Gulp๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์‹ค์ œ๋กœ .js .git ํ”„๋กœ์ ํŠธ๋ฅผ ์ปดํŒŒ์ผํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค. ์ €๋Š” ์ฃผ๋กœ C#/Asp.net Mvc๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฏ€๋กœ ์ด๊ฒƒ์€ ์ €์—๊ฒŒ ์•ฝ๊ฐ„ ์ƒˆ๋กญ์Šต๋‹ˆ๋‹ค.
apchandler์˜ ์†”๋ฃจ์…˜์€ ๋‚˜์—๊ฒŒ ์˜ค๋ฅ˜๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. (๋™์˜์ƒ์ด ์ •์˜๋˜์ง€ ์•Š์Œ)
ํ˜„์žฌ Android ๊ธฐ๊ธฐ์šฉ "๊ณ ์ •" instascan.min.js์™€ IOS์šฉ ๋ฒ„์ „์„ ๋กœ๋“œํ•˜๊ณ  ์žˆ์ง€๋งŒ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

html ๋น„๋””์˜ค ์š”์†Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?
```

When you run instascan you need to speficy a video element like:

var ์ž๊ธฐ = ์ด๊ฒƒ;
self.scanner = new Instascan.Scanner({ ๋น„๋””์˜ค: document.getElementById('๋ฏธ๋ฆฌ๋ณด๊ธฐ'), scanPeriod: 5 });
self.scanner.addListener('์Šค์บ”', ํ•จ์ˆ˜(๋‚ด์šฉ, ์ด๋ฏธ์ง€) {
self.scans.unshift({ ๋‚ ์งœ: +(๋‚ ์งœ.now()), ๋‚ด์šฉ: ๋‚ด์šฉ });
});
Instascan.Camera.getCameras().then(ํ•จ์ˆ˜(์นด๋ฉ”๋ผ) {
self.cameras = ์นด๋ฉ”๋ผ;
if (์นด๋ฉ”๋ผ ๊ธธ์ด > 0) {
self.activeCameraId = ์นด๋ฉ”๋ผ[0].id;
self.scanner.start(์นด๋ฉ”๋ผ[0]);
} ๋˜ ๋‹ค๋ฅธ {
console.error('์นด๋ฉ”๋ผ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
}
}).catch(ํ•จ์ˆ˜(e) {
console.error(e);
});
```

์˜ˆ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

<video class="player" style="max-width:100%" id="preview" playsinline></video>

<script>
.....
  Instascan.Camera.getCameras().then(function (cameras) {
        if (cameras.length > 0) {
          scanner.start(cameras[0]);
        } else {
          console.error('No cameras found.');
        }
      }).catch(function (e) {
        console.error(e);
      });
</script>

Iphone/Ios ๊ธฐ๊ธฐ์šฉ ์นด๋ฉ”๋ผ[0] ์‹œ์ž‘ ์ค‘. ์•ˆ๋“œ๋กœ์ด๋“œ์šฉ:

<script>
.....
  Instascan.Camera.getCameras().then(function (cameras) {
                if (cameras.length > 0) {
                    var selectedCam = cameras[0];
                    $.each(cameras, (i, c) => {
                        if (c.name.indexOf('back') != -1) {
                            selectedCam = c;
                            return false;
                        }
                    });
                    scanner.start(selectedCam);
                }
                else {
                    console.error('No cameras found.');
                }
              });
</script>

๋ฌธ์ œ๋Š” "iphone"์ด ์•„๋‹Œ Request.UserAgent.Contains("ios")๋งŒ ํ™•์ธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— Iphone์šฉ Android ์Šคํฌ๋ฆฝํŠธ๋„ ์‹คํ–‰ํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์•Œ์•„๋‘์‹œ๋ฉด ์ข‹์Šต๋‹ˆ๋‹ค. ์ •๋ณด์— ๋Œ€ํ•ด์„œ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

@apchandler ์•ˆ๋…•ํ•˜์„ธ์š”, '๋ฉ”์ธ' ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”์ง€ ์•„์‹ญ๋‹ˆ๊นŒ?

๋‚ด ์‚ฌ์šฉ์ž๊ฐ€ instascan์„ ์‚ฌ์šฉํ•˜์—ฌ QR ์ฝ”๋“œ๋ฅผ ์Šค์บ”ํ•˜๋Š” ์›น์‚ฌ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ์›น์‚ฌ์ดํŠธ๋ฅผ ๊ฐœ๋ฐœ ์ค‘์ด๋ฉฐ 4๊ฐœ์˜ ํ›„๋ฉด ์นด๋ฉ”๋ผ(HUAWEI P30 PRO)๊ฐ€ ์žˆ๋Š” ๋ชจ๋ฐ”์ผ ์ „ํ™”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น์‚ฌ์ดํŠธ์— ์•ก์„ธ์Šคํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” $.each๋ฅผ ์‹œ๋„ํ–ˆ๊ณ  ์ฒซ ๋ฒˆ์งธ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•œ ์ƒํƒœ์—์„œ ์‹œ์•ผ๊ฐ€ ๋„ˆ๋ฌด ํ๋ฆฟํ•˜๊ณ  ๋งŽ์€ ์คŒ์œผ๋กœ ์ธํ•ด ์•„๋ฌด๊ฒƒ๋„ ์Šค์บ”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์นด๋ฉ”๋ผ[2]๋ฅผ ์„ ํƒํ•˜๋ฉด ๋ชจ๋“  ๊ฒƒ์„ ์Šค์บ”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

'๋ฉ”์ธ' ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๋‚ด ์›น ์•ฑ์€ ๋‹ค๋ฅธ ํœด๋Œ€ ์ „ํ™”, ๋‹ค๋ฅธ ์ˆ˜์˜ ์นด๋ฉ”๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋งŽ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ฉฐ ์นด๋ฉ”๋ผ์˜ ์ˆœ์„œ๋„ ๋‹ค๋ฅผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•„๋‹ˆ๋ฉด ๋ชจ๋“  ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ์ž์‹ ์—๊ฒŒ ์™„๋ฒฝํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋Š” ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๋„๋ก ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

๊ฐ์‚ฌ ํ•ด์š”

@apchandler ์•ˆ๋…•ํ•˜์„ธ์š”, '๋ฉ”์ธ' ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”์ง€ ์•„์‹ญ๋‹ˆ๊นŒ?

๋‚ด ์‚ฌ์šฉ์ž๊ฐ€ instascan์„ ์‚ฌ์šฉํ•˜์—ฌ QR ์ฝ”๋“œ๋ฅผ ์Šค์บ”ํ•˜๋Š” ์›น์‚ฌ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ์›น์‚ฌ์ดํŠธ๋ฅผ ๊ฐœ๋ฐœ ์ค‘์ด๋ฉฐ 4๊ฐœ์˜ ํ›„๋ฉด ์นด๋ฉ”๋ผ(HUAWEI P30 PRO)๊ฐ€ ์žˆ๋Š” ๋ชจ๋ฐ”์ผ ์ „ํ™”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น์‚ฌ์ดํŠธ์— ์•ก์„ธ์Šคํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” $.each๋ฅผ ์‹œ๋„ํ–ˆ๊ณ  ์ฒซ ๋ฒˆ์งธ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•œ ์ƒํƒœ์—์„œ ์‹œ์•ผ๊ฐ€ ๋„ˆ๋ฌด ํ๋ฆฟํ•˜๊ณ  ๋งŽ์€ ์คŒ์œผ๋กœ ์ธํ•ด ์•„๋ฌด๊ฒƒ๋„ ์Šค์บ”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์นด๋ฉ”๋ผ[2]๋ฅผ ์„ ํƒํ•˜๋ฉด ๋ชจ๋“  ๊ฒƒ์„ ์Šค์บ”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

'๋ฉ”์ธ' ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๋‚ด ์›น ์•ฑ์€ ๋‹ค๋ฅธ ํœด๋Œ€ ์ „ํ™”, ๋‹ค๋ฅธ ์ˆ˜์˜ ์นด๋ฉ”๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋งŽ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ฉฐ ์นด๋ฉ”๋ผ์˜ ์ˆœ์„œ๋„ ๋‹ค๋ฅผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•„๋‹ˆ๋ฉด ๋ชจ๋“  ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ์ž์‹ ์—๊ฒŒ ์™„๋ฒฝํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋Š” ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๋„๋ก ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

๊ฐ์‚ฌ ํ•ด์š”

๋ฏธ์•ˆ ํ•ด์š”. ์—ฌ๋Ÿฌ ๋Œ€๊ฐ€ ์žˆ์„ ๋•Œ '๋ฉ”์ธ' ์นด๋ฉ”๋ผ๋กœ ์ง€์ •ํ•˜๋Š” ๊ฐ’์„ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์นด๋ฉ”๋ผ ์„ ํƒ ๊ธฐ๋Šฅ์— ์ตœ์†Œํ•œ ํŠน์ • ํ•ด์ƒ๋„ ๋ฐ ๊ธฐํƒ€ ์‚ฌ์–‘์ด ์žˆ์–ด์•ผ ํ•จ์„ ์ง€์ •ํ•˜๋Š” ๊ธฐ์ค€ ๊ฐœ์ฒด๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ์˜ ๋Šฅ๋ ฅ์„ ๊ฐ–์ถ˜ ์นด๋ฉ”๋ผ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์†”๋ฃจ์…˜์ด ์ ‘๊ทผํ•˜๋ ค๋Š” ๋ฐฉ์‹์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

@apchandler ์•ˆ๋…•ํ•˜์„ธ์š”, '๋ฉ”์ธ' ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”์ง€ ์•„์‹ญ๋‹ˆ๊นŒ?
๋‚ด ์‚ฌ์šฉ์ž๊ฐ€ instascan์„ ์‚ฌ์šฉํ•˜์—ฌ QR ์ฝ”๋“œ๋ฅผ ์Šค์บ”ํ•˜๋Š” ์›น์‚ฌ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ์›น์‚ฌ์ดํŠธ๋ฅผ ๊ฐœ๋ฐœ ์ค‘์ด๋ฉฐ 4๊ฐœ์˜ ํ›„๋ฉด ์นด๋ฉ”๋ผ(HUAWEI P30 PRO)๊ฐ€ ์žˆ๋Š” ๋ชจ๋ฐ”์ผ ์ „ํ™”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น์‚ฌ์ดํŠธ์— ์•ก์„ธ์Šคํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๋‚˜๋Š” $.each๋ฅผ ์‹œ๋„ํ–ˆ๊ณ  ์ฒซ ๋ฒˆ์งธ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•œ ์ƒํƒœ์—์„œ ์‹œ์•ผ๊ฐ€ ๋„ˆ๋ฌด ํ๋ฆฟํ•˜๊ณ  ๋งŽ์€ ์คŒ์œผ๋กœ ์ธํ•ด ์•„๋ฌด๊ฒƒ๋„ ์Šค์บ”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ์นด๋ฉ”๋ผ[2]๋ฅผ ์„ ํƒํ•˜๋ฉด ๋ชจ๋“  ๊ฒƒ์„ ์Šค์บ”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
'๋ฉ”์ธ' ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?
๋‚ด ์›น ์•ฑ์€ ๋‹ค๋ฅธ ํœด๋Œ€ ์ „ํ™”, ๋‹ค๋ฅธ ์ˆ˜์˜ ์นด๋ฉ”๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋งŽ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ฉฐ ์นด๋ฉ”๋ผ์˜ ์ˆœ์„œ๋„ ๋‹ค๋ฅผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์•„๋‹ˆ๋ฉด ๋ชจ๋“  ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ์ž์‹ ์—๊ฒŒ ์™„๋ฒฝํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋Š” ์นด๋ฉ”๋ผ๋ฅผ ์„ ํƒํ•˜๋„๋ก ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?
๊ฐ์‚ฌ ํ•ด์š”

๋ฏธ์•ˆ ํ•ด์š”. ์—ฌ๋Ÿฌ ๋Œ€๊ฐ€ ์žˆ์„ ๋•Œ '๋ฉ”์ธ' ์นด๋ฉ”๋ผ๋กœ ์ง€์ •ํ•˜๋Š” ๊ฐ’์„ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์นด๋ฉ”๋ผ ์„ ํƒ ๊ธฐ๋Šฅ์— ์ตœ์†Œํ•œ ํŠน์ • ํ•ด์ƒ๋„ ๋ฐ ๊ธฐํƒ€ ์‚ฌ์–‘์ด ์žˆ์–ด์•ผ ํ•จ์„ ์ง€์ •ํ•˜๋Š” ๊ธฐ์ค€ ๊ฐœ์ฒด๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ์˜ ๋Šฅ๋ ฅ์„ ๊ฐ–์ถ˜ ์นด๋ฉ”๋ผ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์†”๋ฃจ์…˜์ด ์ ‘๊ทผํ•˜๋ ค๋Š” ๋ฐฉ์‹์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

๋‹ต๋ณ€ํ•ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ํ•ด์ƒ๋„๋กœ ๋…ธ๋ ฅํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. Instascan์€ ์นด๋ฉ”๋ผ A์˜ ํ•ด์ƒ๋„๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@glorynguyen ๋ฐ @apchandler๊ฐ€ ์ œ๊ณตํ•œ ๋ฐฉ๋ฒ•์— ๋”ฐ๋ฅด๋ฉด.
์ด์ œ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์ผค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
instascan.min ์ˆ˜์ •
์ „์—
case 0:return i={audio:!1,video:{mandatory:{sourceId:this.id,minWidth:600,maxWidth:800,minAspectRatio:1.6},optional:[]}}
ํ›„์—
case 0:return i=(/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream)?{audio:!1,video:{facingMode:{exact:"environment"},mandatory:{sourceId:this.id,minWidth:600,maxWidth:800,minAspectRatio:1.6},optional:[]}}:{audio:!1,video:{mandatory:{sourceId:this.id,minWidth:600,maxWidth:800,minAspectRatio:1.6},optional:[]}}

iOS 12+์—์„œ Safari์™€ ํ•จ๊ป˜ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‚ธ ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ €๋Š” ์•ฝ 7๊ฐœ์›” ๋™์•ˆ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ˆ˜์ •๋œ ๋ฒ„์ „์„ 30๊ฐœ ์ด์ƒ์˜ ์œ ํ˜•์˜ ios ๋ฐ Android ํœด๋Œ€ํฐ ๋ฐ ํƒœ๋ธ”๋ฆฟ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ž‘์—… ์ค‘์ธ OS์—์„œ ์นด๋ฉ”๋ผ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์ˆ˜์ •๋œ ๋ฒ„์ „์— ๋Œ€ํ•ด ์œ„์— ๋‚จ๊ธด ๋Œ“๊ธ€์„ ํ™•์ธํ•˜์„ธ์š”. ๋Œ“๊ธ€์€ ์ดํ›„์— webrtc๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ๊ณ„์† ์ด์•ผ๊ธฐํ•˜๋Š”๋ฐ, ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ „์ฒด ๋ฌธ์ œ์ธ ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ์—์„œ webrtc๋ฅผ ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜๊ณ  ๋‹ค์‹œ ์ปดํŒŒ์ผํ–ˆ์Šต๋‹ˆ๋‹ค. webrtc๋Š” es5 ์ด์ƒ์œผ๋กœ ํŠธ๋žœ์ŠคํŒŒ์ผ๋  ๋•Œ ์ด ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ webrtc๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ฝ”๋”ฉ ๋ฐฉ์‹์œผ๋กœ ์ธํ•ด ์˜ฌ๋ฐ”๋ฅธ ์นด๋ฉ”๋ผ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•œ๋™์•ˆ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๊ณ ์ • ๋ฐ ํŠธ๋žœ์ŠคํŒŒ์ผ๋œ ์ผ๋ฐ˜ ๋ฐ ์ถ•์†Œ๋œ js ํŒŒ์ผ์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ํ•™์ƒ๊ณผ ๊ต์‚ฌ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ชจ๋“  ์ „ํ™”๊ธฐ์—์„œ QrCode๋กœ ํ•™๊ต ์ถœ์„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ์ „ํ™”๊ธฐ๋Š” ํ˜„์žฌ ์•ฝ 30๊ฐœ ์ด์ƒ์˜ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์นด๋ฉ”๋ผ๋ฅผ ์žก์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒŒ ๋„์›€์ด ๋˜๊ธธ ๋ฐ”๋ž€๋‹ค.

ํ›„๋ฉด ์นด๋ฉ”๋ผ ์ฝ”๋“œ

scanner = new Instascan.Scanner({ video: video, scanPeriod: 4, mirror:false })
                .then(handleSuccess)
                .catch(handleError);
             //Start scanning
             scanner.addListener('scan', foundCode);

             Instascan.Camera.getCameras().then(function (cameras) {
                 if (cameras.length > 0) {
                     scanner.start(cameras[0]);
                 }
                 else {
            ...        
                 }
             }).catch (function (e) {
              ...  
             });

instascan.min.zip

#182(๋Œ“๊ธ€)

๋‹น์‹ ์€ ๋ฐฉ๊ธˆ ์ฃผ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž์˜ ์ง์—…์„ ๊ตฌํ–ˆ๊ณ  ํ‰์ƒ ํŒฌ์ด๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๊ฐ์‚ฌ ํ•ด์š”. ์ด ์ฝ”๋“œ๋ฅผ ๋ดค์„ ๋•Œ ๋‹น์‹ ์ด ์žˆ๋˜ ๋ฐ”๋กœ ๊ทธ ์ž๋ฆฌ์— ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ธฐํ•œ์ด ์žˆ์—ˆ๊ณ  30๊ฐ€์ง€ ์œ ํ˜•์˜ ์นด๋ฉ”๋ผ๊ฐ€ ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๋“ค์ด ์ด๊ฒƒ์„ ์ผ๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ 15๊ฐœ์›” ๋™์•ˆ 45๊ฐ€์ง€ ๋‹ค๋ฅธ ๋ชจ๋ธ์˜ ํœด๋Œ€ํฐ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ์‚ผ์„ฑ์ด ํŒจ์น˜ํ–ˆ์„ ๋•Œ ์ˆ˜์ •๋œ ์‚ผ์„ฑ ํœด๋Œ€ํฐ์—์„œ ๋‹จ ํ•œ ๋ฒˆ์˜ ๋”ธ๊พน์งˆ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์‚ผ์„ฑ WebKit ์˜ค๋ฅ˜์˜€์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š”,
๋‚˜๋Š” ๋˜ํ•œ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ IOS์—์„œ ํ›„๋ฉด ์นด๋ฉ”๋ผ ๋ฌธ์ œ์— ์ง๋ฉดํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. iPhone์—์„œ ํ›„๋ฉด ์นด๋ฉ”๋ผ๊ฐ€ ์—ด๋ฆฌ์ง€ ์•Š๊ณ  ๊ธฐ๋ณธ ์ „๋ฉด ์นด๋ฉ”๋ผ๊ฐ€ ์‹คํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค. ์‚ฌํŒŒ๋ฆฌ ์—…๋ฐ์ดํŠธ ๋ฒ„์ „(13.xx.xx)์œผ๋กœ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์‹  ๋ถ„์ด ๊ณ„์‹œ๋ฉด ๋„์™€์ฃผ์„ธ์š”.

iOS 12+์—์„œ Safari์™€ ํ•จ๊ป˜ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‚ธ ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ €๋Š” ์•ฝ 7๊ฐœ์›” ๋™์•ˆ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ˆ˜์ •๋œ ๋ฒ„์ „์„ 30๊ฐœ ์ด์ƒ์˜ ์œ ํ˜•์˜ ios ๋ฐ Android ํœด๋Œ€ํฐ ๋ฐ ํƒœ๋ธ”๋ฆฟ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ž‘์—… ์ค‘์ธ OS์—์„œ ์นด๋ฉ”๋ผ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์ˆ˜์ •๋œ ๋ฒ„์ „์— ๋Œ€ํ•ด ์œ„์— ๋‚จ๊ธด ๋Œ“๊ธ€์„ ํ™•์ธํ•˜์„ธ์š”. ๋Œ“๊ธ€์€ ์ดํ›„์— webrtc๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ๊ณ„์† ์ด์•ผ๊ธฐํ•˜๋Š”๋ฐ, ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ „์ฒด ๋ฌธ์ œ์ธ ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ์—์„œ webrtc๋ฅผ ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜๊ณ  ๋‹ค์‹œ ์ปดํŒŒ์ผํ–ˆ์Šต๋‹ˆ๋‹ค. webrtc๋Š” es5 ์ด์ƒ์œผ๋กœ ํŠธ๋žœ์ŠคํŒŒ์ผ๋  ๋•Œ ์ด ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ webrtc๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ฝ”๋”ฉ ๋ฐฉ์‹์œผ๋กœ ์ธํ•ด ์˜ฌ๋ฐ”๋ฅธ ์นด๋ฉ”๋ผ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•œ๋™์•ˆ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๊ณ ์ • ๋ฐ ํŠธ๋žœ์ŠคํŒŒ์ผ๋œ ์ผ๋ฐ˜ ๋ฐ ์ถ•์†Œ๋œ js ํŒŒ์ผ์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ํ•™์ƒ๊ณผ ๊ต์‚ฌ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ชจ๋“  ์ „ํ™”๊ธฐ์—์„œ QrCode๋กœ ํ•™๊ต ์ถœ์„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ์ „ํ™”๊ธฐ๋Š” ํ˜„์žฌ ์•ฝ 30๊ฐœ ์ด์ƒ์˜ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์นด๋ฉ”๋ผ๋ฅผ ์žก์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒŒ ๋„์›€์ด ๋˜๊ธธ ๋ฐ”๋ž€๋‹ค.

ํ›„๋ฉด ์นด๋ฉ”๋ผ ์ฝ”๋“œ

scanner = new Instascan.Scanner({ video: video, scanPeriod: 4, mirror:false })
                .then(handleSuccess)
                .catch(handleError);
             //Start scanning
             scanner.addListener('scan', foundCode);

             Instascan.Camera.getCameras().then(function (cameras) {
                 if (cameras.length > 0) {
                     scanner.start(cameras[0]);
                 }
                 else {
            ...        
                 }
             }).catch (function (e) {
              ...  
             });

instascan.min.zip

#182(๋Œ“๊ธ€)

Android์™€ iOS ๋ชจ๋‘์—์„œ ๋งค๋ ฅ์ฒ˜๋Ÿผ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค! ๋ฐฉ๊ธˆ ์›๋ณธ instascan ๋งˆ์Šคํ„ฐ ๋ธŒ๋žœ์น˜๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ํŒŒ์ผ์„ "dist" ํด๋”์— ๋„ฃ์œผ๋ฉด ๋์ž…๋‹ˆ๋‹ค! ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค !

Android์™€ iOS ๋ชจ๋‘์—์„œ ๋งค๋ ฅ์ฒ˜๋Ÿผ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค! ๋ฐฉ๊ธˆ ์›๋ณธ instascan ๋งˆ์Šคํ„ฐ ๋ธŒ๋žœ์น˜๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ํŒŒ์ผ์„ "dist" ํด๋”์— ๋„ฃ์œผ๋ฉด ๋์ž…๋‹ˆ๋‹ค! ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค !

@antworks-hub ๋ธŒ๋žœ์น˜์˜ ์ „์ฒด ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์…จ๋‚˜์š” ์•„๋‹ˆ๋ฉด ์ถ•์†Œ๋œ js๋ฅผ ์‚ฌ์šฉํ•˜์…จ๋‚˜์š”?
"dist" ํด๋”๋Š” ์–ด๋””์„œ ๊ตฌํ•˜์…จ๋‚˜์š”?

Android์™€ iOS ๋ชจ๋‘์—์„œ ๋งค๋ ฅ์ฒ˜๋Ÿผ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค! ๋ฐฉ๊ธˆ ์›๋ณธ instascan ๋งˆ์Šคํ„ฐ ๋ธŒ๋žœ์น˜๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ํŒŒ์ผ์„ "dist" ํด๋”์— ๋„ฃ์œผ๋ฉด ๋์ž…๋‹ˆ๋‹ค! ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค !

@antworks-hub ๋ธŒ๋žœ์น˜์˜ ์ „์ฒด ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์…จ๋‚˜์š” ์•„๋‹ˆ๋ฉด ์ถ•์†Œ๋œ js๋ฅผ ์‚ฌ์šฉํ•˜์…จ๋‚˜์š”?
"dist" ํด๋”๋Š” ์–ด๋””์„œ ๊ตฌํ•˜์…จ๋‚˜์š”?

@Sandi2211 ์›๋ž˜ instascan ๋งˆ์Šคํ„ฐ ๋ธŒ๋žœ์น˜์˜ ๋ฃจํŠธ์— "dist" ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ  ๊ทธ ํด๋”์— instasca,min.zip ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ๋„ฃ์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

iOS 12+์—์„œ Safari์™€ ํ•จ๊ป˜ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‚ธ ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ €๋Š” ์•ฝ 7๊ฐœ์›” ๋™์•ˆ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ˆ˜์ •๋œ ๋ฒ„์ „์„ 30๊ฐœ ์ด์ƒ์˜ ์œ ํ˜•์˜ ios ๋ฐ Android ํœด๋Œ€ํฐ ๋ฐ ํƒœ๋ธ”๋ฆฟ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ž‘์—… ์ค‘์ธ OS์—์„œ ์นด๋ฉ”๋ผ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์ˆ˜์ •๋œ ๋ฒ„์ „์— ๋Œ€ํ•ด ์œ„์— ๋‚จ๊ธด ๋Œ“๊ธ€์„ ํ™•์ธํ•˜์„ธ์š”. ๋Œ“๊ธ€์€ ์ดํ›„์— webrtc๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ๊ณ„์† ์ด์•ผ๊ธฐํ•˜๋Š”๋ฐ, ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ „์ฒด ๋ฌธ์ œ์ธ ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค.
ํ”„๋กœ์ ํŠธ์—์„œ webrtc๋ฅผ ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜๊ณ  ๋‹ค์‹œ ์ปดํŒŒ์ผํ–ˆ์Šต๋‹ˆ๋‹ค. webrtc๋Š” es5 ์ด์ƒ์œผ๋กœ ํŠธ๋žœ์ŠคํŒŒ์ผ๋  ๋•Œ ์ด ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ webrtc๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ฝ”๋”ฉ ๋ฐฉ์‹์œผ๋กœ ์ธํ•ด ์˜ฌ๋ฐ”๋ฅธ ์นด๋ฉ”๋ผ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.
ํ•œ๋™์•ˆ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๊ณ ์ • ๋ฐ ํŠธ๋žœ์ŠคํŒŒ์ผ๋œ ์ผ๋ฐ˜ ๋ฐ ์ถ•์†Œ๋œ js ํŒŒ์ผ์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ํ•™์ƒ๊ณผ ๊ต์‚ฌ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ชจ๋“  ์ „ํ™”๊ธฐ์—์„œ QrCode๋กœ ํ•™๊ต ์ถœ์„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ์ „ํ™”๊ธฐ๋Š” ํ˜„์žฌ ์•ฝ 30๊ฐœ ์ด์ƒ์˜ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์นด๋ฉ”๋ผ๋ฅผ ์žก์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๊ฒŒ ๋„์›€์ด ๋˜๊ธธ ๋ฐ”๋ž€๋‹ค.
ํ›„๋ฉด ์นด๋ฉ”๋ผ ์ฝ”๋“œ

scanner = new Instascan.Scanner({ video: video, scanPeriod: 4, mirror:false })
                .then(handleSuccess)
                .catch(handleError);
             //Start scanning
             scanner.addListener('scan', foundCode);

             Instascan.Camera.getCameras().then(function (cameras) {
                 if (cameras.length > 0) {
                     scanner.start(cameras[0]);
                 }
                 else {
            ...        
                 }
             }).catch (function (e) {
              ...  
             });

instascan.min.zip
#182(๋Œ“๊ธ€)

์ด๊ฒƒ์€ ๋‚ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ œ ์ž‘์—…์ด ์ž˜ ๋ฉ๋‹ˆ๋‹ค. ์ƒˆ js๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๊ดœ์ฐฎ์•„์š”. ์ด ๋ชจ๋“  ๊ฒƒ์ด ์—ฌ์ „ํžˆ ์—ฌ๊ธฐ์—์„œ ์ž‘๋™ํ•˜๊ณ  ์žˆ์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค.

iOS 12+์—์„œ Safari์™€ ํ•จ๊ป˜ ํ›„๋ฉด ์นด๋ฉ”๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‚ธ ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ €๋Š” ์•ฝ 7๊ฐœ์›” ๋™์•ˆ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ˆ˜์ •๋œ ๋ฒ„์ „์„ 30๊ฐœ ์ด์ƒ์˜ ์œ ํ˜•์˜ ios ๋ฐ Android ํœด๋Œ€ํฐ ๋ฐ ํƒœ๋ธ”๋ฆฟ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ž‘์—… ์ค‘์ธ OS์—์„œ ์นด๋ฉ”๋ผ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์ˆ˜์ •๋œ ๋ฒ„์ „์— ๋Œ€ํ•ด ์œ„์— ๋‚จ๊ธด ๋Œ“๊ธ€์„ ํ™•์ธํ•˜์„ธ์š”. ๋Œ“๊ธ€์€ ์ดํ›„์— webrtc๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ๊ณ„์† ์ด์•ผ๊ธฐํ•˜๋Š”๋ฐ, ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ „์ฒด ๋ฌธ์ œ์ธ ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ์—์„œ webrtc๋ฅผ ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜๊ณ  ๋‹ค์‹œ ์ปดํŒŒ์ผํ–ˆ์Šต๋‹ˆ๋‹ค. webrtc๋Š” es5 ์ด์ƒ์œผ๋กœ ํŠธ๋žœ์ŠคํŒŒ์ผ๋  ๋•Œ ์ด ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ webrtc๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ฝ”๋”ฉ ๋ฐฉ์‹์œผ๋กœ ์ธํ•ด ์˜ฌ๋ฐ”๋ฅธ ์นด๋ฉ”๋ผ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•œ๋™์•ˆ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๊ณ ์ • ๋ฐ ํŠธ๋žœ์ŠคํŒŒ์ผ๋œ ์ผ๋ฐ˜ ๋ฐ ์ถ•์†Œ๋œ js ํŒŒ์ผ์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ํ•™์ƒ๊ณผ ๊ต์‚ฌ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ชจ๋“  ์ „ํ™”๊ธฐ์—์„œ QrCode๋กœ ํ•™๊ต ์ถœ์„์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ์ „ํ™”๊ธฐ๋Š” ํ˜„์žฌ ์•ฝ 30๊ฐœ ์ด์ƒ์˜ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์นด๋ฉ”๋ผ๋ฅผ ์žก์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒŒ ๋„์›€์ด ๋˜๊ธธ ๋ฐ”๋ž€๋‹ค.

ํ›„๋ฉด ์นด๋ฉ”๋ผ ์ฝ”๋“œ

scanner = new Instascan.Scanner({ video: video, scanPeriod: 4, mirror:false })
                .then(handleSuccess)
                .catch(handleError);
             //Start scanning
             scanner.addListener('scan', foundCode);

             Instascan.Camera.getCameras().then(function (cameras) {
                 if (cameras.length > 0) {
                     scanner.start(cameras[0]);
                 }
                 else {
            ...        
                 }
             }).catch (function (e) {
              ...  
             });

instascan.min.zip

#182(๋Œ“๊ธ€)

๊ณ ๋งˆ์›Œ, @apchandler11! ๋‹น์‹ ์€ ๋‚ด ์ž‘์—…์„ ์ €์žฅํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ง™์†Œ์‚ฌ!

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰