VinceG/vue-web-cam

autoplay prop does not work

sbaudino opened this issue · 13 comments

I have set the autoplay prop and nothing happened. I have took a look in the code and that prop is just declared but not using it in the code.

I need that the camera does not start as default so that i can start it when something happen in my app.

Thanks!

@sbaudino Autoplay is used on the video element.

https://github.com/VinceG/vue-web-cam/blob/master/src/webcam.vue#L6

that's how it actually works by default, you need to listen to events such as onCameras and then set a data property to the device id and pass it to the webcam component. You can also run start and stop as in the example provided in the repository to start and stop the camera respectively.

What I need to do is that the webcam does not start when the page loads. I need to start it when I change a select but i cant figure out how to do this. I tried to watch a vuex ready prop and when that prop is true I stop the camera but that didn't work. So, I need the camera is stop at the beggining. How can I do this?

Thanks!

@sbaudino the camera is stopped by default. as soon as you pass in the device id it starts. You can pass in the device id when you are ready to start it. Once it started for the first time you can either call stop or null the device id passed to stop it.

Edit:
The example with the dropdown select to chose which camera you want to use in this repository is pretty much exactly what you are looking to achieve it seems.

@VinceG The solution you gave me didn't work. I set by default the deviceId null and when I entered in the page the wembcam started and I saw in my laptop the light when the webcam is on and in the tab of the browser the icon circle when the tab is recording video.
I need to enter in the page and the camera starts stopped, that is, no light in my laptop and no red circle in the tab browser, completely off. Is there a way?

This is my original code.

<template>
  <div class="row" v-show="ready">
    <div class="col-md-12 col-lg-3">
      <div class="card">
        <h4 class="card-header">DOCUMENTOS</h4>
        <div class="card-body">
          <div class="comp-background">
            <div class="form-group">
              <span v-if="!accountOpen">Debes tener la cuenta abierta para poder subir documentos</span>
              <select v-if="accountOpen" class="form-control" name="tipo" v-model="type">
                <option value="" disabled selected>Tipo de documento</option>
                <option v-for="docKey in Object.keys(documents)" :value="docKey">{{ documents[docKey].label }}</option>
              </select>
            </div>
            <div v-show="type">
              <div class="form-group" v-show="!sourceButtonClicked">
                <b-button class="w-49" @click="showCamera">Cámara</b-button>
                <input type="file" ref="file" @change="handleFile" style="display: none">
                <b-button class="w-49" @click.prevent.stop="showUploadFile">Archivo</b-button>
              </div>
              <div class="form-group" v-show="sourceButtonClicked">
                <div v-show="camSelected && !photoTaken">
                  <vue-web-cam ref="webcam" @cameras="setDevices" :deviceId="deviceId" class="w-100 mb-2" :height="250"></vue-web-cam>
                </div>
                <img v-show="photoTaken" class="mb-15" :src="this.file" style="width:100%;height:250px;margin-bottom:10px" />
                <div class="mb-15" v-show="fileName">{{ fileName }}</div>
                <b-button class="w-49" @click="back">Atrás</b-button>
                <b-button class="w-49" v-show="!photoTaken && camSelected" @click="photo">Hacer foto</b-button>
                <b-button class="w-49" v-if="file" @click="sendFile">Enviar</b-button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="col-md-12 col-lg-9">
      <div class="card">
        <div class="card-body">
          <h4 class="mb-3">Documentos subidos</h4>
          <div class="table-responsive">
            <b-table class="tabla-basica" hover :items="docs" :fields="tableFields">
              <template slot="type" slot-scope="data">
                <span :id="`type-${data.item.id}`" class="editable" @click.prevent="showPopover(`type-${data.item.id}`)">{{ data.item.type }}</span>
              </template>
              <template slot="lwId" slot-scope="data">
                <span :id="`lwId-${data.item.id}`" class="editable" @click.prevent="showPopover(`lwId-${data.item.id}`)">{{ data.item.lwId || 'Empty' }}</span>
              </template>
              <template slot="status" slot-scope="data">
                <span :class="data.item.status.class" v-b-tooltip.hover :title="data.item.status.title">{{ data.item.status.label }}</span>
              </template>
              <template slot="download" slot-scope="data">
                <a href="#" @click.prevent="downloadFile(data.item)"><i class="dripicons-download"></i></a>
              </template>
              <template slot="upload" slot-scope="data">
                <a href="#" @click.prevent="uploadLw(data.item)"><i class="dripicons-upload"></i></a>
              </template>
              <template slot="delete" slot-scope="data">
                <a href="#" @click.prevent="$store.dispatch(`${store}/removeFile`, data.item)"><i class="dripicons-trash"></i></a>
              </template>
            </b-table>
            <popover v-for="popoverObj in popoversObj"
                     :key="popoverObj.target"
                     :popoverObj="popoverObj"
                     @hidePopover="hidePopover"
            ></popover>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
