测试
测试摄像头是否可用
fswebcam这是一款小型摄像头程序。首先来安装它
sudo apt install fswebcam
然后进入设备目录查看电脑配置的摄像头
cd /dev/
ls video*
我的电脑只有一个摄像头viedo0
输入以下代码可以抓取摄像头画面,我将它保存在了用户目录的图片里
fswebcam --device /dev/video0 ~/图片/001.jpeg
以上就完成了利用fswebcam抓取当前图像
测试摄像头能否抓取当前视频信息
首先安装ffmpeg(FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。)
然后修改ffserver的配置文件,创建一个文件夹,在里面创建一个名为ffserver.conf的文件,把以下内容复制进去:
HTTPPort 8090
HTTPBindAddress 0.0.0.0
MaxHTTPConnections 100
MaxClients 10
MaxBandwidth 7000
CustomLog -
######### Definition of the live feeds #########
<Feed feed1.ffm>
File /tmp/feed1.ffm
FileMaxSize 200K
ACL allow 192.168.43.0 192.168.43.255
</Feed>
######### Definition of the stream #########
<Stream test1.mpg>
Feed feed1.ffm
Format mpeg
VideoBitRate 200
VideoBufferSize 40
VideoFrameRate 25
VideoSize 320x240
VideoGopSize 12
VideoCodec mpeg1video
NoAudio
ACL allow 192.168.0.0 192.168.255.255
</Stream>
######### stat.html #########
<Stream stat.html>
Format status
ACL allow 192.168.0.0 192.168.255.255
ACL allow 127.0.0.1
</Stream>
输入:ffserver -f ~/ffserver/ffserver.conf
然后打开浏览器输入以下:localhost:8090/stat.html 此时网页变成如下样式
然后输入
ffmpeg -i /dev/video http://localhost:8090/feed1.ffm
可以观察到网页内容有细微变化,下面出现RECEIVE_DATA字样。
它表示正在接收摄像头传输的数据,然后输入以下命令:
ffplay -v info -i http://localhost:8090/test1.mpg
此时第一阶段任务完成,我们可以看到实时的视频内容,视频会出现一定延迟。此时只证明可以从电脑端看到视频信息。然后我们可以关掉ffplay这个终端,接下来是让是让视频能够在网页上播放
将视频搬到网页上
创建一个client文件夹
因为要播放视频所以要把jsmpeg.min.js库放在里面。里面的index.html内容如下:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="jsmpeg.min.js"></script>
<title>title</title>
</head>
<body>
<h1>Demo</h1>
<canvas id="video-canvas"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("video-canvas");
var url = "ws://" + document.location.hostname + ":8082/";
var player = new JSMpeg.Player(url, {canvas: canvas});
</script>
</body>
</html>
安装websocket
它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
首先输入如下命令来安装websocket
npm init
npm install ws@2.3.1
[cat package.json]
创建一个websocket文件夹
里面的websocket-relay.js文件写入如下:
// Use the websocket-relay to serve a raw MPEG-TS over WebSockets. You can use
// ffmpeg to feed the relay. ffmpeg -> websocket-relay -> browser
// Example:
// node websocket-relay yoursecret 8081 8082
// ffmpeg -i <some input> -f mpegts http://localhost:8081/yoursecret
var fs = require('fs'),
http = require('http'),
WebSocket = require('ws');
if (process.argv.length < 3) {
console.log(
'Usage: \n' +
'node websocket-relay.js <secret> [<stream-port> <websocket-port>]'
);
process.exit();
}
var STREAM_SECRET = process.argv[2],
STREAM_PORT = process.argv[3] || 8081,
WEBSOCKET_PORT = process.argv[4] || 8082,
RECORD_STREAM = false;
// Websocket Server
var socketServer = new WebSocket.Server({port: WEBSOCKET_PORT, perMessageDeflate: false});
socketServer.connectionCount = 0;
socketServer.on('connection', function(socket) {
socketServer.connectionCount++;
console.log(
'New WebSocket Connection: ',
socket.upgradeReq.socket.remoteAddress,
socket.upgradeReq.headers['user-agent'],
'('+socketServer.connectionCount+' total)'
);
socket.on('close', function(code, message){
socketServer.connectionCount--;
console.log(
'Disconnected WebSocket ('+socketServer.connectionCount+' total)'
);
});
});
socketServer.broadcast = function(data) {
socketServer.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
};
// HTTP Server to accept incomming MPEG-TS Stream from ffmpeg
var streamServer = http.createServer( function(request, response) {
var params = request.url.substr(1).split('/');
if (params[0] !== STREAM_SECRET) {
console.log(
'Failed Stream Connection: '+ request.socket.remoteAddress + ':' +
request.socket.remotePort + ' - wrong secret.'
);
response.end();
}
response.connection.setTimeout(0);
console.log(
'Stream Connected: ' +
request.socket.remoteAddress + ':' +
request.socket.remotePort
);
request.on('data', function(data){
socketServer.broadcast(data);
if (request.socket.recording) {
request.socket.recording.write(data);
}
});
request.on('end',function(){
console.log('close');
if (request.socket.recording) {
request.socket.recording.close();
}
});
// Record the stream to a local file?
if (RECORD_STREAM) {
var path = 'recordings/' + Date.now() + '.ts';
request.socket.recording = fs.createWriteStream(path);
}
}).listen(STREAM_PORT);
console.log('Listening for incomming MPEG-TS Stream on http://127.0.0.1:'+STREAM_PORT+'/<secret>');
console.log('Awaiting WebSocket connections on ws://127.0.0.1:'+WEBSOCKET_PORT+'/');
输入命令
进入websocket文件夹,打开终端输入如下命令:
node websocket-relay.js <secret>
(secret中随便写几个数字用来识别。)
再打开一个新的终端输入以下命令;
ffmpeg -i http://localhost:8090/test1.mpg -f mpegts -vcodec mpeg1video http://localhost:8081/<secret>
最后进入创建的client文件夹里打开终端输入http-server就可以刷新网页看到视频了。
接下来要使服务器端和客户端连接起来,并且通过客户端的操作,使服务端能够打印出消息。所以我们需要再创建一个文件夹(服务器端)分别来存放控制台代码,并且在客户端里写入相应的请求。
将客户端与服务器端连接起来
客户端(client)
我要实现的功能:
设置四个按钮(上下左右),通过点击按钮在控制台输出点击的方向(上下左右)和时间长度
所以这里要用到jquery里的post(post() 方法通过 HTTP POST 请求从服务器载入数据。),所以要安装jquery,还要在client文件夹里放入一个”jquery-3.3.1.min.js”的文件。
文件代码如下(这里只写一个按钮):
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>title</title>
<script src="jquery-3.3.1.min.js"></script>
<script src="jsmpeg.min.js"></script>
<style>
#up{
position:absolute;
left:180px;
top:50px;
}
</style>
</head>
<body>
<h1>Demo</h1>
<div><button type="button" class="btn" id="up">Up</button></div>
<div><canvas id="video-canvas"></canvas></div>
<script type="text/javascript">
var canvas = document.getElementById("video-canvas");
var url = "ws://" + document.location.hostname + ":8082/";
var player = new JSMpeg.Player(url, {canvas: canvas});
</script>
<script type="text/javascript">
var up1 = new Date();
var up_d = new Date();
var upButton = document.getElementById('up');
upButton.onmousedown = function(){
up1 = new Date();
}
upButton.onmouseup = function(){
var up2 = new Date();
up_d=up2-up1;
$.post("127.0.0.1:3000/test",
{
direction: "up",
range: up_d
});
}
</script>
</body>
</html>
服务器端(jquery-server)
再创建一个名为jquery-server的文件夹,里面的index.js里写入如下代码:
const express = require('express');
var bodyParser = require('body-parser');
const app = express()
app.use(bodyParser.urlencoded({extended:false}))
app.post('/test',function(request,response){
var direction = request.body.direction;
var duration = request.body.range;
console.log("direction:"+direction+", duration:"+duration);
});
});
app.listen(3000)
连接
在jquery-server文件夹里打开终端输入:node index.js 在client文件夹里打开终端输入:http-server
打开网页刷新并且点击按钮就可以在控制台看到输出的信息了。
问题
一.
内容:我们打开chrome,点击网页按钮,发现只能点击六次,之后再点击就无法输出信息了,同时换用火狐浏览器发现只能点击九次。
原因:客户端发送请求给服务器,而服务器端没有做出回应导致客户端不再发送请求,也就无法打印信息。
解决方法: 在post里面返回响应,加入 response.send(“OK”);这一句就好了。
二.
内容: 火狐浏览器运行没有报错,但是谷歌显示出现了Access-Control-Allow-Origin,也就是跨域问题。
原因:端口不同导致的
解决办法:依然在post里加入一句: response.header(‘Access-Control-Allow-Origin’, ‘*’);
以上只是按照自己的理解暂时编辑,之后在进行补充。