谢谢你的解决方案。我必须使用Gstreamer管道使其工作,但我不认为Gstreamer可以直接发送到http,所以我添加了一个UDP服务器。
它与相同的HTML一起工作。
这是我的Gstreamer测试管道:
gst-launch-1.0 videotestsrc ! videoconvert ! videoscale ! video/x-raw,width=800,height=600 ! avenc_mpeg1video ! mpegtsmux name=mux ! rtpmp2tpay ! udpsink host=0.0.0.0 port=8083
更新的服务器端nodeJS
var os = require("os");
var fs = require("fs");
var http = require("http").createServer(http_handler);
var url = require("url");
var dgram = require('dgram');
var websocket = require("ws");
var server_port = 8080;
var websocket_stream_port = 8082;
var file_index_name = "index.html";
var file_css_name = "style.css";
var file_jsplayer_name = "jsmpeg.min.js";
var file_index;
var file_css;
var file_jsplayer;
var stream_name = "mystream";
var udpServer = dgram.createSocket('udp4');
udpServer.on('listening', function () {
var address = udpServer.address();
console.log('UDP server listening on ' + address.address + ':' + address.port);
});
udpServer.on('message', function (msg, rinfo) {
console.log('Received UDP message with ' + msg.length + ' bytes');
streaming_websocket.broadcast(msg);
});
udpServer.bind(8083);
var io = require("socket.io")(udpServer);
var server_ip;
var ifaces = os.networkInterfaces();
Object.keys(ifaces).forEach
(
function (ifname) {
var alias = 0;
ifaces[ifname].forEach
(
function (iface) {
if ('IPv4' !== iface.family || iface.internal !== false) {
return;
}
if (alias >= 1) {
console.log('INFO: Server interface ' + alias + ' - ' + ifname + ':' + alias, iface.address);
}
else {
server_ip = iface.address;
console.log('INFO: Server interface - ' + ifname, iface.address);
}
++alias;
}
);
}
);
http.listen
(
server_port,
function () {
console.log('INFO: ' + server_ip + ' listening to html requests on port ' + server_port);
file_index = load_file(file_index_name);
file_css = load_file(file_css_name);
file_jsplayer = load_file(file_jsplayer_name);
}
);
function http_handler(req, res) {
if (req.url == '/') {
res.writeHead(200, { "Content-Type": detect_content(file_index_name), "Content-Length": file_index.length });
res.write(file_index);
res.end();
console.log("INFO: Serving file: " + req.url);
}
else if (req.url == ("/" + file_css_name)) {
res.writeHead(200, { "Content-Type": detect_content(file_css_name), "Content-Length": file_css.length });
res.write(file_css);
res.end();
console.log("INFO: Serving file: " + req.url);
}
else if (req.url == ("/" + file_jsplayer_name)) {
res.writeHead(200, { "Content-Type": detect_content(file_jsplayer_name), "Content-Length": file_jsplayer.length });
res.write(file_jsplayer);
res.end();
console.log("INFO: Serving file: " + req.url);
}
else if (req.url == "/mystream") {
res.connection.setTimeout(0);
console.log('test');
console.log("Stream Connected: " + req.socket.remoteAddress + ":" + req.socket.remotePort);
req.on
(
"data",
function (data) {
streaming_websocket.broadcast(data);
console.log("broadcast: ", data.length);
}
);
req.on
(
"end",
function () {
console.log("local stream has ended");
if (req.socket.recording) {
req.socket.recording.close();
}
}
);
}
else {
res.end();
console.log("ERR: Invalid file request" + req.url);
}
}
io.on
(
"connection",
function (socket) {
console.log("connecting...");
socket.emit("welcome", { payload: "Server says hello" });
setInterval
(
function () {
socket.emit("server_time", { server_time: get_server_time() });
},
333
);
socket.on
(
"myclick",
function (data) {
timestamp_ms = get_timestamp_ms();
socket.emit("profile_ping", { timestamp: timestamp_ms });
console.log("button event: " + " client says: " + data.payload);
}
);
socket.on
(
"keyboard",
function (data) {
timestamp_ms = get_timestamp_ms();
socket.emit("profile_ping", { timestamp: timestamp_ms });
console.log("keyboard event: " + " client says: " + data.payload);
}
);
socket.on
(
"profile_pong",
function (data) {
timestamp_ms_pong = get_timestamp_ms();
timestamp_ms_ping = data.timestamp;
console.log("Pong received. Round trip time[ms]: " + (timestamp_ms_pong - timestamp_ms_ping));
}
);
}
);
var streaming_websocket = new websocket.Server({ port: websocket_stream_port, perMessageDeflate: false });
streaming_websocket.connectionCount = 0;
streaming_websocket.on
(
"connection",
function (socket, upgradeReq) {
streaming_websocket.connectionCount++;
console.log
(
'New websocket Connection: ',
(upgradeReq || socket.upgradeReq).socket.remoteAddress,
(upgradeReq || socket.upgradeReq).headers['user-agent'],
'(' + streaming_websocket.connectionCount + " total)"
);
socket.on
(
'close',
function (code, message) {
streaming_websocket.connectionCount--;
console.log('Disconnected websocket (' + streaming_websocket.connectionCount + ' total)');
}
);
}
);
streaming_websocket.broadcast = function (data) {
streaming_websocket.clients.forEach
(
function each(client) {
if (client.readyState === websocket.OPEN) {
console.log('sending datas');
client.send(data);
} else {
console.log('.....no')
}
}
);
};
function get_server_time() {
my_date = new Date();
return my_date.toUTCString();
}
function get_timestamp_ms() {
my_date = new Date();
return 1000.0 * my_date.getSeconds() + my_date.getMilliseconds()
}
function load_file(file_name) {
var file_tmp;
var file_path = __dirname + "/" + file_name;
try {
file_tmp = fs.readFileSync(file_path);
}
catch (err) {
console.log("ERR: " + err.code + " failed to load: " + file_path);
throw err;
}
console.log("INFO: " + file_path + " has been loaded into memory");
return file_tmp;
}
function detect_content(file_name) {
if (file_name.includes(".html")) {
return "text/html";
}
else if (file_name.includes(".css")) {
return "text/css";
}
else if (file_name.includes(".js")) {
return "application/javascript";
}
else {
throw "invalid extension";
}
}