diff --git a/packages/qr-code-scanner/src/qr-code-scanner.js b/packages/qr-code-scanner/src/qr-code-scanner.js
index 6d97c1cd58be58c2f8e0fdb738c0c748dd350dde..775c4d524e0eb921dc6afef4a8633ea53363c7d5 100644
--- a/packages/qr-code-scanner/src/qr-code-scanner.js
+++ b/packages/qr-code-scanner/src/qr-code-scanner.js
@@ -4,8 +4,9 @@ import DBPLitElement from 'dbp-common/dbp-lit-element';
 import * as commonStyles from 'dbp-common/styles';
 import {Icon, MiniSpinner} from 'dbp-common';
 import {classMap} from 'lit-html/directives/class-map.js';
-import QrScanner from 'qr-scanner';
 import * as commonUtils from "dbp-common/utils";
+import jsQR from "jsqr";
+
 
 /**
  * Notification web component
@@ -14,6 +15,19 @@ export class QrCodeScanner extends DBPLitElement {
     constructor() {
         super();
         this.lang = 'de';
+
+        this.videoRunning = false;
+        this.notSupported = false;
+
+        this.scanIsOk = true;
+
+    }
+
+    static get scopedElements() {
+        return {
+            'dbp-icon': Icon,
+            'dbp-mini-spinner': MiniSpinner,
+        };
     }
 
     /**
@@ -22,6 +36,9 @@ export class QrCodeScanner extends DBPLitElement {
     static get properties() {
         return {
             lang: { type: String },
+            videoRunning: { type: Boolean, attribute: false },
+            notSupported: { type: Boolean, attribute: false },
+            scanIsOk: { type: Boolean, attribute: true }
         };
     }
 
@@ -31,10 +48,146 @@ export class QrCodeScanner extends DBPLitElement {
         const that = this;
 
         this.updateComplete.then(()=>{
-            QrScanner.WORKER_PATH = commonUtils.getAssetURL('dbp-qr-scanner', 'qr-scanner-worker.min.js');
-            const qrScanner = new QrScanner(this._('#reader'), result => console.log('decoded qr code:', result), undefined, undefined, 'user');
-            qrScanner.start();
+
+            // Check for support & cams
+           if (!!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
+               navigator.mozGetUserMedia || navigator.msGetUserMedia) && !(!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices)) {
+               console.log("Everything works");
+               this.notSupported = false;
+           } else {
+               this.notSupported = true;
+               console.log("not supportet");
+           }
+
+           let devices_map = new Map();
+
+           const that = this;
+
+            navigator.mediaDevices.enumerateDevices()
+                .then(function(devices) {
+                    devices.forEach(function(device) {
+                        console.log(device.kind + ": " + device.label +
+                            " id = " + device.deviceId);
+                        if(device.kind === 'videoinput') {
+                            // TODO Ãœbersetzen
+                            devices_map.set(device.deviceId, device.label || 'camera ' + (devices_map.size + 1));
+                        }
+                    });
+                    if(devices_map.size < 1) {
+                        that.notSupported = true;
+                    }
+                    for (let [id, label] of devices_map)
+                    {
+                        let opt = document.createElement("option");
+                        opt.value= id;
+                        opt.text = label;
+                        that._('#videoSource').appendChild(opt);
+                    }
+                })
+                .catch(function(err) {
+                    console.log(err.name + ": " + err.message);
+                    that.notSupported = true;
+                });
+
+
+
+
+        });
+    }
+
+    qrCodeScannerInit() {
+        let video = document.createElement("video");
+        let canvasElement = this._("#canvas");
+        let canvas = canvasElement.getContext("2d");
+        let loadingMessage = this._("#loadingMessage");
+        let outputContainer = this._("#output");
+        let outputMessage = this._("#outputMessage");
+        let outputData = this._("#outputData");
+
+        let color = this.scanIsOk ? getComputedStyle(document.documentElement)
+                .getPropertyValue('--dbp-success-bg-color') : getComputedStyle(document.documentElement)
+            .getPropertyValue('--dbp-danger-bg-color');
+
+
+        function drawLine(begin, end, color) {
+            canvas.beginPath();
+            canvas.moveTo(begin.x, begin.y);
+            canvas.lineTo(end.x, end.y);
+            canvas.lineWidth = 4;
+            canvas.strokeStyle = color;
+            canvas.stroke();
+        }
+
+        const that = this;
+        // Use facingMode: environment to attemt to get the front camera on phones
+        navigator.mediaDevices.getUserMedia({ video: { deviceId: this._('#videoSource').val } }).then(function(stream) {
+            video.srcObject = stream;
+            video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
+            video.play();
+            that.videoRunning = true;
+            requestAnimationFrame(tick);
+
+            const track = stream.getVideoTracks()[0];
+            track.applyConstraints(constraints)
+                .then(() => {
+                    advanced : [{ zoom: 3 }]
+                    // Do something with the track such as using the Image Capture API.
+                })
+
         });
+
+        function tick() {
+            if (that.videoRunning === false) {
+                video.srcObject.getTracks().forEach(function(track) {
+                    track.stop();
+                    console.log("stop early");
+                    loadingMessage.hidden = false;
+                    canvasElement.hidden = true;
+                    outputContainer.hidden = true;
+                });
+                loadingMessage.innerText = "🎥 Unable to access video stream (please make sure you have a webcam enabled)";
+                return;
+            }
+
+            loadingMessage.innerText = "⌛ Loading video..."
+            if (video.readyState === video.HAVE_ENOUGH_DATA) {
+                loadingMessage.hidden = true;
+                canvasElement.hidden = false;
+                outputContainer.hidden = false;
+
+                canvasElement.height = video.videoHeight;
+                canvasElement.width = video.videoWidth;
+                canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
+                var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
+                var code = jsQR(imageData.data, imageData.width, imageData.height, {
+                    inversionAttempts: "dontInvert",
+                });
+                if (code) {
+                    drawLine(code.location.topLeftCorner, code.location.topRightCorner, that.scanIsOk ? 'green' : 'red');
+                    drawLine(code.location.topRightCorner, code.location.bottomRightCorner, that.scanIsOk ? 'green' : 'red');
+                    drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, that.scanIsOk ? 'green' : 'red');
+                    drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, that.scanIsOk ? 'green' : 'red');
+                    outputMessage.hidden = true;
+                    outputData.parentElement.hidden = false;
+                    outputData.innerText = code.data;
+                    that.sendUrl(code.data);
+                } else {
+                    outputMessage.hidden = false;
+                    outputData.parentElement.hidden = true;
+                }
+            }
+            requestAnimationFrame(tick);
+        }
+    }
+
+    stopScanning() {
+        this.videoRunning = false;
+    }
+    
+    sendUrl(url) {
+        const event = new CustomEvent("dbp-qr-code-scanner-url",
+            {  bubbles: true, composed: true , detail: url});
+        this.dispatchEvent(event);
     }
 
     static get styles() {
@@ -42,21 +195,78 @@ export class QrCodeScanner extends DBPLitElement {
         return css`
             ${commonStyles.getThemeCSS()}
             ${commonStyles.getGeneralCSS()}
+            
+             body {
+              font-family: 'Ropa Sans', sans-serif;
+              color: #333;
+              max-width: 640px;
+              margin: 0 auto;
+              position: relative;
+            }
+
+            #loadingMessage {
+              text-align: center;
+              padding: 40px;
+            }
+        
+            #canvas {
+              width: 100%;
+            }
+        
+            #output {
+              margin-top: 20px;
+              background: #eee;
+              padding: 10px;
+              padding-bottom: 0;
+            }
+        
+            #output div {
+              padding-bottom: 10px;
+              word-wrap: break-word;
+            }
+        
+            #noQRFound {
+              text-align: center;
+            }
         `;
     }
 
-    //todo check for cam: QrScanner.hasCamera();
-    //start stop button
     //doku
     //demo
-    //quadrat
+
+    //check obs geht: function hasGetUserMedia() {
+    //   // Note: Opera builds are unprefixed.
+    //   return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
+    //             navigator.mozGetUserMedia || navigator.msGetUserMedia);
+    // }
+    //
+    // if (hasGetUserMedia()) {
+    //   // Good to go!
+    // } else {
+    //   alert('getUserMedia() is not supported in your browser');
+    // }
 
     render() {
         return html`
             <div class="columns">
                 <div class="column" id="qr">
-                    <button class="start">start scanning</button>
-                    <video id="reader"></video>
+                    
+                    
+                    <div class="${classMap({hidden: this.notSupported})}">
+                        <div id="loadingMessage">🎥 Unable to access video stream (please make sure you have a webcam enabled)</div>
+                        <button id="switch">On / Off</button>
+                        <canvas id="canvas" hidden></canvas>
+                        <select id="videoSource"></select>
+                        <button class="start ${classMap({hidden: this.videoRunning})}" @click="${() => this.qrCodeScannerInit()}">start scanning</button>
+                        <button class="stop ${classMap({hidden: !this.videoRunning})}" @click="${() => this.stopScanning()}">stop scanning</button>
+                          <div id="output" hidden>
+                            <div id="outputMessage">No QR code detected.</div>
+                            <div hidden><b>Data:</b> <span id="outputData"></span></div>
+                        </div>
+                    </div>
+                    <div class="${classMap({hidden: !this.notSupported})}">
+                        Ihr device unterstützt keine video aufnahmen
+                    </div>
                 </div>
             </div>
         `;