JS打開攝像頭並截圖上傳

来源:http://www.cnblogs.com/imwtr/archive/2017/02/18/6413595.html
-Advertisement-
Play Games

直入正題,JS打開攝像頭並截圖上傳至後端的一個完整步驟 1. 打開攝像頭主要用到getUserMedia方法,然後將獲取到的媒體流置入video標簽 2. 截取圖片主要用到canvas繪圖,使用drawImage方法將video的內容繪至canvas中 3. 將截取的內容上傳至伺服器,將canvas ...


直入正題,JS打開攝像頭並截圖上傳至後端的一個完整步驟

 

 

1. 打開攝像頭主要用到getUserMedia方法,然後將獲取到的媒體流置入video標簽

2. 截取圖片主要用到canvas繪圖,使用drawImage方法將video的內容繪至canvas中

3. 將截取的內容上傳至伺服器,將canvas中的內容轉為base64格式上傳,後端(PHP)通過file_put_contents將其轉為圖片

要註意的是,在chrome以外的瀏覽器中,使用攝像頭或多或少會出現一些問題,可能也是老問題了,所以以下代碼主要基於chrome使用

比如在最新版FireFox中的報錯,不知為啥

 

1. 打開攝像頭

getUserMedia 有新版本和舊版本兩種,建議使用新版本

 

舊版本位於navigator 對象下,根據瀏覽器不同有所不同

// 獲取媒體方法(舊方法)
    navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMeddia || navigator.msGetUserMedia;
if (navigator.getMedia) {
        navigator.getMedia({
            video: true
        }, function(stream) {
            mediaStreamTrack = stream.getTracks()[0];

            video.src = (window.URL || window.webkitURL).createObjectURL(stream);
            video.play();
        }, function(err) {
            console.log(err);
        });
    }

第一個參數中指示需要使用視頻(video)或音頻(audio),更多參見文檔

第二個參數中指示調用成功後的回調,其中帶一個參數(MediaStream),在舊版本中可以直接通過調用MediaStream.stop() 來關閉攝像頭,不過在新版之中已廢棄。需要使用MediaStream.getTracks()[index].stop() 來關閉相應的Track

第三個參數指示調用失敗後的回調

 

新版本位於navigator.mediaDevices 對象下

if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices.getUserMedia({
            video: true,
            audio: true
        }).then(function(stream) {
            console.log(stream);

            mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[1];

            video.src = (window.URL || window.webkitURL).createObjectURL(stream);
            video.play();
        }).catch(function(err) {
            console.log(err);
        })
    }

與舊版類似,不過該方法返回了一個Promise對象,可以使用then和catch表示成功與失敗的回調

更多參見文檔

需要註意的是,MediaStream.getTracks() 返回的Tracks數組是按第一個參數倒序排列的

比如現在定義了

{
    video: true,
    audio: true
}

想關閉攝像頭,就需要調用MediaStream.getTracks()[1].stop();

同理,0對應於audio的track

 

使用createObjectURL 將MediaStream寫入video標簽,就能夠存儲實時的媒體流數據(也可以方便的實時查看畫面)

舊版本中webkitURL 對象以不被支持,需要使用URL對象

 

  <video width="200" height="150"></video>
    <canvas width="200" height="150"></canvas>

    <p>
        <button id="snap">截取圖像</button>
        <button id="close">關閉攝像頭</button>
        <button id="upload">上傳圖像</button>
    </p>

    <img id="uploaded" width="200" height="150" />

 

2. 截取圖像

將內容寫入即可

// 截取圖像
    snap.addEventListener('click', function() {
        context.drawImage(video, 0, 0, 200, 150);
    }, false);

 

3. 關閉攝像頭

// 關閉攝像頭
    close.addEventListener('click', function() {
        mediaStreamTrack && mediaStreamTrack.stop();
    }, false);

 

4. 上傳截取的圖像

canvas.toDataURL('image/png')

// 上傳截取的圖像
    upload.addEventListener('click', function() {
        jQuery.post('/uploadSnap.php', {
            snapData: canvas.toDataURL('image/png')
        }).done(function(rs) {
            rs = JSON.parse(rs);

            console.log(rs);

            uploaded.src = rs.path;
        }).fail(function(err) {
            console.log(err);
        });
    }, false);

而這裡的後端(PHP)則將獲取的內容轉換成圖像文件保存

需要註意的是,要將base64的頭部信息欄位去掉再保存,否則似乎圖像是損壞無法打開滴

