如何解决电子网络流媒体
我正在尝试使用电子和 nodejs 服务器通过 networkig 流式传输我的桌面。 问题是,传输的字节没有显示为视频源。
我在底部提供了代码来重现。 请记住,这只是一些测试,tcp 服务器/客户端将被正确编码以用于生产。
node -v: v14.16.0 npm -v: 6.14.11
流媒体客户端 [index.html] (Electron):
<!DOCTYPE html>
<html>
<head>
<Meta charset="UTF-8">
<title>Hello World!</title>
<Meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body style="background: rgb(33,33,33);">
<video id="video" controls width="1280" height="720"></video>
<script>require('./index.js')</script>
</body>
</html>
流媒体客户端 [index.js] (Electron):
const { desktopCapturer,ipcRenderer } = require("electron");
desktopCapturer.getSources({types: ["window","screen"]}).then(async sources => {
for(const source of sources){
if(source.name === "Screen 1"){
try{
const stream = await navigator.mediaDevices.getUserMedia({
audio: false,video: {
mandatory: {
chromeMediaSource: 'desktop',chromeMediaSourceId: source.id,minWidth: 1280,maxWidth: 1280,minHeight: 720,maxHeight: 720,maxFrameRate: 60
}
}
});
handleStream(stream);
} catch (e){
handleError(e);
}
return;
}
}
})
function handleStream(stream){
const recorder = new MediaRecorder(stream,{mimeType: 'video/webm; codecs=vp9'});
recorder.ondataavailable = handleDataAvailable;
const video = document.querySelector("#video");
video.srcObject = stream;
video.onloadedMetadata = (e) => {
video.play();
recorder.start(2000);
}
}
function handleError(error){
console.log(error);
}
const handleDataAvailable = (event) => {
event.data.arrayBuffer().then(buffer => {
ipcRenderer.send("video-data",buffer);
})
}
流媒体客户端 [main.js] (Electron):
const { app,browserWindow,ipcMain } = require('electron')
const fs = require("fs");
const net = require("net");
const client = new net.socket();
let CLIENT_CONNECTED = false;
function createWindow () {
const win = new browserWindow({
width: 800,height: 600,webPreferences: {
nodeIntegration: true,contextIsolation: false
}
})
win.webContents.toggleDevTools();
win.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
client.connect(10000,"127.0.0.1",() => {
console.log("connected");
CLIENT_CONNECTED = true;
})
});
client.on("data",data => {
console.log(data);
});
client.on("close",() => {
console.log("client closed");
CLIENT_CONNECTED = false;
});
client.on("error",error => {
console.log(error);
CLIENT_CONNECTED = false;
});
app.on('window-all-closed',() => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate',() => {
if (browserWindow.getAllWindows().length === 0) {
createWindow()
}
})
ipcMain.on('video-data',(event,arg) => {
if(CLIENT_CONNECTED) client.write(new Buffer.from(arg).toString('base64'));
})
接收客户端 [index.js] (Electron):
const { ipcRenderer } = require("electron");
const video = document.getElementById("video");
const prefix = "data:video/webm;base64,";
ipcRenderer.on("video-data",arg) => {
video.setAttribute("src",prefix + arg);
})
接收客户端 [index.html] (Electron):
<!DOCTYPE html>
<html>
<head>
<Meta charset="UTF-8">
<title>Hello World!</title>
<Meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body style="background: rgb(33,33);">
<video id="video" controls width="1280" height="720"></video>
<script>require('./index.js')</script>
</body>
</html>
接收客户端 [main.js] (Electron):
const { app,ipcMain,ipcRenderer } = require('electron')
const fs = require("fs");
const net = require("net");
const { Readable } = require("stream");
var ipcstream = require('electron-ipc-stream')
const client = new net.socket();
let CLIENT_CONNECTED = false;
const webmReadable = new Readable();
webmReadable._read = () => { };
let win;
let ipcs;
function createWindow () {
win = new browserWindow({
width: 800,contextIsolation: false
}
});
ipcs = new ipcstream('video-data',win)
win.webContents.toggleDevTools();
win.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
client.connect(10000,() => {
console.log("connected");
CLIENT_CONNECTED = true;
})
webmReadable.on("data",data => {
win.webContents.send("video-data",Buffer.from(data).toString("base64"));
})
});
client.on("data",data => {
const buffer = Buffer.from(data);
console.log(buffer.length);
webmReadable.push(buffer);
});
client.on("close",() => {
if (browserWindow.getAllWindows().length === 0) {
createWindow()
}
})
节点js tcp服务器:
const net = require("net");
const server = net.createServer();
const process = require("process");
let sockets = [];
let buffers = [];
process.on("SIGINT",() => {
console.log(buffers);
})
const handleConnect = (socket) => {
sockets.push(socket);
buffers.push({socket: socket,buffer: []})
socket.on("data",data => handleData(socket,data));
socket.on("error",error => handleError(socket,error));
socket.on("close",() => handleClose(socket));
socket.on("end",() => handleEnd(socket));
socket.on("drain",() => handleDrain(socket));
socket.on("lookup",() => handleLookup(socket));
socket.on("timeout",() => handleTimeout(socket));
}
const handleData = (socket,data) => {
broadcast(socket,data);
// buffers.forEach(s => {
// if(s.socket == socket){
// // console.log("socket gefunden,daten werden gespeichert");
// // let buf = Buffer.from(data);
// // s.buffer.push(buf);
// }
// })
}
const handleError = (socket,error) => {
const index = sockets.indexOf(socket);
sockets.splice(index,1);
console.error(error);
}
const handleClose = (socket) => {
const index = sockets.indexOf(socket);
sockets.splice(index,1);
console.log("client closed");
}
const handleEnd = (socket) => {
console.log("client ended");
}
const handleDrain = (socket) => {
}
const handleLookup = (socket) => {
console.log("client lookup");
}
const handleTimeout = (socket) => {
const index = sockets.indexOf(socket);
sockets.splice(index,1);
console.log("client timeout");
}
const broadcast = (sender,data) => {
sockets.forEach(socket => {
if(socket !== sender) socket.write(data);
})
}
server.on("connection",socket => handleConnect(socket));
server.listen(10000,"127.0.0.1");
非常感谢,希望你能帮助我。
附言我已经尝试过 ffmpeg,我无法获得正确的输出质量(并且流根本不起作用),所以我认为我会使用 Electron desktopCapturer,因为我无论如何都想构建一个电子应用程序。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。