最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript實現(xiàn)網(wǎng)頁端播放攝像頭實時畫面

 更新時間:2022年02月23日 09:25:26   作者:莫問哥哥  
這篇文章主要介紹了如何利用JavaScript實現(xiàn)在網(wǎng)頁端播放局域網(wǎng)(不能上云)或是廣域網(wǎng)的攝像頭的實時畫面,文中的示例代碼講解詳細,需要的可以參考一下

初衷

寫這篇博客已經(jīng)是項目過去很久了,之所以寫是因為當(dāng)時被這個問題為難了很久。我原本是做后端的,涉及到前端的東西,當(dāng)時是兩眼一黑。好在最后還是解決了。當(dāng)相信這個內(nèi)容還是有價值的,所以今天整理出來,幫助未來可能需求的人。

應(yīng)對的場景

希望在自己的Web應(yīng)用中播放局域網(wǎng)(不能上云),或是廣域網(wǎng)的攝像頭實時畫面。

涉及到的范圍

  • Nodejs 以及 Express
  • WebSocket html頁面拉流
  • ffmpeg 推流用
  • node-rtsp-stream 主要依賴這個東西,將 rtsp 流推送到 Ws
  • JSMpeg 主要用來播放 ws 流畫面

這個解決方案是全前端方案,所以后端的流處理都是用Node處理的。

解決問題的思路

  • 首先要拿到攝像頭的播放Rtsp通道。(有些是帶密碼的,有些不帶密碼)。
  • 使用ffmpeg將rtsp流轉(zhuǎn)成ws流。
  • 當(dāng)客戶端請求播放攝像頭畫面的時候,Node接受請求,并將流地址返回給前端。
  • 前端使用 JSMpeg 去播放ws流,畫面呈現(xiàn)。
  • 閉關(guān)的時候,仍然請求后端,用Node處理。閉關(guān)推流進程。

攝像頭的Rtsp地址

因為這里沒有攝像頭,所以我在網(wǎng)上搜索了一個流地址:

  rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov'

如果電腦中裝了 VCL,則可以使用VCL的流地址播放功能去播放,這里我就不做演示了。

ffmpeg 下載,安裝,配置環(huán)境變量

這里我在gitHub上找到了一個ffmepg下載地址 ,這個版本是windows版本的。

安裝就不用說了,下一步,下一步即可,最后就說配置環(huán)境變量。其作用就是在命令行狀態(tài)下可以直接通過 ffmpeg 訪問到文件。

nodejs 和 Express

nodejs 我就不詳細介紹了,express也一樣,這兩個東西要是不會,這篇文章也就不用看了。

然后就是寫代碼接受前端到http請求了。可以參考博客園里面的express介紹。稍后我會貼出代碼,建議看看文檔。

Express參考

接受請求的代碼

var express = require('express');
const requestmanager = require('../lib/RequestManager')
var router = express.Router();

router.get('/', function (req, res) {
    res.send('Carmeras Server is Runing...');
});

/* GET users listing. */
router.post('/', function (req, res) {
    var cfg = req.body
    let result = new requestmanager().Open(cfg)
    res.json(result)
});

router.post('/close', function (req, res) {
    var cfg = req.body
    new requestmanager().Close(cfg)
    res.json({ state: 'close the rtsp stream success.' })
})

這里用到了 node-rtsp-stream 、express 、express.Router 還引用了一個 RequestManager,這是我自己寫的一個管理請求的包,代碼如下:

const Stream = require('node-rtsp-stream')
const os = require('os');
///獲取本機ip///
function getIPAdress() {
    var interfaces = os.networkInterfaces();
    for (var devName in interfaces) {
        var iface = interfaces[devName];
        for (var i = 0; i < iface.length; i++) {
            var alias = iface[i];
            if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
                return alias.address;
            }
        }
    }
}
const args = []
const requestManager = function () { }
//這里是在原型上加上打開和關(guān)閉兩個方法
requestManager.prototype = {
    Open: function (arg) {
        let result = {}
        if (args.length == 0) {
            result = this._create(arg)
            result = this._openVideo(result)
        } else {
            args.forEach(a => {
                if (a.rtspUrl == arg.rtspUrl) {
                    result = a
                }
            })
            if (result.port === undefined || result.rtspUrl === undefined) {
                result = this._create(arg)
                result = this._openVideo(result)
            }
        }
        result = Object.assign(result,{url:`ws:\\${getIPAdress()}:${result.port}`})
        return result;
    },
    Close: function (arg) {
        let result = {}
        let idx = -1
        idx = args.findIndex(a => a.rtspUrl == arg.rtspUrl)
        if (idx !== -1) {
            args[idx].stream.stop()
            result = args.splice(idx, 1)
        } else {

        }
        console.log(args)
        return result
    },
    //這里是產(chǎn)生一個隨機端口號,用來推流使用。
    _randomPort: function () {
        let port = Math.floor(Math.random() * (4001 - 3001) + 3001)
        return port
    },
    //這里是核心推流代碼,其實很簡單。
    _openVideo: function (arg) {
        arg.stream = new Stream({
            name: 'name',
            //streamUrl: 'rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov',
            streamUrl: arg.rtspUrl,
            wsPort: arg.port,
            ffmpegOptions: { // options ffmpeg flags
                '-stats': '', // an option with no neccessary value uses a blank string
                '-r': 30, // options with required values specify the value after the key
                '-s': arg.size,
                '-codec:a': 'mp2',
                '-ar': 44100,
                '-ac': 1,
                '-b:a': '128k'
            }
        })
        return arg
    },
    //這里創(chuàng)建參數(shù)。
    _create: function (arg) {
        let target = {
            rtspUrl: 'rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov',
            port: this._randomPort(),
            size: '1024*768',
            stream: null
        }
        let source = {
            rtspUrl: arg.rtspUrl,
            port: this._randomPort(),
            size: arg.size,
            stream: null
        }
        Object.assign(target, source)
        args.push(target)
        return target
    }

}

