Html5
ffmpeg 安装和常见问题
//websocket-relay.js
var fs = require('fs'),
http = require('http'),
WebSocket = require('ws');
if (process.argv.length < 3) {
console.log(
'Usage: \n' +
'node websocket-relay.js [ ]'
);
process.exit();
}
var STREAM_SECRET = process.argv[2],
STREAM_PORT = process.argv[3] || 8081,
WEBSOCKET_PORT = process.argv[4] || 8082,
HTTP_PORT = process.argv[5] || 8083,
RECORD_STREAM = false;
// Websocket Server
var socketServer = new WebSocket.Server({port: WEBSOCKET_PORT, perMessageDeflate: false});
socketServer.connectionCount = 0;
socketServer.on('connection', function (socket, upgradeReq) {
var params = upgradeReq.url.substr(1).split('/');
if (!params || params.length != 1) {
console.log("deviceId param was loss");
response.end();
}
socket.deviceId = params[0];
socketServer.connectionCount++;
console.log(
'New WebSocket Connection: ',
(upgradeReq || socket.upgradeReq).socket.remoteAddress,
(upgradeReq || 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("fda")
});
socketServer.broadcast = function (deviceId, data) {
socketServer.clients.forEach(function each(client) {
if (client.deviceId && client.deviceId == deviceId) {
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[1] !== 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(params[0], data);
if (request.socket.recording) {
request.socket.recording.write(data);
}
});
request.on('end', function () {
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);
}
})
// Keep the socket open for streaming
streamServer.headersTimeout = 0;
streamServer.listen(STREAM_PORT);
// HTTP Server to start convert shell
const express = require('express');
const bodyParser = require('body-parser');
const child_process = require('child_process');
const httpServer = express();
httpServer.use(bodyParser());
httpServer.use(bodyParser.json());
httpServer.use(bodyParser.urlencoded({extended: true}));
httpServer.killByProcessName = function (name) {
var shell = `ps aux | grep "${name}" |grep -v grep| cut -c 9-15 | xargs kill -9`;
try {
console.log("exec", shell);
var result = child_process.execSync(shell, {stdio: 'ignore'});
console.log("进程已存在", result);
} catch (e) {
console.log("进程不存在(假定只有不存在的时候才会报错)")
return false;
}
return true;
}
httpServer.get('/', function (req, res) {
res.send('摄像头服务');
});
const error_image = "data:image/jpg;base64,默认图片"
/**
抓帧
**/
httpServer.get('/snapshot', function (req, res) {
if (!req.query.deviceId || !req.query.streamUrl) {
res.json({succee: false, msg: "缺少参数"});
return;
}
try {
var frameShell = `ffmpeg -y -i "${req.query.streamUrl}" -ss 1 -frames:v 1 ./${req.query.deviceId}.jpeg`;
console.log("snapshot", frameShell);
child_process.execSync(frameShell, {stdio: 'ignore'});
let bitmap = fs.readFileSync(`./${req.query.deviceId}.jpeg`);
let base64str = Buffer.from(bitmap, 'binary').toString('base64');
res.send("data:image/jpg;base64," + base64str);
return;
} catch (e) {
console.log("在抓帧时获得异常,返回默认", e)
}
res.send(error_image);
});
httpServer.post('/camera', function (req, res) {
console.log(req.body)
if (!req.body.deviceId || !req.body.streamUrl) {
res.json({succee: false, msg: "缺少参数"});
return;
}
var exist = httpServer.killByProcessName(`http://127.0.0.1:8082/${req.body.deviceId}`);
var cmd = `ffmpeg -rtsp_transport tcp -i "${req.body.streamUrl}" -f mpegts -b:v 800k -codec:v mpeg1video -codec:a mp2 -s 640x480 -r 32 "http://127.0.0.1:8082/${req.body.deviceId}/123456/640/480/"`;
try {
child_process.exec(cmd, function (error, stdout, stderr) {
if (error) {
console.log(error)
}
console.log("error:" + error);
console.log("stdout:" + stdout);
console.log("stderr:" + stderr);
});
console.log(`添加[${req.body.deviceId}:${req.body.streamUrl}]成功!`)
} catch (e) {
console.log(`添加[${req.body.deviceId}:${req.body.streamUrl}]失败!`, e)
return res.json({succee: false, msg: "添加失败!"})
}
exist ? res.json({succee: true, msg: "已启动脚本!"}) : res.json({succee: true, msg: "已重启脚本!"});
});
httpServer.listen(HTTP_PORT);
console.log('Listening for incomming MPEG-TS Stream on http://127.0.0.1:' + STREAM_PORT + '/' );
console.log('Awaiting WebSocket connections on ws://127.0.0.1:' + WEBSOCKET_PORT + '/');
console.log('Web Api service on http://127.0.0.1:' + HTTP_PORT + '/');
"dependencies": {
"body-parser": "^1.19.0",
"child_process": "^1.0.2"
}
node websocket-relay.js 123456 8082 8084 8087
<html>
<head>
<title>JSMpeg Stream Clienttitle>
<style type="text/css">
html, body {
background-color: #111;
text-align: center;
}
style>
head>
<body>
<canvas id="video-canvas">canvas>
<script type="text/javascript" src="jsmpeg.min.js">script>
<script type="text/javascript">
var canvas = document.getElementById('video-canvas');
var url = 'ws://192.168.100.13:8084/deviceId1';
var player = new JSMpeg.Player(url, {canvas: canvas});
script>
body>
html>