<?php

    $snapData = $_POST['snapData'];
    $snapData = str_replace('data:image/png;base64,', '', $snapData);
    // $snapData = str_replace(' ', '+', $snapData);

    $img = base64_decode($snapData);

    $uploadDir = 'upload/';
    $fileName = date('YmdHis', time()) . uniqid();

    if (!(file_put_contents($uploadDir . $fileName, $img))) {
        echo json_encode(array('code' => 500, 'msg' => '文件上傳失敗'));
    } else {
        echo json_encode(array('code' => 200, 'msg' => '文件上傳成功', 'path' => $uploadDir . $fileName));
    }

?>

 

完整JS代碼

 1 <script type="text/javascript" src="jquery.js"></script>
 2     <script type="text/javascript">
 3     function $(elem) {
 4         return document.querySelector(elem);
 5     }
 6 
 7     // 獲取媒體方法(舊方法)
 8     navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMeddia || navigator.msGetUserMedia;
 9 
10     var canvas = $('canvas'),
11         context = canvas.getContext('2d'),
12         video = $('video'),
13         snap = $('#snap'),
14         close = $('#close'),
15         upload = $('#upload'),
16         uploaded = $('#uploaded'),
17         mediaStreamTrack;
18 
19     // 獲取媒體方法(新方法)
20     // 使用新方法打開攝像頭
21     if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
22         navigator.mediaDevices.getUserMedia({
23             video: true,
24             audio: true
25         }).then(function(stream) {
26             console.log(stream);
27 
28             mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[1];
29 
30             video.src = (window.URL || window.webkitURL).createObjectURL(stream);
31             video.play();
32         }).catch(function(err) {
33             console.log(err);
34         })
35     }
36     // 使用舊方法打開攝像頭
37     else if (navigator.getMedia) {
38         navigator.getMedia({
39             video: true
40         }, function(stream) {
41             mediaStreamTrack = stream.getTracks()[0];
42 
43             video.src = (window.URL || window.webkitURL).createObjectURL(stream);
44             video.play();
45         }, function(err) {
46             console.log(err);
47         });
48     }
49 
50     // 截取圖像
51     snap.addEventListener('click', function() {
52         context.drawImage(video, 0, 0, 200, 150);
53     }, false);
54 
55     // 關閉攝像頭
56     close.addEventListener('click', function() {
57         mediaStreamTrack && mediaStreamTrack.stop();
58     }, false);
59 
60     // 上傳截取的圖像
61     upload.addEventListener('click', function() {
62         jQuery.post('/uploadSnap.php', {
63             snapData: canvas.toDataURL('image/png')
64         }).done(function(rs) {
65             rs = JSON.parse(rs);
66 
67             console.log(rs);
68 
69             uploaded.src = rs.path;
70         }).fail(function(err) {
71             console.log(err);
72         });
73     }, false);
74 
75     </script>
View Code

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • var ca = document.getElementById("ca"); var ctx = ca.getContext('2d'); //生成n~m之間的隨機數的函數 function random(n,m){ return Math.floor(Math.random() * (m - n... ...
  • 新手Perfect教程之JavaScript教程—①你好,世界! ...
  • CSS命名規範(規則)常用的CSS命名規則 頭:header 內容:content/container 尾:footer 導航:nav 側欄:sidebar 欄目:column 頁面外圍控制整體佈局寬度:wrapper 左右中:left right center 登錄條:loginbar 標誌:lo ...
  • html代碼: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <title>輪播圖練習</title> <link rel="stylesheet" href="css/css.css" type="text/css"/ ...
  • 動態顯示目錄的作用 不用每次寫博客的時候繁瑣的人工整理目錄,又可以動態浮動在右下角,方便快速跳到感興趣的位置同時也可以快速的對文章內容有一個大概的瞭解。 實現原理 首先根據個人喜好,我習慣了用 h1 來做分類。所以本篇內容也主要是針對h1來提取目錄。 如何提取出來h1呢? 先來看這張圖,以獵豹瀏覽器 ...
  • 一、為什麼使用RequireJS? <script src="a.js"></script> <script src="b.js"></script> <script src="c.js"></script> <script src="b.js"></script> <script src="c.j ...
  • 個人在移動端的一些總結歸納,有新的知識點會一直更新 一.css部分 1.meta標簽 <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"/> 移動端加上這個標簽才是真正的自適應,不加的 ...
  • 1 . 相對定位relative:顧名思義,相對定位是相對於自己的位置來進行偏移,如下圖: 以盒子中心為基準,為每條邊的正方向,例: 向右移動20px : 代碼為left:20px;或者right:-20px; 向下移動20px : 代碼為top:20px;或者bottom:-20px; 2 . 絕 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...