Merge remote-tracking branch 'origin/master'

This commit is contained in:
Yukino Song
2024-09-10 17:59:34 +08:00
26 changed files with 357 additions and 80 deletions

View File

@@ -1,7 +1,6 @@
[flake8] [flake8]
filename = filename =
*.py, *.py
*.pys
max-line-length = 120 max-line-length = 120
extend-exclude = extend-exclude =
venv/ venv/

245
.github/workflows/common-lint.yml vendored Normal file
View File

@@ -0,0 +1,245 @@
---
# This action is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.
# Common linting.
name: common lint
on:
pull_request:
branches: [master]
types: [opened, synchronize, reopened]
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
jobs:
lint:
name: Common Lint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
python -m pip install --upgrade \
pip \
setuptools \
wheel \
cmakelang \
flake8 \
nb-clean \
nbqa[toolchain]
- name: C++ - find files
id: cpp_files
run: |
# find files
found_files=$(find . -type f \
-iname "*.c" -o \
-iname "*.cpp" -o \
-iname "*.h" -o \
-iname "*.hpp" -o \
-iname "*.m" -o \
-iname "*.mm" \
)
ignore_files=$(find . -type f -iname ".clang-format-ignore")
# Loop through each C++ file
for file in $found_files; do
for ignore_file in $ignore_files; do
ignore_directory=$(dirname "$ignore_file")
# if directory of ignore_file is beginning of file
if [[ "$file" == "$ignore_directory"* ]]; then
echo "ignoring file: ${file}"
found_files="${found_files//${file}/}"
break 1
fi
done
done
# remove empty lines
found_files=$(echo "$found_files" | sed '/^\s*$/d')
echo "found cpp files: ${found_files}"
# do not quote to keep this as a single line
echo found_files=${found_files} >> $GITHUB_OUTPUT
- name: C++ - Clang format lint
if: always() && steps.cpp_files.outputs.found_files
uses: DoozyX/clang-format-lint-action@v0.18
with:
source: ${{ steps.cpp_files.outputs.found_files }}
extensions: 'c,cpp,h,hpp,m,mm'
style: file
inplace: false
- name: CMake - find files
id: cmake_files
if: always()
run: |
# find files
found_files=$(find . -type f -iname "CMakeLists.txt" -o -iname "*.cmake")
ignore_files=$(find . -type f -iname ".cmake-lint-ignore")
# Loop through each C++ file
for file in $found_files; do
for ignore_file in $ignore_files; do
ignore_directory=$(dirname "$ignore_file")
# if directory of ignore_file is beginning of file
if [[ "$file" == "$ignore_directory"* ]]; then
echo "ignoring file: ${file}"
found_files="${found_files//${file}/}"
break 1
fi
done
done
# remove empty lines
found_files=$(echo "$found_files" | sed '/^\s*$/d')
echo "found cmake files: ${found_files}"
# do not quote to keep this as a single line
echo found_files=${found_files} >> $GITHUB_OUTPUT
- name: CMake - cmake-lint
if: always() && steps.cmake_files.outputs.found_files
run: |
cmake-lint --line-width 120 --tab-size 4 ${{ steps.cmake_files.outputs.found_files }}
- name: Docker - find files
id: dokcer_files
if: always()
run: |
found_files=$(find . -type f -iname "Dockerfile" -o -iname "*.dockerfile")
echo "found_files: ${found_files}"
# do not quote to keep this as a single line
echo found_files=${found_files} >> $GITHUB_OUTPUT
- name: Docker - hadolint
if: always() && steps.dokcer_files.outputs.found_files
run: |
docker pull hadolint/hadolint
# create hadolint config file
cat <<EOF > .hadolint.yaml
---
ignored:
- DL3008
- DL3013
- DL3016
- DL3018
- DL3028
- DL3059
EOF
failed=0
failed_files=""
for file in ${{ steps.dokcer_files.outputs.found_files }}; do
echo "::group::${file}"
docker run --rm -i \
-e "NO_COLOR=0" \
-e "HADOLINT_VERBOSE=1" \
-v $(pwd)/.hadolint.yaml:/.config/hadolint.yaml \
hadolint/hadolint < $file || {
failed=1
failed_files="$failed_files $file"
}
echo "::endgroup::"
done
if [ $failed -ne 0 ]; then
echo "::error:: hadolint failed for the following files: $failed_files"
exit 1
fi
- name: Python - flake8
if: always()
run: |
python -m flake8 \
--color=always \
--verbose
- name: Python - nbqa flake8
if: always()
run: |
python -m nbqa flake8 \
--color=always \
--verbose \
.
- name: Python - nb-clean
if: always()
run: |
output=$(find . -name '*.ipynb' -exec nb-clean check {} \;)
# fail if there are any issues
if [ -n "$output" ]; then
echo "$output"
exit 1
fi
- name: YAML - find files
id: yaml_files
if: always()
run: |
# space separated list of files
FILES=.clang-format
# empty placeholder
found_files=""
for FILE in ${FILES}; do
if [ -f "$FILE" ]
then
found_files="$found_files $FILE"
fi
done
echo "found_files=${found_files}" >> $GITHUB_OUTPUT
- name: YAML - yamllint
id: yamllint
if: always()
uses: ibiqlik/action-yamllint@v3
with:
# https://yamllint.readthedocs.io/en/stable/configuration.html#default-configuration
config_data: |
extends: default
rules:
comments:
level: error
document-start:
level: error
line-length:
max: 120
new-line-at-end-of-file:
level: error
new-lines:
type: unix
truthy:
# GitHub uses "on" for workflow event triggers
# .clang-format file has options of "Yes" "No" that will be caught by this, so changed to "warning"
allowed-values: ['true', 'false', 'on']
check-keys: true
level: warning
file_or_dir: . ${{ steps.yaml_files.outputs.found_files }}
- name: YAML - log
if: always() && steps.yamllint.outcome == 'failure'
run: |
cat "${{ steps.yamllint.outputs.logfile }}" >> $GITHUB_STEP_SUMMARY

