Merge pull request #92 from williamhackett0/master

AMD Encoder Fixes + General Improvements.
This commit is contained in:
DevL0rd 2022-12-23 21:16:22 +07:00 committed by GitHub
commit b7cdaf7953
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 4380 additions and 53 deletions

View file

@ -1,16 +1,15 @@
# SkyNX
Stream your PC games to your Nintendo Switch without Android! Now on the Homebrew App Store!
# SkyNX+
[Downloads are here](https://github.com/DevL0rd/SkyNX/releases).
This is a modfied version of SkyNX which fixes the AMD encoder issues currently present on the main branch. Also includes more user input for vsync options and allows you to specify a monitor when setting the resolution to 720p (This issue appears in multi-monitor setups). SkyNX allows you to stream your PC games to your Nintendo Switch without Android! Now on the Homebrew App Store!
Also, if you can help, I'm currently looking for a job. If you have any leads, let me know at SkyNxApp@gmail.com.
For compatilibility reasons run this as an admin! Let me know if there's any issues with NVIDIA / Intel encoders as I can only test with AMD / CPU.
[Video Instructions / Review Here](https://www.youtube.com/watch?v=YtnIqVdYbf4).
[NEW Downloads are here](https://github.com/williamhackett0/SkyNX/releases).
[Old Downloads are here](https://github.com/DevL0rd/SkyNX/releases).
If your interested in using SkyNX to turn your Nintendo Switch into a WiiU gamepad using Cemu. Here is a link with my tutorial on how to set it up! [Nintendo Switch as a WiiU Gamepad](https://gbatemp.net/threads/how-to-use-your-switch-as-a-wiiu-game-pad-in-cemu-using-skynx.563405/)
## Set Resolution to 1280 x 720
As per user suggestions I have made a patreon and a paypal.
If you think this app is Useful, Plese consider donating to support its development. [Donate](https://www.paypal.me/SkyNX)
When this setting is enabled the resolution of the monitor specified will be changedd to 1280 x 720 allowing for smoother streaming. There exists a bug currently whereby this feature may not work when ran from specific areas in windows (Desktop etc). Try running it from Downloads / Docouments / C:/ drive.
The desktop streaming client is completely new. The Switch app however has it's roots in the original [In-Home-Switching](https://github.com/jakibaki/In-Home-Switching) app.
## Features
@ -60,7 +59,6 @@ If there is no audio playing..
1. Remove the audio driver in settings, and re-install it. If it doesn't work then try step 2.
2. Restart windows and launch it again.
## Known issues
* Currently more than 1 controller is not working, please wait for update.
@ -70,3 +68,4 @@ If there is no audio playing..
* [SwitchBrew](https://switchbrew.org/) for libNX and its ffmpeg inclusion
* [Atmosphère](https://github.com/Atmosphere-NX/Atmosphere) for being such a great Switch CFW
* [Screen Capture Recorder](https://github.com/rdp/screen-capture-recorder-to-video-windows-free) for helping us grab audio.
* [William Hackett](https://github.com/williamhackett0/SkyNX) Fixing AMD encoding bug + adding some general fixes/improvements.

View file

@ -2,7 +2,7 @@
/* GitHub: https://github.com/DevL0rd */
html {
background: transparent;
height: 100%;
height: 1200px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
border-bottom-left-radius: 8px;
@ -25,12 +25,11 @@ body {
textarea:focus, input:focus{
outline: none;
}
#content {
background: linear-gradient(to bottom, rgba(30,30,30,0.9) 0%,rgba(51,51,51,0.8) 67%,rgba(51,51,51,0.8) 100%);
height: calc(100% - 57px);
overflow: auto;
height: 100%;
width: 100%;
}
#title-bar {
@ -213,11 +212,12 @@ textarea:focus, input:focus{
position: absolute;
top: 32px;
left: 50px;
height: calc(100% - 57px);
height: 100%;
width: calc(100% - 50px);
background: rgba(50,50,50,0.5);
overflow: hidden;
}
.contentAreaScrollable{
overflow: hidden;
overflow-y: auto;

View file

@ -56,11 +56,25 @@
<div class="dropdown-menu" aria-labelledby="encodingDrop">
<a class="dropdown-item" href="javascript:setEncoding('CPU')">CPU Encoding</a>
<a class="dropdown-item" href="javascript:setEncoding('NVENC')">Nvidia Encoding</a>
<a class="dropdown-item" href="javascript:setEncoding('AMDVCE')">AMD Encoding</a>
<a class="dropdown-item" href="javascript:setEncoding('AMDVCE')">AMD Encoding (AMF)</a>
<a class="dropdown-item" href="javascript:setEncoding('AMDHEVC')">AMD Encoding (HEVC)</a>
<a class="dropdown-item" href="javascript:setEncoding('QSV')">Intel Encoding</a>
</div>
</div>
</div>
<div class="form-group">
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle btn-block" type="button" id="vsyncDrop"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Vsync (VFR)
</button>
<div class="dropdown-menu" aria-labelledby="vsyncDrop">
<a class="dropdown-item" href="javascript:setVsync('passthrough')">Passthrough</a>
<a class="dropdown-item" href="javascript:setVsync('drop')">Drop</a>
<a class="dropdown-item" href="javascript:setVsync('vfr')">VFR</a>
</div>
</div>
</div>
<div class="form-group">
<button id="startBtn" type="button" class="btn btn-dark btn-lg btn-block">Start Streamer</button>
</div>
@ -140,6 +154,10 @@
<hr />
<h2>General</h2>
<hr />
<div class="form-group">
<label for="monitorInput">Monitor ID (0, 1, etc)</label>
<input id="monitorInput" title="Typically your primary monitor is ID 0, however due to Windows stuff this isn't always the case... MUST BE A NUMBER!" type="text" class="form-control" value="0">
</div>
<div class="form-group">
<label class="switch">
<input id="autoChangeResolution" type="checkbox">

View file

@ -6,7 +6,7 @@ function connect() {
$('#startBtn').addClass('btn-danger').removeClass('btn-dark');
$("#startBtn").html("End Streamer");
running = true;
ipcRenderer.send('connect', { ip: clientSettings.ip, q: clientSettings.quality, disableVideo: clientSettings.disableVideo, disableAudio: clientSettings.disableAudio, abxySwap: clientSettings.abxySwap, encoding: clientSettings.encoding, limitFPS: clientSettings.limitFPS, mouseControl: clientSettings.mouseControl });
ipcRenderer.send('connect', { ip: clientSettings.ip, q: clientSettings.quality, disableVideo: clientSettings.disableVideo, disableAudio: clientSettings.disableAudio, abxySwap: clientSettings.abxySwap, encoding: clientSettings.encoding, limitFPS: clientSettings.limitFPS, mouseControl: clientSettings.mouseControl, vsync: clientSettings.vsync, monitorID: clientSettings.monitorID});
}
function disconnect() {
$("#startBtn").addClass('btn-dark').removeClass('btn-danger');
@ -16,7 +16,7 @@ function disconnect() {
}
function restart() {
if (running) {
ipcRenderer.send('restart', { ip: clientSettings.ip, q: clientSettings.quality, disableVideo: clientSettings.disableVideo, disableAudio: clientSettings.disableAudio, abxySwap: clientSettings.abxySwap, encoding: clientSettings.encoding, limitFPS: clientSettings.limitFPS, mouseControl: clientSettings.mouseControl });
ipcRenderer.send('restart', { ip: clientSettings.ip, q: clientSettings.quality, disableVideo: clientSettings.disableVideo, disableAudio: clientSettings.disableAudio, abxySwap: clientSettings.abxySwap, encoding: clientSettings.encoding, limitFPS: clientSettings.limitFPS, mouseControl: clientSettings.mouseControl, vsync: clientSettings.vsync, monitorID: clientSettings.monitorID});
}
}
$('#startBtn').click(function () {

View file

@ -32,6 +32,9 @@ function initSettings() {
if (!clientSettings.hasOwnProperty("ip")) {
clientSettings.ip = "0.0.0.0";
}
if (!clientSettings.hasOwnProperty("monitorID")) {
clientSettings.monitorID = "0";
}
if (!clientSettings.hasOwnProperty("quality")) {
clientSettings.quality = 5;
}
@ -62,6 +65,9 @@ function initSettings() {
if (!clientSettings.hasOwnProperty("autoStartup")) {
clientSettings.autoStartup = false;
}
if (!clientSettings.hasOwnProperty("vsync")) {
clientSettings.vsync = "vfr";
}
applyClientSettings();
}
@ -90,16 +96,38 @@ function applyClientSettings() {
ipcRenderer.send("autoChangeResolutionOff")
}
$("#ipInput").val(clientSettings.ip);
$("#monitorInput").val(clientSettings.monitorID);
if (clientSettings.encoding == "NVENC") {
$("#encodingDrop").html("Encoding (Nvidia)");
} else if (clientSettings.encoding == "AMDVCE") {
$("#encodingDrop").html("Encoding (AMD)")
} else if (clientSettings.encoding == "QSV") {
$("#encodingDrop").html("Encoding (AMD amf)")
}
else if (clientSettings.encoding == "AMDHEVC")
{
$("#encodingDrop").html("Encoding (AMD hevc)")
}
else if (clientSettings.encoding == "QSV") {
$("#encodingDrop").html("Encoding (Intel)");
} else {
$("#encodingDrop").html("Encoding (CPU)");
clientSettings.encoding = "CPU";
}
//Vsync options
switch(clientSettings.vsync)
{
case "passthrough":
$("#vsyncDrop").html("Vsync (Passthrough)")
break
case "drop":
$("#vsyncDrop").html("Vsync (Drop)")
break
case "vfr":
$("#vsyncDrop").html("Vsync (VFR)")
break
}
if (clientSettings.mouseControl == "ANALOG") {
$("#mouseControlDrop").html("Mouse Control (Analog)");
} else if (clientSettings.mouseControl == "GYRO") {
@ -193,6 +221,12 @@ $(document).on('input', '#ipInput', function () {
clientSettings.ip = $(this).val();
saveClientSettings();
});
$(document).on('input', '#monitorInput', function () {
clientSettings.monitorID = $(this).val();
saveClientSettings();
});
$("#disableVideo").on('change', function () {
clientSettings.disableVideo = $("#disableVideo").prop("checked");
if (running) {
@ -245,6 +279,17 @@ function setEncoding(encoding) {
saveClientSettings();
applyClientSettings();
}
function setVsync(vsync)
{
clientSettings.vsync = vsync;
if (running) {
restart();
}
saveClientSettings();
applyClientSettings();
}
function setMouseControl(mouseControl) {
clientSettings.mouseControl = mouseControl;
if (running) {

View file

@ -18,7 +18,8 @@ var ansi_up = new AU.default;
let mainWindow
var minimizeToTray = false;
var autoChangeResolution = false;
var ip = "0.0.0.0"
var ip = "0.0.0.0";
var monitorID = "0";
var quality = 5;
var hidStreamClient = null;
var usingVideo = true;
@ -26,6 +27,7 @@ var usingAudio = true;
var abxySwap = false;
var limitFPS = false;
var encoding = "CPU";
var vsync = "vfr";
var screenWidth = 1280;
var screenHeight = 720;
var screenScale = 1;
@ -57,10 +59,10 @@ function createWindow() {
// height: mainWindowState.height,
show: true,
width: 500,
height: 320,
height: 400,
frame: false,
transparent: true, // needed for windows rounded edges
resizable: false,
resizable: true,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
@ -160,7 +162,7 @@ ipcMain.on('autoChangeResolutionOn', (event, fullMessage) => {
function changeScreenRes(width, height) {
var df = __dirname + "\\lib\\ChangeScreenResolution.exe"
exec(df + " /w=" + width + " /h=" + height + " /d=0");
exec(df + " /w=" + width + " /h=" + height + " /d=" + monitorID);
screenWidth = width;
screenHeight = height;
}
@ -211,19 +213,32 @@ function startStreamer() {
var bitrate = quality * 1024;
bitrate = bitrate + "k";
console.log(bitrate)
if (encoding == "NVENC") {
ffmpegVideoArgs = ["-probesize", "32", "-hwaccel", "auto", "-y", "-f", "gdigrab", "-framerate", fps, "-vsync", "vfr", "-video_size", screenWidth + "x" + screenHeight, "-offset_x", "0", "-offset_y", "0", "-draw_mouse", "1", "-i", "desktop", "-c:v", "h264_nvenc", "-gpu", "0", "-rc", "vbr", "-zerolatency", "1", "-f", "h264", "-vf", "scale=1280x720", "-pix_fmt", "yuv420p", "-profile:v", "baseline", "-cq:v", "19", "-g", "999999", "-b:v", bitrate, "-minrate", bitrate, "-maxrate", bitrate, "-bufsize", bitrate, "tcp://" + ip + ":2222"];
if (encoding == "NVENC")
{
ffmpegVideoArgs = ["-fflags", "nobuffer", "-flags", "low_delay", "-probesize", "32", "-hwaccel", "auto", "-y", "-f", "gdigrab", "-framerate", fps, "-vsync", vsync, "-video_size", screenWidth + "x" + screenHeight, "-offset_x", "0", "-offset_y", "0", "-draw_mouse", "1", "-i", "desktop", "-c:v", "h264_nvenc", "-gpu", "0", "-rc", "vbr", "-zerolatency", "1", "-f", "h264", "-vf", "scale=1280x720", "-pix_fmt", "yuv420p", "-profile:v", "baseline", "-cq:v", "19", "-g", "999999", "-b:v", bitrate, "-minrate", bitrate, "-maxrate", bitrate, "-bufsize", bitrate, "tcp://" + ip + ":2222"];
log("Using Nvidia Encoding");
} else if (encoding == "AMDVCE") { //AMD Video Coding Engine
ffmpegVideoArgs = ["-probesize", "32", "-hwaccel", "auto", "-y", "-f", "gdigrab", "-framerate", fps, "-vsync", "vfr", "-video_size", screenWidth + "x" + screenHeight, "-offset_x", "0", "-offset_y", "0", "-draw_mouse", "1", "-i", "desktop", "-f", "h264", "-c:v", "h264_amf", "-usage", "1", "-rc", "vbr", "-vf", "scale=1280x720", "-pix_fmt", "yuv420p", "-b:v", bitrate, "-minrate", bitrate, "-maxrate", bitrate, "-bufsize", bitrate, "tcp://" + ip + ":2222"];
log("Using AMD Video Coding Engine");
} else if (encoding == "QSV") {
ffmpegVideoArgs = ["-probesize", "32", "-hwaccel", "auto", "-y", "-f", "gdigrab", "-framerate", fps, "-vsync", "vfr", "-video_size", screenWidth + "x" + screenHeight, "-offset_x", "0", "-offset_y", "0", "-draw_mouse", "1", "-i", "desktop", "-f", "h264", "-c:v", "h264_qsv", "-preset", "faster", "-profile", "baseline", "-vf", "scale=1280x720", "-pix_fmt", "yuv420p", "-b:v", bitrate, "-minrate", bitrate, "-maxrate", bitrate, "-bufsize", bitrate, "tcp://" + ip + ":2222"];
} else if (encoding == "AMDVCE") //AMD Video Coding Engine
{
ffmpegVideoArgs = ["-fflags", "nobuffer", "-flags", "low_delay", "-probesize", "32", "-hwaccel", "auto", "-y", "-f", "gdigrab", "-framerate", fps, "-vsync", vsync, "-video_size", screenWidth + "x" + screenHeight, "-offset_x", "0", "-offset_y", "0", "-draw_mouse", "1", "-i", "desktop", "-f", "h264", "-c:v", "h264_amf", "-usage", "ultralowlatency", "-quality", "speed", "-rc", "vbr_latency", "-vf", "scale=1280x720", "-pix_fmt", "yuv420p", "-b:v", bitrate, "-minrate", bitrate, "-maxrate", bitrate, "-bufsize", bitrate, "tcp://" + ip + ":2222"];
log("Using AMD Video Coding Engine (amf)");
}
else if(encoding == "AMDHEVC")
{
ffmpegVideoArgs = ["-fflags", "nobuffer", "-flags", "low_delay", "-probesize", "32", "-hwaccel", "auto", "-y", "-f", "gdigrab", "-framerate", fps, "-vsync", vsync, "-video_size", screenWidth + "x" + screenHeight, "-offset_x", "0", "-offset_y", "0", "-draw_mouse", "1", "-i", "desktop", "-f", "h264", "-c:v", "hevc_amf", "-usage", "ultralowlatency", "-quality", "speed", "-rc", "vbr_latency", "-vf", "scale=1280x720", "-pix_fmt", "yuv420p", "-b:v", bitrate, "-minrate", bitrate, "-maxrate", bitrate, "-bufsize", bitrate, "tcp://" + ip + ":2222"];
log("Using AMD Video Coding Engine (hevc)");
}
else if (encoding == "QSV")
{
ffmpegVideoArgs = ["-fflags", "nobuffer", "-flags", "low_delay", "-probesize", "32", "-hwaccel", "auto", "-y", "-f", "gdigrab", "-framerate", fps, "-vsync", vsync, "-video_size", screenWidth + "x" + screenHeight, "-offset_x", "0", "-offset_y", "0", "-draw_mouse", "1", "-i", "desktop", "-f", "h264", "-c:v", "h264_qsv", "-preset", "faster", "-profile", "baseline", "-vf", "scale=1280x720", "-pix_fmt", "yuv420p", "-b:v", bitrate, "-minrate", bitrate, "-maxrate", bitrate, "-bufsize", bitrate, "tcp://" + ip + ":2222"];
log("Using Intel QSV Encoding");
} else { //CPU Software Encoding
ffmpegVideoArgs = ["-probesize", "32", "-hwaccel", "auto", "-y", "-f", "gdigrab", "-framerate", fps, "-vsync", "vfr", "-video_size", screenWidth + "x" + screenHeight, "-offset_x", "0", "-offset_y", "0", "-draw_mouse", "1", "-i", "desktop", "-f", "h264", "-vf", "scale=1280x720", "-preset", "ultrafast", "-crf", "18", "-tune", "zerolatency", "-pix_fmt", "yuv420p", "-profile:v", "baseline", "-x264-params", "nal-hrd=vbr:opencl=true", "-b:v", bitrate, "-minrate", bitrate, "-maxrate", bitrate, "-bufsize", bitrate, "tcp://" + ip + ":2222"];
}
else
{ //CPU Software Encoding
ffmpegVideoArgs = ["-fflags", "nobuffer", "-flags", "low_delay", "-probesize", "32", "-hwaccel", "auto", "-y", "-f", "gdigrab", "-framerate", fps, "-vsync", vsync, "-video_size", screenWidth + "x" + screenHeight, "-offset_x", "0", "-offset_y", "0", "-draw_mouse", "1", "-i", "desktop", "-f", "h264", "-vf", "scale=1280x720", "-preset", "ultrafast", "-crf", "18", "-tune", "zerolatency", "-pix_fmt", "yuv420p", "-profile:v", "baseline", "-x264-params", "nal-hrd=vbr:opencl=true", "-b:v", bitrate, "-minrate", bitrate, "-maxrate", bitrate, "-bufsize", bitrate, "tcp://" + ip + ":2222"];
log("Using CPU Encoding");
}
ffmpegProcess = spawn(
__dirname + "/lib/ffmpeg.exe",
ffmpegVideoArgs,
@ -276,7 +291,9 @@ function setArgs(arg) {
limitFPS = arg.limitFPS;
screenScale = screen.getPrimaryDisplay().scaleFactor;
mouseControl = arg.mouseControl;
encoding = arg.encoding
encoding = arg.encoding;
vsync = arg.vsync;
monitorID = arg.monitorID;
}
ipcMain.on('connect', (event, arg) => {
clientSender = event.sender;

File diff suppressed because it is too large Load diff