Custom netplay implementation #658
Replies: 4 comments 20 replies
-
I really like this method of doing netplay. I have a question how is the audio captured? This is a cool project, I think this would be an awesome client to replace linuxserver.io docker image. If you would be ok with that. Another thing is how are the delays and what are the draw backs of always depending on the host. Like what is the extra performance on the host that is needed? I think the server code would need to be written in node.js but that would be not too hard. Do you have discord? If so would you mind joining the server for easier communication and collaboration. |
Beta Was this translation helpful? Give feedback.
-
I've tried netplay from this angle, but it's never really turned out well, er, worked. My other concerns are latency and bandwidth. I have a goal for netplay to be optimized as much as possible, to be playable on 3G speeds, and to not have to have the worry of any data cap, which is why I haven't gone the approach of streaming the video. Our current take on netplay is this. We're planning on basically reverse engineering how netplay works in retroarch and putting it in here. I think the main issue was that game state prediction is unimplimented at the moment, after that we should be able to optimize latency and delay as much as possible, the same way retroarch does it. @allancoding is assigned with this task, and I got no clue where the progress is at. Now my question, how did you get an audio stream again? I've tried and tried but I've never been able to get an audio stream. Could you try recording it with a mediarecorder? Because that's my current goal that I haven't been able to accomplish |
Beta Was this translation helpful? Give feedback.
-
About audio capture. It's code here: https://github.com/n-at/playtime/blob/master/assets/netplay.js#L394 AL exposes
function collectMediaTracks() {
let videoTrack = null;
const videoTracks = document.querySelector(`${window.EJS_player} canvas`).captureStream().getVideoTracks();
if (videoTracks.length !== 0) {
videoTrack = videoTracks[0];
} else {
console.error('Unable to capture video stream');
return null;
}
let audioTrack = null;
if (window.AL && window.AL.currentCtx && window.AL.currentCtx.audioCtx) {
const alContext = window.AL.currentCtx;
const audioContext = alContext.audioCtx;
const gainNodes = [];
for (let sourceIdx in alContext.sources) {
gainNodes.push(alContext.sources[sourceIdx].gain);
}
const merger = audioContext.createChannelMerger(gainNodes.length);
gainNodes.forEach(node => node.connect(merger));
const destination = audioContext.createMediaStreamDestination();
merger.connect(destination);
const audioTracks = destination.stream.getAudioTracks();
if (audioTracks.length !== 0) {
audioTrack = audioTracks[0];
}
}
const stream = new MediaStream();
if (videoTrack && videoTrack.readyState === 'live') {
stream.addTrack(videoTrack);
}
if (audioTrack && audioTrack.readyState === 'live') {
stream.addTrack(audioTrack);
}
return stream;
}
setTimeout(() => {
const chunks = [];
const recorder = new MediaRecorder(collectMediaTracks());
recorder.addEventListener('dataavailable', e => {
chunks.push(e.data);
});
recorder.addEventListener('stop', () => {
const blob = new Blob(chunks);
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'video.webm';
a.click();
});
recorder.start();
setTimeout(() => { recorder.stop()}, 10000);
}, 5000); And this video been recorded: video.webmVideo looks fine but the game canvas refresh rate reduced to 1-2 FPS during recording. Maybe the canvas should not be captured directly (for example use another invisible canvas of fixed size and paint game canvas image on it). |
Beta Was this translation helpful? Give feedback.
-
I also like this method of netplay, and some friend of mine & me have made a similar solution in the past (albiet much much more crude lol as it was meant for only about 4 of us), but without webRTC (due to complications) Was very little compared to this |
Beta Was this translation helpful? Give feedback.
-
I've created a simple retro game library with built-in ability to play with EmulatorJS and built-in netplay: https://github.com/n-at/playtime
On the user's side, netplay works like this:
Game host uploads a game and enables netplay in the game settings:
The game host starts the game and opens the netplay menu. There are link and QR code that can be shared with other players. No registration is required to join:
Other players (clients) start as a spectators and cannot yet control the game. The game host can assign their player id (i.e. controller number):
Players (clients) in the netplay menu can also change their display names:
On the technical side, netplay is implemented using WebSocket and WebRTC:
AL
gain nodes. Stream is one-directional: from the game host to clients.Maybe this can be helpful for an official netplay implementation.
Beta Was this translation helpful? Give feedback.
All reactions