mirror of
https://github.com/LizardByte/Sunshine.git
synced 2024-11-18 20:09:54 +00:00
211b25848f
Invoke DwmFlush() before acquiring the next frame to alleviate visual stutter during mouse movement at the cost of constraining the capture rate to the host's monitor refresh. Disabled by default; enable via "dwmflush" boolean configuration parameter.
919 lines
32 KiB
HTML
919 lines
32 KiB
HTML
<div id="app" class="container">
|
|
<h1 class="my-4">Configuration</h1>
|
|
<div class="form" v-if="config">
|
|
<!--Header-->
|
|
<ul class="nav nav-tabs">
|
|
<li class="nav-item" v-for="tab in tabs" :key="tab.id">
|
|
<a
|
|
class="nav-link"
|
|
:class="{'active': tab.id === currentTab}"
|
|
href="#"
|
|
@click="currentTab = tab.id"
|
|
>{{tab.name}}</a
|
|
>
|
|
</li>
|
|
</ul>
|
|
<!--General Tab-->
|
|
<div v-if="currentTab === 'general'" class="config-page">
|
|
<!--Sunshine Name-->
|
|
<div class="mb-3">
|
|
<label for="sunshine_name" class="form-label">Sunshine Name</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="sunshine_name"
|
|
placeholder="Sunshine"
|
|
v-model="config.sunshine_name"
|
|
/>
|
|
<div class="form-text">
|
|
The name displayed by Moonlight. If not specified, the PC's hostname is used
|
|
</div>
|
|
</div>
|
|
<!--Log Level-->
|
|
<div class="mb-3">
|
|
<label for="min_log_level" class="form-label">Log Level</label>
|
|
<select
|
|
id="min_log_level"
|
|
class="form-select"
|
|
v-model="config.min_log_level"
|
|
>
|
|
<option value="0">Verbose</option>
|
|
<option value="1">Debug</option>
|
|
<option value="2">Info</option>
|
|
<option value="3">Warning</option>
|
|
<option value="4">Error</option>
|
|
<option value="5">Fatal</option>
|
|
<option value="6">None</option>
|
|
</select>
|
|
<div class="form-text">
|
|
The minimum log level printed to standard out
|
|
</div>
|
|
</div>
|
|
<!--Origin Web UI Allowed-->
|
|
<div class="mb-3">
|
|
<label for="origin_web_ui_allowed" class="form-label"
|
|
>Origin Web UI Allowed</label
|
|
>
|
|
<select
|
|
id="origin_web_ui_allowed"
|
|
class="form-select"
|
|
v-model="config.origin_web_ui_allowed"
|
|
>
|
|
<option value="pc">Only localhost may access Web UI</option>
|
|
<option value="lan">Only those in LAN may access Web UI</option>
|
|
<option value="wan">Anyone may access Web UI</option>
|
|
</select>
|
|
<div class="form-text">
|
|
The origin of the remote endpoint address that is not denied access to Web UI
|
|
</div>
|
|
</div>
|
|
<!--UPnP-->
|
|
<div class="mb-3">
|
|
<label for="upnp" class="form-label">UPnP</label>
|
|
<select id="upnp" class="form-select" v-model="config.upnp">
|
|
<option value="disabled">Disabled</option>
|
|
<option value="enabled">Enabled</option>
|
|
</select>
|
|
<div class="form-text">Automatically configure port forwarding</div>
|
|
</div>
|
|
<!--Gamepads-->
|
|
<div class="mb-3" v-if="platform === 'windows'">
|
|
<label for="gamepad" class="form-label">Gamepads</label>
|
|
<select id="gamepad" class="form-select" v-model="config.gamepad">
|
|
<option value="ds4">DS4 (PS4)</option>
|
|
<option value="x360">X360 (Xbox 360)</option>
|
|
</select>
|
|
<div class="form-text">Choose which type of gamepad to Emulate on the host</div>
|
|
</div>
|
|
<!--Ping Timeout-->
|
|
<div class="mb-3">
|
|
<label for="ping_timeout" class="form-label">Ping Timeout</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="ping_timeout"
|
|
placeholder="10000"
|
|
v-model="config.ping_timeout"
|
|
/>
|
|
<div class="form-text">
|
|
How long to wait in milliseconds for data from moonlight before shutting down the stream
|
|
</div>
|
|
</div>
|
|
<!--Advertised FPS and Resolutions-->
|
|
<div class="mb-3">
|
|
<label for="ping_timeout" class="form-label"
|
|
>Advertised Resolutions and FPS</label
|
|
>
|
|
<div class="resolutions-container">
|
|
<label>Resolutions</label>
|
|
<div class="resolutions d-flex flex-wrap">
|
|
<div
|
|
class="p-2 ms-item m-2 d-flex justify-content-between"
|
|
v-for="(r,i) in resolutions"
|
|
:key="r"
|
|
>
|
|
<span class="px-2">{{r}}</span>
|
|
<span style="cursor: pointer" @click="resolutions.splice(i,1)"
|
|
>×</span
|
|
>
|
|
</div>
|
|
<form
|
|
@submit.prevent="resolutions.push(resIn);resIn = '';"
|
|
class="d-flex align-items-center"
|
|
>
|
|
<input
|
|
type="text"
|
|
v-model="resIn"
|
|
required
|
|
pattern="[0-9]+x[0-9]+"
|
|
style="
|
|
border-top-right-radius: 0;
|
|
border-bottom-right-radius: 0;
|
|
"
|
|
class="form-control"
|
|
/>
|
|
<button
|
|
style="border-top-left-radius: 0; border-bottom-left-radius: 0"
|
|
class="btn btn-success"
|
|
>
|
|
+
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<div class="fps-container">
|
|
<label>FPS</label>
|
|
<div class="fps d-flex flex-wrap">
|
|
<div
|
|
class="p-2 ms-item m-2 d-flex justify-content-between"
|
|
v-for="(f,i) in fps"
|
|
:key="f"
|
|
>
|
|
<span class="px-2">{{f}}</span>
|
|
<span style="cursor: pointer" @click="fps.splice(i,1)"
|
|
>×</span
|
|
>
|
|
</div>
|
|
<form
|
|
@submit.prevent="fps.push(fpsIn);fpsIn = '';"
|
|
class="d-flex align-items-center"
|
|
>
|
|
<input
|
|
type="text"
|
|
v-model="fpsIn"
|
|
required
|
|
pattern="[0-9]+"
|
|
style="
|
|
width: 6ch;
|
|
border-top-right-radius: 0;
|
|
border-bottom-right-radius: 0;
|
|
"
|
|
class="form-control"
|
|
/>
|
|
<button
|
|
style="border-top-left-radius: 0; border-bottom-left-radius: 0"
|
|
class="btn btn-success"
|
|
>
|
|
+
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<div class="form-text">
|
|
The display modes advertised by Sunshine<br />
|
|
Some versions of Moonlight, such as Moonlight-nx (Switch), rely on this list to ensure that the requested
|
|
resolutions and fps are supported.<br>
|
|
This setting does <b>not</b> change how the screen stream is sent to Moonlight
|
|
</div>
|
|
</div>
|
|
<!-- Mapping Key AltRight to Key Windows -->
|
|
<div class="mb-3">
|
|
<label for="mapkey" class="form-label"
|
|
>Map Right Alt key to Windows key</label
|
|
>
|
|
<select
|
|
id="mapkey"
|
|
class="form-select"
|
|
v-model="config.key_rightalt_to_key_win"
|
|
>
|
|
<option value="disabled">Disabled</option>
|
|
<option value="enabled">Enabled</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-text">
|
|
It may be possible that you cannot send the Windows Key from Moonlight directly.<br />
|
|
In those cases it may be useful to make Sunshine think the Right Alt key is the Windows key
|
|
</div>
|
|
</div>
|
|
<!--Files Tab-->
|
|
<div v-if="currentTab === 'files'" class="config-page">
|
|
<!--Private Key-->
|
|
<div class="mb-3">
|
|
<label for="pkey" class="form-label">Private Key</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="pkey"
|
|
placeholder="/dir/pkey.pem"
|
|
v-model="config.pkey"
|
|
/>
|
|
<div class="form-text">The private key must be 2048 bits</div>
|
|
</div>
|
|
<!--Cert-->
|
|
<div class="mb-3">
|
|
<label for="cert" class="form-label">Cert</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="cert"
|
|
placeholder="/dir/cert.pem"
|
|
v-model="config.cert"
|
|
/>
|
|
<div class="form-text">
|
|
The certificate must be signed with a 2048 bit key
|
|
</div>
|
|
</div>
|
|
|
|
<!--State File-->
|
|
<div class="mb-3">
|
|
<label for="file_state" class="form-label">State File</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="file_state"
|
|
placeholder="sunshine_state.json"
|
|
v-model="config.file_state"
|
|
/>
|
|
<div class="form-text">
|
|
The file where current state of Sunshine is stored
|
|
</div>
|
|
</div>
|
|
<!--Apps File-->
|
|
<div class="mb-3">
|
|
<label for="file_apps" class="form-label">Apps File</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="file_apps"
|
|
placeholder="apps.json"
|
|
v-model="config.file_apps"
|
|
/>
|
|
<div class="form-text">
|
|
The file where current apps of Sunshine are stored
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-if="currentTab === 'input'" class="config-page">
|
|
<!--Back Button Timeout-->
|
|
<div class="mb-3">
|
|
<label for="back_button_timeout" class="form-label"
|
|
>Back Button Timeout</label
|
|
>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="back_button_timeout"
|
|
placeholder="2000"
|
|
v-model="config.back_button_timeout"
|
|
/>
|
|
<div class="form-text">
|
|
The back/select button on the controller.<br />
|
|
On the Shield, the home and power button are not passed to Moonlight.<br />
|
|
If, after the timeout, the back button is still pressed down, Home/Guide button press is emulated.<br />
|
|
If back_button_timeout < 0, then the Home/Guide button will not be emulated<br />
|
|
</div>
|
|
</div>
|
|
<!-- Key Repeat Delay-->
|
|
<div class="mb-3" v-if="platform === 'windows'">
|
|
<label for="key_repeat_delay" class="form-label"
|
|
>Key Repeat Delay</label
|
|
>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="key_repeat_delay"
|
|
placeholder="500"
|
|
v-model="config.key_repeat_delay"
|
|
/>
|
|
<div class="form-text">
|
|
Control how fast keys will repeat themselves<br />
|
|
The initial delay in milliseconds before repeating keys
|
|
</div>
|
|
</div>
|
|
<!-- Key Repeat Frequency-->
|
|
<div class="mb-3" v-if="platform === 'windows'">
|
|
<label for="key_repeat_frequency" class="form-label"
|
|
>Key Repeat Frequency</label
|
|
>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="key_repeat_frequency"
|
|
placeholder="24.9"
|
|
v-model="config.key_repeat_frequency"
|
|
/>
|
|
<div class="form-text">
|
|
How often keys repeat every second<br />
|
|
This configurable option supports decimals
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!--Files Tab-->
|
|
<div v-if="currentTab === 'av'" class="config-page">
|
|
<!--Audio Sink-->
|
|
<div class="mb-3" v-if="platform === 'windows'">
|
|
<label for="audio_sink" class="form-label">Audio Sink</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="audio_sink"
|
|
placeholder="{0.0.0.00000000}.{FD47D9CC-4218-4135-9CE2-0C195C87405B}"
|
|
v-model="config.audio_sink"
|
|
/>
|
|
<div class="form-text">
|
|
The name of the audio sink used for Audio Loopback<br />
|
|
You can find the name of the audio sink using the following command:<br />
|
|
<pre>tools\audio-info.exe</pre>
|
|
</div>
|
|
</div>
|
|
<div class="mb-3" v-if="platform === 'linux'">
|
|
<label for="audio_sink" class="form-label">Audio Sink</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="audio_sink"
|
|
placeholder="alsa_output.pci-0000_09_00.3.analog-stereo"
|
|
v-model="config.audio_sink"
|
|
/>
|
|
<div class="form-text">
|
|
The name of the audio sink used for Audio Loopback<br />
|
|
If you do not specify this variable, pulseaudio will select the default monitor device.<br />
|
|
<br />
|
|
You can find the name of the audio sink using either command:<br />
|
|
<pre>pacmd list-sinks | grep "name:"</pre>
|
|
<pre>pactl info | grep Source</pre>
|
|
<br />
|
|
</div>
|
|
</div>
|
|
<!--Virtual Sink-->
|
|
<div class="mb-3" v-if="platform === 'windows'">
|
|
<label for="virtual_sink" class="form-label">Virtual Sink</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="virtual_sink"
|
|
placeholder="{0.0.0.00000000}.{8edba70c-1125-467c-b89c-15da389bc1d4}"
|
|
v-model="config.virtual_sink"
|
|
/>
|
|
<div class="form-text">
|
|
The virtual sink, is the audio device that's virtual (Like Steam Streaming Speakers), it allows Sunshine to
|
|
stream audio, while muting the speakers.
|
|
</div>
|
|
</div>
|
|
<!--Adapter Name -->
|
|
<div class="mb-3" v-if="platform === 'windows'">
|
|
<label for="adapter_name" class="form-label">Adapter Name</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="adapter_name"
|
|
placeholder="Radeon RX 580 Series"
|
|
v-model="config.adapter_name"
|
|
/>
|
|
<div class="form-text" v-if="platform === 'windows'">
|
|
You can select the video card you want to stream:<br />
|
|
The appropriate values can be found using the following command:<br />
|
|
<pre>tools\dxgi-info.exe</pre>
|
|
</div>
|
|
</div>
|
|
<!--Output Name -->
|
|
<div class="mb-3" class="config-page" v-if="platform === 'windows'">
|
|
<label for="output_name" class="form-label">Output Name</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="output_name"
|
|
placeholder="\\.\DISPLAY1"
|
|
v-model="config.output_name"
|
|
/>
|
|
<div class="form-text">
|
|
You can select the video card you want to stream:<br />
|
|
The appropriate values can be found using the following command:<br />
|
|
tools\dxgi-info.exe<br />
|
|
</div>
|
|
</div>
|
|
<!--DwmFlush-->
|
|
<div class="mb-3" v-if="platform === 'windows'">
|
|
<label for="dwmflush" class="form-label">DwmFlush</label>
|
|
<select id="dwmflush" class="form-select" v-model="config.dwmflush">
|
|
<option value="disabled">Disabled</option>
|
|
<option value="enabled">Enabled</option>
|
|
</select>
|
|
<div class="form-text">
|
|
Improves capture latency during mouse movement.<br />
|
|
Enabling this may prevent the client's FPS from exceeding the host monitor's active refresh rate.
|
|
</div>
|
|
</div>
|
|
<div class="mb-3" class="config-page" v-if="platform === 'linux'">
|
|
<label for="output_name" class="form-label">Monitor number</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="output_name"
|
|
placeholder="0"
|
|
v-model="config.output_name"
|
|
/>
|
|
<div class="form-text">
|
|
xrandr --listmonitors<br />
|
|
Example output:
|
|
<pre> 0: +HDMI-1 1920/518x1200/324+0+0 HDMI-1</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-if="currentTab === 'advanced'" class="config-page">
|
|
<!--Port family-->
|
|
<div class="mb-3">
|
|
<label for="port" class="form-label">Port</label>
|
|
<input
|
|
type="number"
|
|
min="0"
|
|
max="65529"
|
|
class="form-control"
|
|
id="port"
|
|
placeholder="47989"
|
|
v-model="config.port"
|
|
/>
|
|
<div class="form-text">Set the family of ports used by Sunshine</div>
|
|
</div>
|
|
<!-- Quantization Parameter -->
|
|
<div class="mb-3">
|
|
<label for="qp" class="form-label">Quantitization Parameter</label>
|
|
<input
|
|
type="number"
|
|
class="form-control"
|
|
id="qp"
|
|
placeholder="28"
|
|
v-model="config.qp"
|
|
/>
|
|
<div class="form-text">
|
|
Quantitization Parameter<br />
|
|
Some devices may not support Constant Bit Rate.<br />
|
|
For those devices, QP is used instead.<br />
|
|
Higher value means more compression, but less quality<br />
|
|
</div>
|
|
</div>
|
|
<!-- Min Threads -->
|
|
<div class="mb-3">
|
|
<label for="min_threads" class="form-label"
|
|
>Minimum number of threads used by ffmpeg to encode the video.</label
|
|
>
|
|
<input
|
|
type="number"
|
|
min="1"
|
|
class="form-control"
|
|
id="min_threads"
|
|
placeholder="1"
|
|
v-model="config.min_threads"
|
|
/>
|
|
<div class="form-text">
|
|
Minimum number of threads used by ffmpeg to encode the video.<br />
|
|
Increasing the value slightly reduces encoding efficiency, but the tradeoff is usually<br />
|
|
worth it to gain the use of more CPU cores for encoding. The ideal value is the lowest<br />
|
|
value that can reliably encode at your desired streaming settings on your hardware.
|
|
</div>
|
|
</div>
|
|
<!--HEVC Support -->
|
|
<div class="mb-3">
|
|
<label for="hevc_mode" class="form-label">HEVC Support</label>
|
|
<select id="hevc_mode" class="form-select" v-model="config.hevc_mode">
|
|
<option value="0">
|
|
Sunshine will specify support for HEVC based on encoder
|
|
</option>
|
|
<option value="1">
|
|
Sunshine will not advertise support for HEVC
|
|
</option>
|
|
<option value="2">
|
|
Sunshine will advertise support for HEVC Main profile
|
|
</option>
|
|
<option value="3">
|
|
Sunshine will advertise support for HEVC Main and Main10 (HDR) profiles
|
|
</option>
|
|
</select>
|
|
<div class="form-text">
|
|
Allows the client to request HEVC Main or HEVC Main10 video streams.<br />
|
|
HEVC is more CPU-intensive to encode, so enabling this may reduce performance when using software encoding.
|
|
</div>
|
|
</div>
|
|
<!--Encoder -->
|
|
<div class="mb-3">
|
|
<label for="encoder" class="form-label">Force a Specific Encoder</label>
|
|
<select id="encoder" class="form-select" v-model="config.encoder">
|
|
<option value>Autodetect</option>
|
|
<option value="nvenc">nVidia NVENC</option>
|
|
<option value="amdvce">AMD AMF/VCE</option>
|
|
<option value="vaapi">VA-API</option>
|
|
<option value="software">Software</option>
|
|
</select>
|
|
<div class="form-text">
|
|
Force a specific encoder, otherwise Sunshine will use the first encoder that is available
|
|
</div>
|
|
</div>
|
|
<!--FEC Percentage-->
|
|
<div class="mb-3">
|
|
<label for="fec_percentage" class="form-label">FEC Percentage</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="fec_percentage"
|
|
placeholder="20"
|
|
v-model="config.fec_percentage"
|
|
/>
|
|
<div class="form-text">
|
|
Percentage of error correcting packets per data packet in each video frame.<br />
|
|
Higher values can correct for more network packet loss, but at the cost of increasing bandwidth usage.<br />
|
|
The default value of 20 is what GeForce Experience uses.
|
|
</div>
|
|
</div>
|
|
<!--Channels-->
|
|
<div class="mb-3">
|
|
<label for="channels" class="form-label">Channels</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="channels"
|
|
placeholder="1"
|
|
v-model="config.channels"
|
|
/>
|
|
<div class="form-text">
|
|
When multicasting, it could be useful to have different configurations for each connected Client. For example:
|
|
<ul>
|
|
<li>
|
|
Clients connected through WAN and LAN have different bitrate constraints.
|
|
</li>
|
|
<li>
|
|
Decoders may require different settings for color
|
|
</li>
|
|
</ul>
|
|
Unlike simply broadcasting to multiple Client, this will generate distinct video streams.<br />
|
|
Note, CPU usage increases for each distinct video stream generated
|
|
</div>
|
|
</div>
|
|
<!--Credentials File-->
|
|
<div class="mb-3">
|
|
<label for="credentials_file" class="form-label"
|
|
>Web Manager Credentials File</label
|
|
>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="credentials_file"
|
|
placeholder="sunshine_state.json"
|
|
v-model="config.credentials_file"
|
|
/>
|
|
<div class="form-text">
|
|
Store Username/Password separately from Sunshine's state file.
|
|
</div>
|
|
</div>
|
|
<!--Origin PIN Allowed-->
|
|
<div class="mb-3">
|
|
<label for="origin_pin_allowed" class="form-label"
|
|
>Origin PIN Allowed</label
|
|
>
|
|
<select
|
|
id="origin_pin_allowed"
|
|
class="form-select"
|
|
v-model="config.origin_pin_allowed"
|
|
>
|
|
<option value="pc">Only localhost may access /pin</option>
|
|
<option value="lan">Only those in LAN may access /pin</option>
|
|
<option value="wan">Anyone may access /pin</option>
|
|
</select>
|
|
<div class="form-text">
|
|
The origin of the remote endpoint address that is not denied for HTTP method /pin
|
|
</div>
|
|
</div>
|
|
<!--External IP-->
|
|
<div class="mb-3">
|
|
<label for="external_ip" class="form-label">External IP</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="external_ip"
|
|
placeholder="123.456.789.12"
|
|
v-model="config.external_ip"
|
|
/>
|
|
<div class="form-text">
|
|
If no external IP address is given, Sunshine will automatically detect external IP
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!--Software Settings-->
|
|
<div v-if="currentTab === 'sw'" class="config-page">
|
|
<div class="mb-3">
|
|
<label for="sw_preset" class="form-label">SW Presets</label>
|
|
<input
|
|
class="form-control"
|
|
id="sw_preset"
|
|
placeholder="superfast"
|
|
v-model="config.sw_preset"
|
|
/>
|
|
<div class="form-text">
|
|
Available Values: ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow
|
|
</div>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="sw_tune" class="form-label">SW Tune</label>
|
|
<input
|
|
class="form-control"
|
|
id="sw_tune"
|
|
placeholder="zerolatency"
|
|
v-model="config.sw_tune"
|
|
/>
|
|
<div class="form-text">
|
|
Available Tune settings: <br>
|
|
film - use for high quality movie content; lowers deblocking<br>
|
|
animation - good for cartoons; uses higher deblocking and more reference frames<br>
|
|
grain - preserves the grain structure in old, grainy film material<br>
|
|
stillimage - good for slideshow-like content<br>
|
|
fastdecode - allows faster decoding by disabling certain filters<br>
|
|
zerolatency - good for fast encoding and low-latency streaming<br>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!--Nvidia Encoder Settings-->
|
|
<div v-if="currentTab === 'nv'" class="config-page">
|
|
<!--NVENC SETTINGS-->
|
|
<div class="mb-3">
|
|
<label for="nv_preset" class="form-label">NVEnc Preset</label>
|
|
<select id="nv_preset" class="form-select" v-model="config.nv_preset">
|
|
<option value="default">Default</option>
|
|
<option value="hp">High Performance</option>
|
|
<option value="hq">High Quality</option>
|
|
<option value="slow">Slow - hq 2 passes</option>
|
|
<option value="medium">medium -- hq 1 pass</option>
|
|
<option value="fast">fast -- hp 1 pass</option>
|
|
<option value="bd">bd</option>
|
|
<option value="ll">ll -- low latency</option>
|
|
<option value="llhq">llhq</option>
|
|
<option value="llhp">llhp</option>
|
|
<option value="lossless">lossless</option>
|
|
<option value="losslesshp">losslesshp</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="nv_rc" class="form-label">NVEnc Rate Control</label>
|
|
<select id="nv_rc" class="form-select" v-model="config.nv_rc">
|
|
<option value="auto">auto -- let ffmpeg decide rate control</option>
|
|
<option value="constqp">constqp -- constant QP mode</option>
|
|
<option value="vbr">vbr -- variable bitrate</option>
|
|
<option value="cbr">cbr -- constant bitrate</option>
|
|
<option value="cbr_hq">cbr_hq -- cbr high quality</option>
|
|
<option value="cbr_ld_hq">cbr_ld_hq -- cbr low delay high quality</option>
|
|
<option value="vbr_hq">vbr_hq -- vbr high quality</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="nv_coder" class="form-label">NVEnc Coder</label>
|
|
<select id="nv_coder" class="form-select" v-model="config.nv_coder">
|
|
<option value="auto">auto</option>
|
|
<option value="cabac">cabac</option>
|
|
<option value="cavlc">cavlc</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<!--AMD Encoder Settings-->
|
|
<div v-if="currentTab === 'amd'" class="config-page">
|
|
<!--Presets-->
|
|
<div class="mb-3">
|
|
<label for="amd_quality" class="form-label">AMD AMF Quality</label>
|
|
<select
|
|
id="amd_quality"
|
|
class="form-select"
|
|
v-model="config.amd_quality"
|
|
>
|
|
<option value="default">Default</option>
|
|
<option value="speed">Speed</option>
|
|
<option value="balanced">Balanced</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="amd_rc" class="form-label">AMD AMF Rate Control</label>
|
|
<select id="amd_rc" class="form-select" v-model="config.amd_rc">
|
|
<option value="auto">auto -- let ffmpeg decide rate control</option>
|
|
<option value="constqp">constqp -- constant QP mode</option>
|
|
<option value="vbr_latency">vbr_latency -- Latency Constrained Variable Bitrate</option>
|
|
<option value="vbr_peak">vbr_peak -- Peak Contrained Variable Bitrate</option>
|
|
<option value="cbr">cbr -- constant bitrate</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="amd_coder" class="form-label">AMD AMF Coder</label>
|
|
<select id="amd_coder" class="form-select" v-model="config.amd_coder">
|
|
<option value="auto">auto</option>
|
|
<option value="cabac">cabac</option>
|
|
<option value="cavlc">cavlc</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div v-if="currentTab === 'va-api'" class="config-page">
|
|
<input
|
|
class="form-control"
|
|
id="adapter_name"
|
|
placeholder="/dev/dri/renderD128"
|
|
v-model="config.adapter_name"
|
|
/>
|
|
</div>
|
|
<!--VideoToolbox Encoder Settings-->
|
|
<div v-if="currentTab === 'vt'" class="config-page">
|
|
<!--Presets-->
|
|
<div class="mb-3">
|
|
<label for="vt_coder" class="form-label">VideoToolbox Coder</label>
|
|
<select id="vt_coder" class="form-select" v-model="config.vt_coder">
|
|
<option value="auto">auto</option>
|
|
<option value="cabac">cabac</option>
|
|
<option value="cavlc">cavlc</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="vt_software" class="form-label">VideoToolbox Software Encoding</label>
|
|
<select id="vt_software" class="form-select" v-model="config.vt_software">
|
|
<option value="auto">auto</option>
|
|
<option value="disabled">disabled</option>
|
|
<option value="allowed">allowed</option>
|
|
<option value="forced">forced</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="vt_realtime" class="form-label">VideoToolbox Realtime Encoding</label>
|
|
<select id="vt_realtime" class="form-select" v-model="config.vt_realtime">
|
|
<option value="enabled">enabled</option>
|
|
<option value="disabled">disabled</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="alert alert-success my-4" v-if="success">
|
|
<b>Success!</b> Restart Sunshine to apply changes
|
|
</div>
|
|
<div class="mb-3 buttons">
|
|
<button class="btn btn-primary" @click="save">Save</button>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
new Vue({
|
|
el: "#app",
|
|
data() {
|
|
return {
|
|
platform: "",
|
|
success: false,
|
|
config: null,
|
|
fps: [],
|
|
resolutions: [],
|
|
currentTab: "general",
|
|
resIn: "",
|
|
fpsIn: "",
|
|
tabs: [
|
|
{
|
|
id: "general",
|
|
name: "General",
|
|
},
|
|
{
|
|
id: "files",
|
|
name: "Files",
|
|
},
|
|
{
|
|
id: "input",
|
|
name: "Input",
|
|
},
|
|
{
|
|
id: "av",
|
|
name: "Audio/Video",
|
|
},
|
|
{
|
|
id: "advanced",
|
|
name: "Advanced",
|
|
},
|
|
{
|
|
id: "sw",
|
|
name: "Software Encoder",
|
|
},
|
|
{
|
|
id: "nv",
|
|
name: "NVENC Encoder",
|
|
},
|
|
{
|
|
id: "amd",
|
|
name: "AMF Encoder",
|
|
},
|
|
{
|
|
id: "va-api",
|
|
name: "VA-API encoder",
|
|
},
|
|
{
|
|
id: "vt",
|
|
name: "VideoToolbox encoder",
|
|
},
|
|
],
|
|
};
|
|
},
|
|
created() {
|
|
fetch("/api/config")
|
|
.then((r) => r.json())
|
|
.then((r) => {
|
|
this.config = r;
|
|
this.platform = this.config.platform;
|
|
|
|
var app = document.getElementById("app");
|
|
if (this.platform == "windows") {
|
|
this.tabs = this.tabs.filter((el) => {
|
|
return el.id !== "va-api";
|
|
});
|
|
}
|
|
if (this.platform == "linux") {
|
|
this.tabs = this.tabs.filter((el) => {
|
|
return el.id !== "amd";
|
|
});
|
|
}
|
|
|
|
delete this.config.status;
|
|
delete this.config.platform;
|
|
//Populate default values if not present in config
|
|
this.config.key_rightalt_to_key_win =
|
|
this.config.key_rightalt_to_key_win || "disabled";
|
|
this.config.gamepad = this.config.gamepad || "x360";
|
|
this.config.upnp = this.config.upnp || "disabled";
|
|
this.config.dwmflush = this.config.dwmflush || "disabled";
|
|
this.config.min_log_level = this.config.min_log_level || 2;
|
|
this.config.origin_pin_allowed =
|
|
this.config.origin_pin_allowed || "pc";
|
|
this.config.origin_web_ui_allowed =
|
|
this.config.origin_web_manager_allowed || "lan";
|
|
this.config.hevc_mode = this.config.hevc_mode || 0;
|
|
this.config.encoder = this.config.encoder || "";
|
|
this.config.nv_preset = this.config.nv_preset || "default";
|
|
this.config.nv_rc = this.config.nv_rc || "auto";
|
|
this.config.nv_coder = this.config.nv_coder || "auto";
|
|
this.config.amd_coder = this.config.amd_coder || "auto"
|
|
this.config.amd_quality = this.config.amd_quality || "default";
|
|
this.config.amd_rc = this.config.amd_rc || "auto";
|
|
this.config.vt_coder = this.config.vt_coder || "auto";
|
|
this.config.vt_software = this.config.vt_software || "auto";
|
|
this.config.vt_realtime = this.config.vt_realtime || "enabled";
|
|
this.config.fps = this.config.fps || "[10, 30, 60, 90, 120]";
|
|
this.config.resolutions =
|
|
this.config.resolutions ||
|
|
"[352x240,480x360,858x480,1280x720,1920x1080,2560x1080,3440x1440,1920x1200,3860x2160,3840x1600]";
|
|
this.fps = JSON.parse(this.config.fps);
|
|
//Resolutions should be fixed because are not valid JSON
|
|
let res = this.config.resolutions.substring(
|
|
1,
|
|
this.config.resolutions.length - 1
|
|
);
|
|
let resolutions = [];
|
|
res.split(",").forEach((r) => resolutions.push(r.trim()));
|
|
this.resolutions = resolutions;
|
|
});
|
|
},
|
|
methods: {
|
|
save() {
|
|
this.success = false;
|
|
let nl = this.config === "windows" ? "\r\n" : "\n";
|
|
this.config.resolutions =
|
|
"[" +
|
|
nl +
|
|
" " +
|
|
this.resolutions.join("," + nl + " ") +
|
|
nl +
|
|
"]";
|
|
this.config.fps = JSON.stringify(this.fps);
|
|
|
|
fetch("/api/config", {
|
|
method: "POST",
|
|
body: JSON.stringify(this.config),
|
|
}).then((r) => {
|
|
if (r.status == 200) this.success = true;
|
|
});
|
|
},
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
.config-page {
|
|
padding: 1em;
|
|
border: 1px solid #dee2e6;
|
|
border-top: none;
|
|
}
|
|
|
|
.buttons {
|
|
padding: 1em 0;
|
|
}
|
|
|
|
.ms-item {
|
|
background-color: #ccc;
|
|
font-size: 12px;
|
|
font-weight: bold;
|
|
}
|
|
</style>
|