View File

@@ -169,3 +169,8 @@ The architectures supported by these images are shown in the table below.
| [Changelog](docs/changelog.md) | [Third-Party Packages](docs/third_party_packages.md) | | [Changelog](docs/changelog.md) | [Third-Party Packages](docs/third_party_packages.md) |
</div> </div>
<details style="display: none;">
<summary></summary>
[TOC]
</details>

View File

@@ -323,3 +323,8 @@ values in most JSON.}
| [Configuration](configuration.md) | [Guides](guides.md) | | [Configuration](configuration.md) | [Guides](guides.md) |
</div> </div>
<details style="display: none;">
<summary></summary>
[TOC]
</details>

View File

@@ -160,3 +160,8 @@ It may be beneficial to build remotely in some cases. This will enable easier bu
| [Troubleshooting](troubleshooting.md) | [Contributing](contributing.md) | | [Troubleshooting](troubleshooting.md) | [Contributing](contributing.md) |
</div> </div>
<details style="display: none;">
<summary></summary>
[TOC]
</details>

View File

@@ -15,3 +15,8 @@
| [Getting Started](getting_started.md) | [Docker](../DOCKER_README.md) | | [Getting Started](getting_started.md) | [Docker](../DOCKER_README.md) |
</div> </div>
<details style="display: none;">
<summary></summary>
[TOC]
</details>

View File

@@ -2454,3 +2454,8 @@ editing the `conf` file in a text editor. Use the examples as reference.
| [Legal](legal.md) | [App Examples](app_examples.md) | | [Legal](legal.md) | [App Examples](app_examples.md) |
</div> </div>
<details style="display: none;">
<summary></summary>
[TOC]
</details>

View File

