Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 91精品啪在线观看国产91九色,成人福利视频在线,亚洲日本va中文字幕婷婷

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          HTML5 的調用攝像頭拍照和獲取視頻流的方法

          著web功能越來越強大,我們很多時候需要在web頁面來獲取攝像頭進行操作,原生html5提供了對攝像頭的支持,需要用戶的同意授權,下面是一個基于 HTML5 的調用攝像頭拍照并上傳后臺的示例代碼:

          html復制代碼<!DOCTYPE html>
          <html>
          <head>
              <title>拍照上傳</title>
          </head>
          <body>
              <video id="video" style="width:300px;height:200px;"></video>
              <br>
              <button id="btn-start">啟動攝像頭</button>
              <button id="btn-stop">停止攝像頭</button>
              <button id="btn-capture">拍照上傳</button>
              <br>
              <canvas id="canvas"></canvas>
              <form id="form-upload" method="post" enctype="multipart/form-data">
                  <input type="file" id="input-file" name="file"/>
              </form>
          
              <script type="text/javascript">
                  var video = document.getElementById('video');
                  var canvas = document.getElementById('canvas');
                  var ctx = canvas.getContext('2d');
                  
                  // 啟動攝像頭
                  document.getElementById('btn-start').addEventListener('click', function() {
                      navigator.mediaDevices.getUserMedia({
                          video: true,
                          audio: false
                      }).then(function(stream) {
                          video.srcObject = stream;
                      }).catch(function(err) {
                          console.log("啟動攝像頭失敗:" + err);
                      });
                  });
          
                  // 停止攝像頭
                  document.getElementById('btn-stop').addEventListener('click', function() {
                      video.pause();
                      video.srcObject.getTracks()[0].stop();
                      video.srcObject = null;
                  });
          
                  // 拍照,并上傳到后臺
                  document.getElementById('btn-capture').addEventListener('click', function() {
                      canvas.width = video.videoWidth;
                      canvas.height = video.videoHeight;
                      ctx.drawImage(video, 0, 0);
                      canvas.toBlob(function(blob) {
                          var formData = new FormData();
                          formData.append('file', blob, 'photo.jpg');
                          postRequest('/upload', formData, function(res) {
                              alert(res.message);
                          });
                      }, 'image/jpeg');
                  });
          
                  // 發送 POST 請求
                  function postRequest(url, data, callback) {
                      var xhr = new XMLHttpRequest();
                      xhr.open('POST', url, true);
                      xhr.onreadystatechange = function() {
                          if (xhr.readyState == 4 && xhr.status == 200) {
                              var res = JSON.parse(xhr.responseText);
                              callback(res);
                          }
                      };
                      xhr.send(data);
                  }
              </script>
          </body>
          </html>
          

          上述代碼主要分為以下幾個部分:

          1. html5 的 <video> 元素用于顯示攝像頭數據流,我們可以通過 JavaScript API 控制調用攝像頭、暫停和關閉。同時使用了 <canvas> 元素來緩存視頻幀的圖像數據。
          2. 頁面中 btn-start 按鈕通過 getUserMedia() 方法請求瀏覽器授權,并將攝像頭數據流傳給 <video> 元素進行播放。
          3. 點擊 btn-capture 按鈕時,通過 toBlob() 將緩存的圖像數據轉化為 Blob 對象,并封裝到 FormData 中,以便發送給后臺服務。
          4. postRequest() 函數用于發送包含文件數據的 POST 請求,其中 FormData 對象中的 key 是上傳后臺服務器處理時需要讀取的參數名稱,通常對應具體的后臺業務邏輯。

          最后,需要注意的是,在本地調試和開發時,特別是在 Windows 操作系統下使用 Chrome 瀏覽器訪問時,可能會遇到攝像頭不能正常運行的情況。這時可以打開地址欄,在目標請求前加上 --unsafely-treat-insecure-origin-as-secure="http://localhost:8080" 參數(其中端口號需替換成實際的本地服務端口),即可獲得權限,進行攝像頭使用。

          基于Electron實現的pc端智能驗機應用,近期迭代了一個新的功能,需求是通過電腦外接攝像頭對手機屏幕進行拍照,拍照后需將照片上傳至服務端進行屏幕信息比對,確定被檢測屏幕是否為原廠屏。

          需求分析

          根據上面的需求,分析大概要以下幾個步驟。

          1. 先實現將攝像頭的畫面實時展示在頁面視頻采集區域中;
          2. 將攝像頭中的視頻畫面采集一幀成圖片并回顯;
          3. 將生成的圖片上傳至CDN拿到圖片鏈接;
          4. 將圖片鏈接上傳到后端接口做處理;

          確定了需要以上四個步驟后,接下來一步一步實現。

          實現

          視頻采集

          由于 Electron 內置了 Chromium 瀏覽器,該瀏覽器對各項前端標準都支持得非常好,所以基于 Electron 開發應用不會遇到瀏覽器兼容性問題。幾乎可以在 Electron 中使用所有 HTML5CSS3ES6 標準中定義的 API

          所以基于WebRTC提供的API即可獲取到攝像頭的視頻流。

          MediaDevices.getUserMedia()

          代碼如下:

          methods: {
              getUserMedia() {
                  /* 可同時開啟video(攝像頭)和audio(麥克風) 這里只請求攝像頭,所以只設置video為true */
                  navigator.mediaDevices.getUserMedia({ video: true })
                      .then(function(stream) {
                        /* 使用這個 stream 傳遞到成功回調中 */
                        this.success(stream)
                      })
                      .catch(function(err) {
                        /* 處理 error 信息 */
                        this.error(error)
                      });
              }
          }
          
          

          MediaDevices.getUserMedia() 會提示用戶給予使用媒體輸入的許可,媒體輸入會產生一個MediaStream,里面包含了請求的媒體類型的軌道。此流可以包含一個視頻軌道(來自硬件或者虛擬視頻源,比如相機、視頻采集設備和屏幕共享服務等等)、一個音頻軌道(同樣來自硬件或虛擬音頻源,比如麥克風、A/D 轉換器等等),也可能是其它軌道類型。

          它返回一個 Promise 對象,成功后會resolve回調一個 MediaStream 對象。若找不到滿足請求參數的媒體類型,promisereject回調一個NotFoundError

          現在已經成功獲取到視頻流,接下來就是將視頻流回顯到頁面。這里使用video標簽完成,代碼如下:

          <template>
              <div class="video-page">
                  <div class="video-content">
                      <video ref="video" class="video-item"></video>
                  </div>
              </div>
          </template>
          
          export default {
             methods: {
                 getUserMedia() {
                      /* 可同時開啟video(攝像頭)和audio(麥克風) 這里只請求攝像頭,所以只設置video為true */
                      navigator.mediaDevices.getUserMedia({ video: true })
                          .then(function(stream) {
                            /* 使用這個 stream 傳遞到成功回調中 */
                            this.success(stream)
                          })
                          .catch(function(err) {
                            /* 處理 error 信息 */
                            this.error(error)
                          });
                  },
                 success(stream) {
                     console.log('成功', stream);
                     /* 將stream 分配給video標簽 */
                     this.$refs.video.srcObject = stream;
                     this.$refs.video.play();
                  }
              }
          }
          
          

          這時,攝像頭中的畫面就可以顯示在頁面video標簽內,如下圖。

          為了用戶體驗,在進入頁面之前添加了判斷攝像頭是否已經接入并可用的邏輯,避免用戶的攝像頭未接入或者啟動,造成應用不可用的錯覺。

          使用MediaDevices.enumerateDevices()來獲取可用媒體輸入和輸出設備的列表,例如攝像頭、麥克風、耳機等。

          navigator.mediaDevices.enumerateDevices().then(devicesList => {
              console.log('------devicesList', deviceList)
          })
          

          得到的設備列表數據格式如下:

          kind類型有三種,分別是audioinputaudiooutputvideoinput。分別代表音視頻的輸入和輸出。可在列表中查找目標媒體是否已經接入且可用。

          若有選擇切換設備需求,可根據kind類型進行媒體設備分類,選擇目標deviceId,傳入navigator.mediaDevices.getUserMedia,完成來源切換。

           navigator.mediaDevices.getUserMedia({ video: { deviceId: xxxx } })
          

          拍照生成圖片

          拍照其實就是截取視頻中的某一幀,這里使用canvas來實現截取。getContext() 方法可返回一個對象,該對象提供了用于在畫布上繪圖的方法和屬性。其中drawImage()方法用來向畫布上繪制圖像、畫布或視頻。

          <template>
              <div class="video-page">
                  <div class="video-content">
                      <video ref="video" class="video-item" v-if="showVideo"></video>
                      <canvas ref="canvas" v-else width="500" height="346"></canvas>
                  <div class="video-buttons">
                      <div @click="capture" class="button-item capture">拍照</div>
                      <div @click="submit" class="button-item submit"}">提交</div>
                  </div>
              </div>
          </template>
          
          export default {
             data: {
                 showVideo: true, // 是否展示攝像頭畫面
             },
             methods: {
                  /* 拍照按鈕點擊 */
                  capture() {
                    this.showVideo = false
                    var context = this.$refs.canvas.getContext('2d');
                    /* 要跟video的寬高一致 */
                    context.drawImage(this.$refs.video, 0, 0, 1000, 692, 0, 0, 500, 346);
                  }
              }
          }
          
          

          拍照的圖片回顯至canvas標簽。

          上傳圖片至CDN

          上個步驟已經完成了拍照,接下來就需要將圖片上傳至CDN,拿到圖片鏈接。這里有兩種方式可以實現獲取圖片數據。

          1. 使用HTMLCanvasElement.toBlob()

          HTMLCanvasElement.toBlob() 方法生成 Blob 對象,用以展示 canvas 上的圖片。因為直接可以拿到圖片文件,所以無需再使用方法2中的函數來轉化base64,直接可以獲取到圖片文件用來上傳。

          語法

          toBlob(callback, type, quality)
          

          參數

          callback:回調函數,參數為Blob對象(目標圖片文件)。

          type:圖片格式,默認為image/png 可選

          quality:0-1的數字,表示圖片質量,可選

          點擊提交按鈕按鈕時,先獲取圖片文件,為上傳做準備。

          methods: {
              /* 提交按鈕點擊 */
              submit() {
                  const base64Url = this.$refs.canvas.toBlob(blob => {
                      console.log('===blob', blob)
                      const data = new FormData()
                      data.append('file', blob)
                      request.post('https://XXXXX/upload', data)
                  }, "image/jpeg", 0.95)
              }
          }
          

          console的結果如下圖:

          2. 使用HTMLCanvasElement.toDataURL()

          HTMLCanvasElement.toDataURL()方法返回一個包含圖片展示的Data URL。

          Data URL,即前綴為 data: 協議的 URL,其允許內容創建者向文檔中嵌入小文件。

          語法

          canvas.toDataURL(type, encoderOptions);
          

          參數

          type 圖片格式,默認為image/png

          encoderOptions 0到1之間的值,用來選定圖片質量,默認值是0.92,超出范圍會使用默認值。

          返回值

          base64組成的圖片源數據,上傳前需轉為圖片文件。這里封裝了一個convertBase64UrlToImgFile函數用來轉換。代碼如下:

          <template>
              <div class="video-page">
                  <div class="video-content">
                      <video ref="video" class="video-item" v-if="showVideo"></video>
                      <canvas ref="canvas" v-else width="500" height="346"></canvas>
                  <div class="video-buttons">
                      <div @click="capture" class="button-item capture">拍照</div>
                      <div @click="submit" class="button-item submit">提交</div>
                  </div>
              </div>
          </template>
          
          export default {
             data: {
                 /* 是否展示攝像頭畫面 */
                 showVideo: true,
             },
             methods: {
                  /* 將base64轉為圖片文件 */
                  convertBase64UrlToImgFile(urlData, fileType) {
                      const imgData = urlData.split('base64,').splice(-1)[0]
                      /* 解碼使用 base-64 編碼的字符串 轉換為byte */
                      const bytes = window.atob(imgData)
                      
                      /* 處理異常,將ASCII碼小于0的轉換為大于0 */
                      const ab = new ArrayBuffer(bytes.length)
                      const ia = new Int8Array(ab)
                      
                      for (let i = 0; i < bytes.length; i++) {
                          ia[i] = bytes.charCodeAt(i)
                      }
                      
                      /* 轉換成文件,可以添加文件的type,lastModifiedDate屬性 */
                      const blob = new Blob([ab], { type: fileType })
                      blob.lastModifiedDate = new Date()
                      return blob
                  },
                  /* 提交按鈕點擊 */
                  async submit() {
                      const base64Url = this.$refs.canvas.toDataURL()
                      const imgFile = this.convertBase64UrlToImgFile(base64Url, 'image/jpg')
                      console.log('====imgFile', imgFile)
                      const data = new FormData()
                      data.append('file', imgFile)
                      /* 上傳 */
                      request.post('https://XXXXX/upload', data)
                  },
              }
          }
          

          convertBase64UrlToImgFile可用于在使用canvas外的場景進行base64轉換圖片文件。和HTMLCanvasElement.toBlob()方法得到的結果一致。

          以上兩種方法都可以完成圖片上傳,最終拿到CDN圖片鏈接后可傳給后端進行處理。獲取屏幕信息。

          總結

          通過以上四個步驟就完成了Electron應用中通過外接攝像頭拍照并上傳的功能。這里基本用不到Electron的能力,和在web端的實現方式并無區別,Electron在這里起到的作用就是獲取攝像頭媒體流不需要獲取用戶權限。

          Electron是基于ChromiumNode.js實現的,這就使前端開發者可以使用JavaScriptHTMLCSS輕松構建跨平臺的桌面應用。Electron可以使用幾乎所有的Web前端生態領域及Node.js生態領域的組件和技術方案。

          后續會介紹Electron在智能驗機應用中的實踐方案,敬請期待~

          作者:謝星

          來源:微信公眾號:大轉轉FE
          出處:https://mp.weixin.qq.com/s/Yb590oc6u94feS9s7FZWrQ

          天在博客中加了個新的功能,直接復制圖片然后黏貼上傳到服務器。

          之前是自己弄的markdown編輯器,很多功能不完善,剛開始加了個插入圖片的按鈕,現在能直接復制圖片方便多了。

          目前只支持chrome瀏覽器,哈哈,感覺chrome是最好用的瀏覽器。

          主要原理是利用paste事件,然后拿到里面的圖片數據上傳到服務器。

          下面貼代碼

          <textarea id="content" />

          有個編輯的文本框,然后監聽parse事件

          document.querySelector('#content').addEventListener('paste', function(event) {

          var isChrome = false;

          if (event.clipboardData || event.originalEvent) {

          //not for ie11 某些chrome版本使用的是event.originalEvent

          var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);

          if (clipboardData.items) {

          // for chrome

          var items = clipboardData.items, len = items.length, blob = null;

          isChrome = true;

          for (var i = 0; i < len; i++) {

          if (items[i].type.indexOf("image") !== -1) {

          //getAsFile() 此方法只是living standard firefox ie11 并不支持

          blob = items[i].getAsFile();

          }


          主站蜘蛛池模板: 日韩精品一区二区三区老鸦窝| 久久人妻无码一区二区| 国产精品视频一区二区噜噜 | 中日韩精品无码一区二区三区| 国产激情精品一区二区三区| 日韩一区二区三区免费体验| tom影院亚洲国产一区二区| 久久久久久人妻一区二区三区| 亚洲国产精品一区二区久久hs| 亚洲美女高清一区二区三区| 国产精品福利一区| 在线精品亚洲一区二区| 麻豆aⅴ精品无码一区二区| 日本午夜精品一区二区三区电影| 日韩人妻无码一区二区三区| 亚洲成人一区二区| 久久精品国产一区二区三区不卡| 一区二区三区午夜| 好湿好大硬得深一点动态图91精品福利一区二区 | 亚洲毛片不卡av在线播放一区| 国产一区美女视频| 国产产一区二区三区久久毛片国语| 午夜爽爽性刺激一区二区视频| 亚洲视频一区二区三区四区| 91精品一区二区三区在线观看| 无码日韩精品一区二区免费暖暖| 亚洲国产精品一区二区第一页| 一区二区三区人妻无码| 黑人大战亚洲人精品一区| 亚洲国产精品一区二区九九 | 国产午夜精品一区理论片| 国产天堂在线一区二区三区| 麻豆精品人妻一区二区三区蜜桃| 日韩亚洲AV无码一区二区不卡| 99精品国产高清一区二区麻豆| 亚洲欧美国产国产一区二区三区| 无码精品一区二区三区| 色屁屁一区二区三区视频国产 | 狠狠做深爱婷婷综合一区 | 日本道免费精品一区二区| 国产内射在线激情一区|