module.exports = requestManager

當(dāng) Open方法被調(diào)用的時候,node-rtsp-stream會調(diào)用 ffmepg 程序開始推流。其參數(shù)如下:

 ffmpegOptions: { // options ffmpeg flags
                '-stats': '', // an option with no neccessary value uses a blank string
                '-r': 30, // options with required values specify the value after the key
                '-s': arg.size,
                '-codec:a': 'mp2',
                '-ar': 44100,
                '-ac': 1,
                '-b:a': '128k'
            }

這里關(guān)注 -s 它是設(shè)置畫幅大小的。所以我這里用到了參數(shù) arg.size。帶_(下劃線)的方法內(nèi)部使用。 關(guān)鍵位置都給了注視了,一般應(yīng)該是看的懂了。

JSMpeg 播放 和請求打開關(guān)閉

這是個第三方庫,在gitee和gitHub上都有,這里列出Gitee上的地址JSMpeg我用到的關(guān)鍵代碼就幾句

 /*初始化并播放*/
 let player = new JSMpeg.Player(url, opt);
 /*銷毀關(guān)閉*/
 player.destroy()

至于請求,可以用axios 或是 jquery庫,我這里用的是 jquery

       var player
        //關(guān)閉
        function closeStream() { 
            $.post("http://127.0.0.1:3000/cameras/close/", { rtspUrl: $('#rtsp').val() }, function (result) {
                player.destroy()
            })
        }

        //打開
        function start() { 
            var rstp = $('#rtsp').val() 
            var size = $('#size').val()
            $.post("http://127.0.0.1:3000/cameras/", { rtspUrl:rstp, size:  size }, function (result) {  
                var url = "ws://127.0.0.1:" + result.port;
                var canvas = document.getElementById('video-canvas');
                let opt = {
                    canvas: canvas,
                    poster: "0.jpg",
                }
                player = new JSMpeg.Player(url, opt);
            })

        }

完整的Html如下:

<!DOCTYPE html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>DEMO node-rtsp-stream-jsmpeg</title>
    <script src="https://jsmpeg.com/jsmpeg.min.js"></script>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

    <style type="text/css">
        html,
        body {

            text-align: center;
        }

        input[type='text'] {
            width: 450px;
        }
    </style>
</head>

<body>
    <div>
        <!-- <span>rtsp : <input type="text" name="rtsp" id="rtsp"  value="rtsp://admin:xcs123456@192.168.3.11:554/h264/ch1/main/av_stream"></span><br /> -->
        <span>rtsp : <input type="text" name="rtsp" id="rtsp"  value="rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"></span><br />
               
        <span>rtsp : <input type="text" name="size" id="size" value="1024*768"></span><br />
        <canvas id="video-canvas">
        </canvas><br />

        <input type="button" value="Start Stream" onclick="start()">
        <input type="button" value="Close Stream" onclick="closeStream()">
    </div>

 
    <script type="text/javascript">
        var player

        function closeStream() { 
            $.post("http://127.0.0.1:3000/cameras/close/", { rtspUrl: $('#rtsp').val() }, function (result) {
                player.destroy()
            })
        }


        function start() { 
            var rstp = $('#rtsp').val() 
            var size = $('#size').val()
            $.post("http://127.0.0.1:3000/cameras/", { rtspUrl:rstp, size:  size }, function (result) {  
                var url = "ws://127.0.0.1:" + result.port;
                var canvas = document.getElementById('video-canvas');
                let opt = {
                    canvas: canvas,
                    poster: "0.jpg",
                }
                player = new JSMpeg.Player(url, opt);
            })

        } 
    </script> 
</body>