@@ -28,7 +28,7 @@ Read our contribution guide in our organization level
Sunshine and related LizardByte projects are being localized into various languages. Sunshine and related LizardByte projects are being localized into various languages.
The default language is `en` (English). The default language is `en` (English).
![](https://app.lizardbyte.dev/uno/crowdin/LizardByte_graph.svg) ![](https://app.lizardbyte.dev/dashboard/crowdin/LizardByte_graph.svg)
@admonition{Community | We are looking for language coordinators to help approve translations. @admonition{Community | We are looking for language coordinators to help approve translations.
The goal is to have the bars above filled with green! The goal is to have the bars above filled with green!
@@ -193,3 +193,8 @@ maintainers to run the tests locally.
| [Building](building.md) | [Source Code](../third-party/doxyconfig/docs/source_code.md) | | [Building](building.md) | [Source Code](../third-party/doxyconfig/docs/source_code.md) |
</div> </div>
<details style="display: none;">
<summary></summary>
[TOC]
</details>

View File

@@ -29,3 +29,8 @@ Sunshine does have some limitations, as compared to Nvidia GameStream.
| [Third-party Packages](third_party_packages.md) | [Legal](legal.md) | | [Third-party Packages](third_party_packages.md) | [Legal](legal.md) |
</div> </div>
<details style="display: none;">
<summary></summary>
[TOC]
</details>

View File

@@ -570,4 +570,9 @@ Tutorials and Guides are community generated. Want to contribute? Reach out to u
</div> </div>
<details style="display: none;">
<summary></summary>
[TOC]
</details>
[latest-release]: https://github.com/LizardByte/Sunshine/releases/latest [latest-release]: https://github.com/LizardByte/Sunshine/releases/latest

View File

@@ -532,3 +532,8 @@ going up and down. This device will be referred to as Voicemeeter Input.}
| [App Examples](app_examples.md) | [Performance Tuning](performance_tuning.md) | | [App Examples](app_examples.md) | [Performance Tuning](performance_tuning.md) |
</div> </div>
<details style="display: none;">
<summary></summary>
[TOC]
</details>

View File

@@ -25,3 +25,8 @@ concerns about using Sunshine in a commercial setting, we recommend consulting w
| [Gamestream Migration](gamestream_migration.md) | [Configuration](configuration.md) | | [Gamestream Migration](gamestream_migration.md) | [Configuration](configuration.md) |
</div> </div>
<details style="display: none;">
<summary></summary>
[TOC]
</details>

View File

@@ -18,3 +18,8 @@ Enabling *Fast Sync* in Nvidia settings may help reduce latency.
| [Guides](guides.md) | [Troubleshooting](troubleshooting.md) | | [Guides](guides.md) | [Troubleshooting](troubleshooting.md) |
</div> </div>
<details style="display: none;">
<summary></summary>
[TOC]
</details>

View File

@@ -24,3 +24,8 @@
| [Docker](../DOCKER_README.md) | [Gamestream Migration](gamestream_migration.md) | | [Docker](../DOCKER_README.md) | [Gamestream Migration](gamestream_migration.md) |
</div> </div>
<details style="display: none;">
<summary></summary>
[TOC]
</details>

View File

@@ -143,25 +143,24 @@ often grub is used to load the kernel and set its command line.)
### AMD encoding latency issues ### AMD encoding latency issues
If you notice unexpectedly high encoding latencies (e.g. in Moonlight's If you notice unexpectedly high encoding latencies (e.g. in Moonlight's
performance overlay) or strong fluctuations thereof, this is due to performance overlay) or strong fluctuations thereof, your system's Mesa
[missing support](https://gitlab.freedesktop.org/drm/amd/-/issues/3336) libraries are outdated (<24.2). This is particularly problematic at higher
in Mesa/libva for AMD's low latency encoder mode. This is particularly resolutions (4K).
problematic at higher resolutions (4K).
Only the most recent development versions of mesa include support for this
low-latency mode. It will be included in Mesa-24.2.
In order to enable it, Sunshine has to be started with a special environment
variable:
Starting with Mesa-24.2 applications can request a
[low-latency mode](https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30039)
by running them with a special
[environment variable](https://docs.mesa3d.org/envvars.html#envvar-AMD_DEBUG):
```bash ```bash
AMD_DEBUG=lowlatencyenc sunshine export AMD_DEBUG=lowlatencyenc
``` ```
Sunshine sets this variable automatically, no manual
configuration is needed.
To check whether low-latency mode is being used, one can watch the `VCLK` and To check whether low-latency mode is being used, one can watch the VCLK and DCLK
`DCLK` frequencies in `amdgpu_top`. Without this encoder tuning both clock frequencies in amdgpu_top. Without this encoder tuning both clock frequencies
frequencies will fluctuate strongly, whereas with active low-latency encoding will fluctuate strongly, whereas with active low-latency encoding they will stay
they will stay high as long as the encoder is used. high as long as the encoder is used.
### Gamescope compatibility ### Gamescope compatibility
Some users have reported stuttering issues when streaming games running within Gamescope. Some users have reported stuttering issues when streaming games running within Gamescope.
@@ -198,3 +197,8 @@ permissions on the disk.
| [Performance Tuning](performance_tuning.md) | [Building](building.md) | | [Performance Tuning](performance_tuning.md) | [Building](building.md) |
</div> </div>
<details style="display: none;">
<summary></summary>
[TOC]
</details>

View File

@@ -5,13 +5,13 @@
"dev": "vite build --watch" "dev": "vite build --watch"
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "6.6.0", "@lizardbyte/shared-web": "2024.901.195233",
"@popperjs/core": "2.11.8", "vue": "3.5.3",
"@vitejs/plugin-vue": "4.6.2",
"bootstrap": "5.3.3",
"vite": "4.5.2",
"vite-plugin-ejs": "1.6.4",
"vue": "3.4.38",
"vue-i18n": "9.14.0" "vue-i18n": "9.14.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "4.6.2",
"vite": "4.5.2",
"vite-plugin-ejs": "1.6.4"
} }
} }

View File

@@ -84,7 +84,7 @@ build() {
-D CMAKE_INSTALL_PREFIX=/usr \ -D CMAKE_INSTALL_PREFIX=/usr \
-D SUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine \ -D SUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine \
-D SUNSHINE_ASSETS_DIR="share/sunshine" \ -D SUNSHINE_ASSETS_DIR="share/sunshine" \
-D SUNSHINE_PUBLSIHER_NAME='LizardByte' \ -D SUNSHINE_PUBLISHER_NAME='LizardByte' \
-D SUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' \ -D SUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' \
-D SUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support' -D SUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support'

View File

@@ -77,7 +77,7 @@ modules:
- -DSUNSHINE_ENABLE_X11=ON - -DSUNSHINE_ENABLE_X11=ON
- -DSUNSHINE_ENABLE_DRM=ON - -DSUNSHINE_ENABLE_DRM=ON
- -DSUNSHINE_ENABLE_CUDA=ON - -DSUNSHINE_ENABLE_CUDA=ON
- -DSUNSHINE_PUBLSIHER_NAME='LizardByte' - -DSUNSHINE_PUBLISHER_NAME='LizardByte'
-DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' -DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev'
-DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support' -DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support'
sources: sources:

View File

@@ -44,7 +44,7 @@ configure.args -DBOOST_USE_STATIC=ON \
-DBUILD_WERROR=ON \ -DBUILD_WERROR=ON \
-DCMAKE_INSTALL_PREFIX=${prefix} \ -DCMAKE_INSTALL_PREFIX=${prefix} \
-DSUNSHINE_ASSETS_DIR=etc/sunshine/assets \ -DSUNSHINE_ASSETS_DIR=etc/sunshine/assets \
-DSUNSHINE_PUBLSIHER_NAME='LizardByte' \ -DSUNSHINE_PUBLISHER_NAME='LizardByte' \
-DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' \ -DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' \
-DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support' -DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support'

View File

@@ -71,7 +71,7 @@ class @PROJECT_NAME@ < Formula
-DSUNSHINE_ASSETS_DIR=sunshine/assets -DSUNSHINE_ASSETS_DIR=sunshine/assets
-DSUNSHINE_BUILD_HOMEBREW=ON -DSUNSHINE_BUILD_HOMEBREW=ON
-DSUNSHINE_ENABLE_TRAY=OFF -DSUNSHINE_ENABLE_TRAY=OFF
-DSUNSHINE_PUBLSIHER_NAME='LizardByte' -DSUNSHINE_PUBLISHER_NAME='LizardByte'
-DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' -DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev'
-DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support' -DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support'
] ]

View File