/* global document */
import documents from 'src/documents';
import ajax from 'src/ajax';
import popover from 'components/shared/popover.vue';

export default {
  name: 'documents',
  components: {
    popover,
  },
  data() {
    return {
      deviceId: null,
      devices: [],
      countDownAlert: 5,
      documents,
      type: '',
      error: '',
      sourceButtonClicked: false,
      camSelected: false,
      fileSelected: false,
      photoTaken: false,
      file: false,
      fileName: '',
      updating: false,
      activePopover: '',
      tableFields: {
        createdAt: {
          label: 'Fecha',
        },
        type: {
          label: 'Tipo',
        },
        description: {
          label: 'Descripción',
        },
        fileName: {
          label: 'Archivo',
        },
        lwId: {
          label: 'ID LW',
        },
        status: {
          label: 'Estado LW',
        },
        download: {
          label: 'Descargar',
        },
        upload: {
          label: 'Subir',
        },
        delete: {
          label: 'Eliminar',
        },
      },
      editableFields: [
        {
          key: 'type',
          tagType: 'select',
          options: Object.keys(documents).map((key) => {
            return {
              key,
              value: documents[key].label,
            };
          }),
        },
        {
          key: 'lwId',
          tagType: 'input',
          number: true,
        },
      ],
    };
  },
  props: ['store', 'section'],
  mounted() {
    this.$store.dispatch(`${this.store}/fetchDocuments`);
  },
  beforeDestroy() {
    this.$store.commit(`${this.store}/clearSection`, 'lists');
    this.stopCamera();
  },
  computed: {
    ready() {
      return this.$store.state[this.store].ready;
    },
    userId() {
      return this.$store.state[this.store].userId;
    },
    docs() {
      return this.$store.state[this.store].lists.docs;
    },
    walletStatusCode() {
      return this.$store.getters[`${this.store}/walletStatusCode`];
    },
    accountOpen() {
      return this.walletStatusCode > 1 && this.walletStatusCode !== 10;
    },
    popoversObj() {
      const popovers = [];
      this.docs.forEach((doc) => {
        Object.keys(doc).forEach((key) => {
          const editableField = this.editableFields.find(e => e.key === key);
          if (editableField) {
            popovers.push({
              section: 'docs',
              target: `${editableField.key}-${doc.id}`,
              value: doc[editableField.key],
              number: editableField.number,
              tagType: editableField.tagType,
              options: editableField.options,
              putURL: `/api/documents/${doc.id}`,
              updateMethod: this.updateProp,
              clear: this.clear,
            });
          }
        });
      });
      return popovers;
    },
  },
  methods: {
    setDevices(cameras) {
      this.deviceId = cameras[0].deviceId;
    },
    startCamera() {
      this.$refs.webcam.start();
    },
    stopCamera() {
      this.$refs.webcam.stop();
    },
    showCamera() {
      this.sourceButtonClicked = true;
      this.camSelected = true;
      this.startCamera();
    },
    showUploadFile() {
      const fileInput = this.$refs.file;
      fileInput.click();
    },
    updateProp(obj) {
      this.$store.commit(`${this.store}/updateListProperty`, obj);
    },
    back() {
      if (this.photoTaken) {
        this.photoTaken = false;
        this.startCamera();
      } else {
        this.stopCamera();
        this.sourceButtonClicked = false;
        this.camSelected = false;
        this.fileSelected = false;
        this.fileName = '';
      }
      this.file = false;
    },
    photo() {
      this.file = this.$refs.webcam.capture();
      this.photoTaken = true;
      this.stopCamera();
    },
    handleFile() {
      this.sourceButtonClicked = true;
      this.fileSelected = true;
      const file = this.$refs.file.files[0];
      this.fileName = file.name;
      this.file = file;
    },
    sendFile() {
      const formData = new FormData();
      formData.append('file', this.file);
      formData.append('type', this.type);
      formData.append('description', this.documents[this.type].desc);
      formData.append('user', this.userId);
      if (this.section === 'affiliate') {
        formData.append('affiliate', this.$store.state[this.store].affiliateId);
      } else {
        formData.append('loan', this.$store.state[this.store].creditId);
      }
      this.reset();
      this.$store.dispatch(`${this.store}/createFile`, formData);
      this.stopCamera();
    },
    uploadLw(document) {
      this.$store.commit(`${this.store}/setReady`, false);
      ajax('PUT', `${process.env.APIURL}/api/uploadDocumentLW/${document.id}`)
        .then(() => {
          this.$store.commit(`${this.store}/setSuccess`, 'Se ha subido correctamente el documento a LW');
        })
        .catch(() => {
          this.$store.commit(`${this.store}/setError`, 'Ha habido un error subiendo el documento a LW');
        })
        .finally(() => {
          this.$store.commit(`${this.store}/setReady`, true);
        });
    },
    reset() {
      this.type = '';
      this.sourceButtonClicked = false;
      this.camSelected = false;
      this.fileSelected = false;
      this.photoTaken = false;
      this.file = false;
      this.fileName = '';
      this.$refs.file.value = '';
    },
    downloadFile(file) {
      ajax('GET', `${process.env.APIURL}/api/documents/${file.id}/media`)
        .then((response) => {
          const link = document.createElement('a');
          link.href = response.media;
          link.download = file.description;
          link.click();
        });
    },
    showPopover(target) {
      this.$root.$emit('bv::show::popover', target);
      if (this.activePopover !== target) {
        this.$root.$emit('bv::hide::popover', this.activePopover);
      }
      this.activePopover = target;
    },
    hidePopover(popoverId) {
      this.$root.$emit('bv::hide::popover', popoverId);
    },
    clear(error) {
      this.$store.commit(`${this.store}/setError`, error);
    },
  },
  watch: {
    ready: {
      deep: true,
      handler() {
        if (this.ready) {
          this.stopCamera();
        }
      },
    },
  },
};
</script>

<style>
</style>
```

I tried using watcher of ready prop of my store but didn't work at all. Sometimes works but sometimes doesn't.

I want to start the component with the camera off and just when i click in "Cámara" button the camera starts (rd icon in browser's url and light in laptop)

@sbaudino Can't you just add another prop to toggle when you actually want to start the camera or use v-if instead of the camera component created when you need it.

<div v-if="cameraStart" v-show="camSelected && !photoTaken">

or

<div v-if="camSelected && !photoTaken">

I tried doing it but when the condition of v-if is true I had an error of start method of the webcam component.

@sbaudino Right because the component is not rendered, wrap that start with the cameraStart or camSelected prop.

@sbaudino My point is, this isn't really an issue with the plugin. It's a usage issue.

Right because the component is not rendered, wrap that start with the cameraStart or camSelected prop

How can I do this? i didnt understand you sorry.

according to my code

I've has the same issue as sbaudino. I think autoplay=false should stop it from autostarting until programatically doing it