以上就是全部的內(nèi)容,完整代碼可以到gitee上下載。

以上就是JavaScript實現(xiàn)網(wǎng)頁端播放攝像頭實時畫面的詳細內(nèi)容,更多關(guān)于JavaScript攝像頭實時畫面的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • ko knockoutjs動態(tài)屬性綁定技巧應(yīng)用

    ko knockoutjs動態(tài)屬性綁定技巧應(yīng)用

    ko的動態(tài)屬性是指,ViewModel不確定的屬性,而后期卻需要的屬性,本文將詳細介紹,需要的朋友參考下
    2012-11-11
  • JavaScript簡單生成 N~M 之間隨機數(shù)的方法

    JavaScript簡單生成 N~M 之間隨機數(shù)的方法

    這篇文章主要介紹了JavaScript簡單生成 N~M 之間隨機數(shù)的方法,結(jié)合自定義函數(shù)分析了JS生成固定區(qū)間內(nèi)隨機數(shù)的相關(guān)操作技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2017-01-01
  • 頁面使用密碼保護代碼

    頁面使用密碼保護代碼

    這是一個由JS實現(xiàn)的網(wǎng)頁密碼保護代碼,在進入網(wǎng)頁前需要在彈出框中輸入密碼才可以,不過現(xiàn)在不怎么用了,一般情況下,目前都在后臺處理這種功能,用戶輸入用戶名和密碼后交給服務(wù)器處理,然后再返回信息,若登錄無誤就可看到某些內(nèi)容
    2013-04-04
  • 微信小程序?qū)崿F(xiàn)滑動刪除

    微信小程序?qū)崿F(xiàn)滑動刪除

    這篇文章主要為大家詳細介紹了微信小程序?qū)崿F(xiàn)滑動刪除,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • Electron 使? electron-builder 打包應(yīng)用過程詳解

    Electron 使? electron-builder 打包應(yīng)用過程詳解

    Electron應(yīng)用開發(fā)中,electron-builder是一個常用的打包工具,提供了多種自定義配置,不過,使用npm安裝electron-builder時可能會遇到下載依賴慢或失敗的問題,本文給大家介紹Electron 使? electron-builder 打包應(yīng)用的相關(guān)操作,感興趣的朋友一起看看吧
    2024-10-10
  • JavaScript實現(xiàn)獲得所有兄弟節(jié)點的方法

    JavaScript實現(xiàn)獲得所有兄弟節(jié)點的方法

    這篇文章主要介紹了JavaScript實現(xiàn)獲得所有兄弟節(jié)點的方法,實例分析了javascript節(jié)點遍歷的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • 使用javascript實現(xiàn)一個在線RGB顏色轉(zhuǎn)換器

    使用javascript實現(xiàn)一個在線RGB顏色轉(zhuǎn)換器

    目前已經(jīng)有很多網(wǎng)頁版在線小工具,之前很多窗體化的工具也逐漸網(wǎng)頁化,比如:PS畫圖軟件,也都能直接網(wǎng)頁化進行設(shè)計,由于自己實際項目經(jīng)常會用到顏色轉(zhuǎn)換,所以直接自己開發(fā)個簡單版的在線顏色轉(zhuǎn)換小工具,需要的朋友可以參考下
    2024-01-01
  • 微信小程序?qū)崿F(xiàn)簡單倒計時功能

    微信小程序?qū)崿F(xiàn)簡單倒計時功能

    這篇文章主要為大家詳細介紹了微信小程序?qū)崿F(xiàn)簡單倒計時功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Bootstrap CSS組件之大屏幕展播

    Bootstrap CSS組件之大屏幕展播

    這篇文章主要介為大家詳細紹了Bootstrap CSS組件之大屏幕展播的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • Javascript中JSON數(shù)據(jù)分組優(yōu)化實踐及JS操作JSON總結(jié)

    Javascript中JSON數(shù)據(jù)分組優(yōu)化實踐及JS操作JSON總結(jié)

    這篇文章主要介紹了Javascript中JSON數(shù)據(jù)分組優(yōu)化實踐,文中還對JS操作JSON的要領(lǐng)做了總結(jié),需要的朋友可以參考下
    2017-12-12

最新評論

古交市| 孝昌县| 绵阳市| 洪泽县| 石柱| 中西区| 隆德县| 双城市| 横峰县| 兴宁市| 集安市| 福州市| 鹤庆县| 尉氏县| 公安县| 海林市| 桑日县| 山阳县| 北辰区| 略阳县| 丰宁| 黎城县| 邹平县| 平江县| 新密市| 黄龙县| 罗源县| 岳普湖县| 富锦市| 盐亭县| 内丘县| 乐清市| 清河县| 平乡县| 邻水| 建湖县| 兴城市| 调兵山市| 长垣县| 彭阳县| 枞阳县|