@@ -150,15 +150,14 @@ namespace nvhttp {
}; };
struct client_t { struct client_t {
std::vector<std::string> certs;
std::vector<named_cert_t> named_devices; std::vector<named_cert_t> named_devices;
}; };
struct pair_session_t { struct pair_session_t {
struct { struct {
std::string uniqueID; std::string uniqueID;
std::string deviceName;
std::string cert; std::string cert;
std::string name;
} client; } client;
std::unique_ptr<crypto::aes_t> cipher_key; std::unique_ptr<crypto::aes_t> cipher_key;
@@ -288,7 +287,6 @@ namespace nvhttp {
named_cert.cert = el.get_value<std::string>(); named_cert.cert = el.get_value<std::string>();
named_cert.uuid = uuid_util::uuid_t::generate().string(); named_cert.uuid = uuid_util::uuid_t::generate().string();
client.named_devices.emplace_back(named_cert); client.named_devices.emplace_back(named_cert);
client.certs.emplace_back(named_cert.cert);
} }
} }
} }
@@ -301,15 +299,11 @@ namespace nvhttp {
named_cert.cert = el.get_child("cert").get_value<std::string>(); named_cert.cert = el.get_child("cert").get_value<std::string>();
named_cert.uuid = el.get_child("uuid").get_value<std::string>(); named_cert.uuid = el.get_child("uuid").get_value<std::string>();
client.named_devices.emplace_back(named_cert); client.named_devices.emplace_back(named_cert);
client.certs.emplace_back(named_cert.cert);
} }
} }
// Empty certificate chain and import certs from file // Empty certificate chain and import certs from file
cert_chain.clear(); cert_chain.clear();
for (auto &cert : client.certs) {
cert_chain.add(crypto::x509(cert));
}
for (auto &named_cert : client.named_devices) { for (auto &named_cert : client.named_devices) {
cert_chain.add(crypto::x509(named_cert.cert)); cert_chain.add(crypto::x509(named_cert.cert));
} }
@@ -318,17 +312,13 @@ namespace nvhttp {
} }
void void
update_id_client(const std::string &uniqueID, std::string &&cert, op_e op) { add_authorized_client(const std::string &name, std::string &&cert) {
switch (op) {
case op_e::ADD: {
client_t &client = client_root; client_t &client = client_root;
client.certs.emplace_back(std::move(cert)); named_cert_t named_cert;
} break; named_cert.name = name;
case op_e::REMOVE: named_cert.cert = std::move(cert);
client_t client; named_cert.uuid = uuid_util::uuid_t::generate().string();
client_root = client; client.named_devices.emplace_back(named_cert);
break;
}
if (!config::sunshine.flags[config::flag::FRESH_STATE]) { if (!config::sunshine.flags[config::flag::FRESH_STATE]) {
save_state(); save_state();
@@ -500,15 +490,7 @@ namespace nvhttp {
add_cert->raise(crypto::x509(client.cert)); add_cert->raise(crypto::x509(client.cert));
auto it = map_id_sess.find(client.uniqueID); auto it = map_id_sess.find(client.uniqueID);
add_authorized_client(client.name, std::move(client.cert));
// set up named cert
named_cert_t named_cert;
named_cert.name = client.deviceName;
named_cert.cert = client.cert;
named_cert.uuid = uuid_util::uuid_t::generate().string();
client_root.named_devices.emplace_back(named_cert);
update_id_client(client.uniqueID, std::move(client.cert), op_e::ADD);
map_id_sess.erase(it); map_id_sess.erase(it);
} }
else { else {
@@ -611,7 +593,7 @@ namespace nvhttp {
} }
sess.client.uniqueID = std::move(uniqID); sess.client.uniqueID = std::move(uniqID);
sess.client.deviceName = std::move(deviceName); sess.client.name = std::move(deviceName);
sess.client.cert = util::from_hex_vec(get_arg(args, "clientcert"), true); sess.client.cert = util::from_hex_vec(get_arg(args, "clientcert"), true);
BOOST_LOG(debug) << sess.client.cert; BOOST_LOG(debug) << sess.client.cert;
@@ -632,7 +614,7 @@ namespace nvhttp {
if (hash.to_string_view() == it->second) { if (hash.to_string_view() == it->second) {
if (!otp_device_name.empty()) { if (!otp_device_name.empty()) {
ptr->second.client.deviceName = std::move(otp_device_name); ptr->second.client.name = std::move(otp_device_name);
} }
getservercert(ptr->second, tree, one_time_pin); getservercert(ptr->second, tree, one_time_pin);
@@ -715,7 +697,7 @@ namespace nvhttp {
getservercert(sess, tree, pin); getservercert(sess, tree, pin);
if (!name.empty()) { if (!name.empty()) {
sess.client.deviceName = name; sess.client.name = name;
} }
// response to the request for pin // response to the request for pin
@@ -1268,18 +1250,6 @@ namespace nvhttp {
client_t &client = client_root; client_t &client = client_root;
for (auto it = client.named_devices.begin(); it != client.named_devices.end();) { for (auto it = client.named_devices.begin(); it != client.named_devices.end();) {
if ((*it).uuid == uuid) { if ((*it).uuid == uuid) {
// Find matching cert and remove it
for (auto cert = client.certs.begin(); cert != client.certs.end();) {
if ((*cert) == (*it).cert) {
cert = client.certs.erase(cert);
removed++;
}
else {
++cert;
}
}
// And then remove the named cert
it = client.named_devices.erase(it); it = client.named_devices.erase(it);
removed++; removed++;
} }

View File

@@ -1002,7 +1002,7 @@ namespace platf {
init() { init() {
// enable low latency mode for AMD // enable low latency mode for AMD
// https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30039 // https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30039
set_env("AMD_DEBUG", "lowlatency"); set_env("AMD_DEBUG", "lowlatencyenc");
// These are allowed to fail. // These are allowed to fail.
gbm::init(); gbm::init();

View File

@@ -618,8 +618,7 @@ namespace platf {
} }
~shm_attr_t() override { ~shm_attr_t() override {
while (!task_pool.cancel(refresh_task_id)) while (!task_pool.cancel(refresh_task_id));
;
} }
capture_e capture_e

View File

@@ -52,7 +52,7 @@
"env_client_fps": "客户端请求的帧率 (int)", "env_client_fps": "客户端请求的帧率 (int)",
"env_client_gcmap": "客户端请求的游戏手柄掩码,采用 bitset/bitfield 格式 (int)", "env_client_gcmap": "客户端请求的游戏手柄掩码,采用 bitset/bitfield 格式 (int)",
"env_client_hdr": "HDR 已被客户端启用 (true/false)", "env_client_hdr": "HDR 已被客户端启用 (true/false)",
"env_client_height": "客户端请求的分辨率的高度 (int)", "env_client_height": "客户端请求的高度 (int)",
"env_client_host_audio": "客户端请求在主机播放声音 (true/false)", "env_client_host_audio": "客户端请求在主机播放声音 (true/false)",
"env_client_width": "客户端请求的分辨率的宽度 (int)", "env_client_width": "客户端请求的分辨率的宽度 (int)",
"env_displayplacer_example": "示例 - 使用 displayplacer 自动更改分辨率:", "env_displayplacer_example": "示例 - 使用 displayplacer 自动更改分辨率:",
@@ -74,7 +74,7 @@
"output_desc": "存储命令输出的文件,如果未指定,输出将被忽略", "output_desc": "存储命令输出的文件,如果未指定,输出将被忽略",
"output_name": "输出", "output_name": "输出",
"run_as_desc": "这可能是某些需要管理员权限才能正常运行的应用程序所必需的。", "run_as_desc": "这可能是某些需要管理员权限才能正常运行的应用程序所必需的。",
"wait_all": "继续串流直到所有应用进程终止", "wait_all": "继续串流直到所有应用进程退出",
"wait_all_desc": "这将继续串流直到应用程序启动的所有进程终止。 当未选中时,串流将在初始应用进程终止时停止,即使其他应用进程仍在运行。", "wait_all_desc": "这将继续串流直到应用程序启动的所有进程终止。 当未选中时,串流将在初始应用进程终止时停止,即使其他应用进程仍在运行。",
"working_dir": "工作目录", "working_dir": "工作目录",
"working_dir_desc": "应传递给进程的工作目录。例如某些应用程序使用工作目录搜索配置文件。如果不设置Apollo 将默认使用命令的父目录", "working_dir_desc": "应传递给进程的工作目录。例如某些应用程序使用工作目录搜索配置文件。如果不设置Apollo 将默认使用命令的父目录",
@@ -181,7 +181,7 @@
"follow_client_hdr_desc": "根据客户端请求自动设置串流屏幕 HDR 的开关。(不建议启用)", "follow_client_hdr_desc": "根据客户端请求自动设置串流屏幕 HDR 的开关。(不建议启用)",
"gamepad": "模拟游戏手柄类型", "gamepad": "模拟游戏手柄类型",
"gamepad_auto": "自动选择选项", "gamepad_auto": "自动选择选项",
"gamepad_desc": "选择要在主机上模拟的游戏手类型", "gamepad_desc": "选择要在主机上模拟的游戏手类型",
"gamepad_ds4": "DS4 (PS4)", "gamepad_ds4": "DS4 (PS4)",
"gamepad_ds5": "DS5 (PS5)", "gamepad_ds5": "DS5 (PS5)",
"gamepad_switch": "Nintendo Pro (Switch)", "gamepad_switch": "Nintendo Pro (Switch)",
@@ -294,7 +294,7 @@
"port_web_ui": "Web UI", "port_web_ui": "Web UI",
"qp": "量化参数 (QP)", "qp": "量化参数 (QP)",
"qp_desc": "某些设备可能不支持恒定码率。对于这些设备,则使用 QP 代替。数值越大,压缩率越高,但质量越差。", "qp_desc": "某些设备可能不支持恒定码率。对于这些设备,则使用 QP 代替。数值越大,压缩率越高,但质量越差。",
"qsv_coder": "QuickSync Coder (H264)", "qsv_coder": "QSV 编码器 (H264)",
"qsv_preset": "QSV 编码器预设", "qsv_preset": "QSV 编码器预设",
"qsv_preset_fast": "fast - 较快(较低质量)", "qsv_preset_fast": "fast - 较快(较低质量)",
"qsv_preset_faster": "faster - 更快(更低质量)", "qsv_preset_faster": "faster - 更快(更低质量)",