JS打開攝像頭並截圖上傳


直入正題,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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM