2026-06-24 10:21:00
| 项目 | 规格 |
|---|---|
| 型号 | MECHREVO Taitan Series GM7TG0M |
| CPU | 11th Gen Intel Core i7-11800H × 16 (8C/16T, Tiger Lake-H) |
| 独显 | NVIDIA GeForce RTX 3060 Laptop GPU (6GB GDDR6) |
| 核显 | Intel UHD Graphics (Tiger Lake-H GT1, 集成于 i7-11800H) |
| 内存 | 64 GiB DDR4 |
| 磁盘 1 | CT240BX500SSD1 240GB SATA SSD |
| 磁盘 2 | Fanxiang S500PRO 1TB NVMe SSD |
| 磁盘 3 | IM2P33F8-512GD 512GB NVMe SSD |
| 固件 | N.1.07MRO06 |
| BIOS 显卡模式 | dGPU Only (独显直连) / MSHybrid (双显卡混合输出) |
| 项目 | 版本 |
|---|---|
| 操作系统 | Debian GNU/Linux 13 (trixie) |
| 架构 | x86_64 |
| 桌面环境 | GNOME 48.7 |
| 窗口系统 | Wayland |
| 内核 | Linux 6.12.90+deb13.1-amd64 |
| NVIDIA 驱动 | 595.80 (私有驱动) |
| NVIDIA VA-API | nvidia-vaapi-driver 0.0.13 (NVDEC 后端) |
| PipeWire | 1.4.2 |
| 腾讯会议 | v3.26.10.401 (deb 包安装于 /opt/wemeet) |
BIOS 中设为双显卡混合输出时,系统主 GPU 是 Intel 核显,桌面合成器(Mutter)由核显驱动。但笔者的两台外接显示器(一台 4K 27 寸、一台 1080P 24 寸)通过 HDMI 和 USB-C 直连到了 RTX 3060 独显,这意味着:外接屏幕的最终画面输出必须经过 NVIDIA 独显。每一帧渲染流程为 Intel 核显合成→经 PCIe 总线拷贝到 NVIDIA 显存→NVIDIA 输出到屏幕,这个跨 GPU 的 PRIME 缓冲区同步过程引入了显著的延迟和掉帧;同时 Mutter 同时管理两个 GPU 的 framebuffer,帧时序难以对齐,进一步加剧了卡顿感。
为什么 Windows 没这个问题? Windows 下 NVIDIA Optimus 的混合输出走的是一个更高效的路径:NVIDIA 驱动内置硬件拷贝引擎(cross-adapter copy engine),独显渲染的画面通过 PCIe 直接写进核显的 framebuffer 然后输出到屏幕,不需要等待双向同步和帧对齐。而 Linux 的 PRIME 方案目前依赖通用 DMA-BUF 机制进行跨 GPU 缓冲区共享,多了一层软件调度开销,在 4K 高分辨率下带宽压力更大,卡顿感就非常明显。本质上不是硬件不行,是 Linux 图形栈在双 GPU 调度上还没做到 Windows 的成熟度。NVIDIA 在 Windows 下的图形驱动已经打磨了超过 25 年(自 1999 年 GeForce 256 发布算起),Optimus 双显卡切换技术也已在 Windows 上迭代了 15 年以上;而 Linux 下的 PRIME 多 GPU 同步方案直到 2016 年前后才逐渐可用,Wayland 下的双 GPU 混合渲染就更加年轻。十几年的工程积累差距,不是短期内能抹平的。
补充:混合模式下若改用 X11 显示协议,流畅度问题同样可以得到缓解——X11 的 GPU 调度路径更成熟,PRIME 同步开销较低。但笔者不选择此方案,因为 Wayland 是 Linux 桌面显示的明确未来方向,且大部分日常软件(包括通过 XWayland 兼容层运行的)在 Wayland 下已足够稳定。放弃 Wayland 换 X11 是走回头路。
最理想的情况似乎是 BIOS 设为 iGPU Only,只用 Intel 核显驱动内置屏幕,简单省电。但这是不可能的,原因在于本游戏本的硬件设计:
HDMI 和 USB-C(DP Alt Mode)视频输出接口在物理上直连到了 RTX 3060 独显,而非 Intel 核显。
这意味着:
因此实际可选的模式只有两种:MSHybrid(双显卡混合输出) 和 dGPU Only(独显直连)。
BIOS 切换为独显直连后,所有渲染由 RTX 3060 承担,桌面流畅度大幅提升。但带来三个问题:
Waydroid 维护者 electrikjesus 于 2025 年 12 月明确表态:
Android uses only Mesa drivers. No way to get around it.
Android 图形栈的 GPU 加速只能通过 Mesa 体系内的驱动实现。NVIDIA 私有驱动(包括 nvidia-open 内核模块)不属于 Mesa 生态,waydroid 无法调用它为 Android 容器渲染界面。
NVIDIA 支持的唯一例外是更换为
nouveau开源驱动,但nouveau在 RTX 3060 上的性能极差,没有实用价值。
既然 Waydroid 使用频率不高,而桌面流畅度与日常体验息息相关,最终决定:
BIOS 设为 dGPU Only(独显直连),放弃 Waydroid。
| 软件 | 状态 | 说明 |
|---|---|---|
| Waydroid | 不可用 | 硬伤,无解 |
| 腾讯会议 webcam | 已修复 | 见第四章 |
| 腾讯会议屏幕共享 | 已修复 | 见第四章 |
| kooha | 已卸载 | VA-API 编码依赖,已用 GNOME Screenshot + ffmpeg NVENC 替代 |
| 音频输入输出 | 正常 | 之前测试时为空是因为 systemctl --user stop pipewire.socket 关掉了 PipeWire,与独显直连无关 |
| GNOME 桌面 | 流畅 | RTX 3060 渲染 + nvidia-clock-unlock 锁频,体验显著改善 |
| 其他软件 | 正常 | Chrome、VS Code、飞书、LibreOffice、GIMP、Krita、VLC、Docker、Flatpak 等均不依赖 Intel GPU |
独显直连能改善流畅度,但 NVIDIA 私有驱动在默认情况下会根据负载动态调整 GPU 频率。桌面合成器(Mutter)的渲染负载波动较大,GPU 在低频↔高频之间频繁切换,导致 GNOME 动画仍有偶尔的掉帧。
为此创建了 nvidia-clock-unlock.service 系统服务,在启动时:
nvidia-smi -pm 1),防止 GPU 在空闲时进入深度休眠nvidia-smi -lgc 1200,2100),确保合成器始终获得足够的渲染算力# /etc/systemd/system/nvidia-clock-unlock.service
[Unit]
Description=Unlock NVIDIA GPU clock floor for smooth Wayland compositing
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/usr/bin/nvidia-smi -pm 1
ExecStart=/usr/bin/nvidia-smi -lgc 1200,2100
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
启用方式:
sudo systemctl daemon-reload
sudo systemctl enable --now nvidia-clock-unlock.service
代价:GPU 无法完全进入最低功耗状态,闲置功耗略高(对本游戏本影响不大,日常插电使用)。
i965-va-driver # Intel 老 GPU VA-API 驱动
intel-media-va-driver # Intel 新 GPU VA-API 驱动
firmware-intel-graphics # Intel GPU 固件
libdrm-intel1 # Intel DRM 用户态库
libigdgmm12 # Intel 显存管理库
以上包在不加载 i915 模块时不生效,占空间极小,保留以免日后切回混合模式时需重装。
# /etc/default/grub 中以下 i915 参数可删除(独显直连下 i915 模块不加载):
i915.enable_psr=0 i915.enable_fbc=1 i915.enable_guc=3
现象:启动腾讯会议后,webcam 预览画面黑屏,无法显示视频。
根因:xcast 日志中 eglCreateWindowSurface 返回 error:3005(EGL_BAD_CONFIG)。wemeet 以 X11(XCB) 后端运行在 XWayland 下,NVIDIA EGL 无法将 XWayland 的 X11 窗口句柄转换为 EGL Window Surface。
关键线索:AUR wemeet-bin 评论区 pinned 评论(by anlorsp, 2025-03-08):
对于 N 卡视频黑屏的问题,可以尝试为腾讯会议单独设置
__EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/50_mesa.json环境变量(不要全局设置该变量!)。在双显卡环境下可以修复黑屏问题,在单 NVIDIA 显卡环境下未测试。
本机验证:dGPU Only 模式(即单 NVIDIA)下,设置此变量后 webcam 加载成功。原理:强制 wemeet 走 Mesa 的 libEGL_mesa.so.0,走 llvmpipe 软件渲染路径,虽然性能不如硬件加速,但可以正常创建 EGL Window Surface 并显示摄像头画面。
修复步骤:编辑 /opt/wemeet/wemeetapp.sh,在第 53 行添加:
export __EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/50_mesa.json
注意:此处必须有
export,仅写变量赋值不导出的话子进程wemeetapp继承不到,变量无效。
当前完整脚本内容见文末 附录 B。
现象:点击"共享屏幕"无反应,或能发起共享但别人看到白屏。
根因(来自 wemeet-screenshare-patch 技术细节):
libscreen_share_module.so 中 DBus 异步调用顺序错误 — Start 调用放在了 SelectSources 之后而未等待其完成,依赖竞态条件。xdg-desktop-portal-gnome 后端将 SelectSources 立即返回、Start 弹窗等待用户选择显示器,掩盖了此 bug;但在 xdg-desktop-portal-wlr 后端则会必然失败。BGRx 格式,部分 portal 后端不支持,导致对方看到白屏。补丁中的 libhook.so 劫持缓冲区路径做了 BGRx↔RGBx 转换。本机修复过程:
python3 patch.py) 和 Step 2 (添加 LD_PRELOAD),能发起共享但别人看到白屏(颜色格式问题)。reverse_colors.py 撤销 Hunk 1a/1b 的颜色格式劫持,同时删除 LD_PRELOAD 行。reverse_colors.py 代码(保存为 .py 文件后用 sudo python3 执行):
#!/usr/bin/env python3
"""Reverse Hunk 1a/1b (color format patches) while keeping Hunk 0 (DBus fix)."""
import mmap
import os
import sys
REVERSE_PATCHES = {
"/opt/wemeet/bin/modules/screen_share/libscreen_share_module.so": [
(0x450fb6, bytes.fromhex("08")),
(0x4566e4, bytes.fromhex("8b45c08b4808")),
(0x6b1951, bytes.fromhex("4889e54883ec1048897df8488b7df8e88b01")),
(0x6b1964, bytes.fromhex("004889c7e8b30100004883c4105dc3662e0f1f84")),
],
"/opt/wemeet/lib/libxcast.so": [
(0xfedbfa, bytes.fromhex("660f1f44")),
(0xfedc3c, bytes.fromhex("23")),
(0xfedc4b, bytes.fromhex("4883")),
(0xfedc4f, bytes.fromhex("5b5d415c415d415e415fc3660f1f440000")),
],
}
def apply(path, patches):
print(f"Patching: {path}")
with open(path, "r+b") as fh:
with mmap.mmap(fh.fileno(), 0, access=mmap.ACCESS_WRITE) as mm:
for offset, new_bytes in patches:
current = mm[offset:offset+len(new_bytes)]
print(f" 0x{offset:08x}: {current.hex()} => {new_bytes.hex()}")
mm.seek(offset)
mm.write(new_bytes)
mm.flush()
print(" OK\n")
for f, patches in REVERSE_PATCHES.items():
apply(f, patches)
print("Done. Hunks 1a/1b reversed. Hunk 0 (DBus fix) retained.")
执行后删除启动脚本中的 LD_PRELOAD 行:
sudo sed -i '/^export LD_PRELOAD.*libhook\.so/d' /opt/wemeet/wemeetapp.sh
| 功能 | 状态 | 备注 |
|---|---|---|
| Webcam 预览 | 正常 |
50_mesa.json → llvmpipe 软件渲染 |
| 观看别人共享屏幕 | 正常 | 软解 + 软渲染,稍慢但可用 |
| 创建屏幕共享给别人看 | 正常 | Hunk 0 DBus 修复 |
| 共享画面颜色 | 正常 | 已撤销 Hunk 1a/1b |
| 音频输入/输出 | 正常 | PipeWire 正常启动即可 |
| 视频硬件编解码 | 关闭 (hwdec:0, hwenc:0) | 走 Mesa llvmpipe 软件路径 |
| 维度 | 混合输出 (MSHybrid) | 独显直连 (dGPU Only) |
|---|---|---|
| 桌面流畅度 | 差 | 好 |
| Waydroid | 可用 | 不可用 |
| 腾讯会议 webcam | 正常 | 已修复(Mesa llvmpipe 兜底) |
| 腾讯会议屏幕共享 | 打 patch 后正常 | 打 patch 后正常 |
| NVIDIA VA-API 硬解 | NVDEC + Intel 都可用 | 仅 NVDEC |
| NVIDIA 硬编 | NVENC 正常 | NVENC 正常 |
核心妥协:放弃 Waydroid,换取桌面流畅度。腾讯会议通过 __EGL_VENDOR_LIBRARY_FILENAMES + wemeet-screenshare-patch(仅 Hunk 0)组合方案完全可用。
/opt/wemeet/wemeetapp.sh 当前内容#!/bin/bash
os_release="/etc/os-release"
if [[ -e ${os_release} ]];then
source /etc/os-release
main=`echo ${VERSION_ID} | awk -F . '{print $1}'`
case $ID in
ubuntu)
if [[ ${main} -le "16" ]];then
zenity --info --title="腾讯会议" --text="腾讯会议检测到您操作系统版本过低,请升级系统到ubuntu18.04或以上版本!" --width=350 --height=100
exit 1
fi
if [[ ${main} -le "18" ]];then
if [ $XMODIFIERS ];then
im_module=$XMODIFIERS
echo 'use XMODIFIERS'
export QT_IM_MODULE=${im_module#*=}
elif [ $GTK_IM_MODULE ];then
echo 'use GTK_IM_MODULE'
export QT_IM_MODULE=${GTK_IM_MODULE}
fi
echo ${QT_IM_MODULE}
fi
;;
*)
;;
esac
fi
if [ "$XDG_SESSION_TYPE" = "wayland" ];then
if [ -f "/opt/x11-wayland/x11-ext.sh" ];then
source /opt/x11-wayland/x11-ext.sh
else
export QT_QPA_PLATFORM=xcb
export XDG_SESSION_TYPE=x11
unset WAYLAND_DISPLAY
export WEMEET_XWAYLAND=1
fi
fi
SELF=$(readlink -f "$0")
HERE=${SELF%/*}
export LC_ALL=zh_CN.UTF-8
export PATH="${HERE}/bin${PATH:+:$PATH}"
export LD_LIBRARY_PATH="${HERE}/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
export QT_PLUGIN_PATH="${HERE}/plugins"
export TZ=Asia/Shanghai
export __EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/50_mesa.json
exec wemeetapp $*
2026-06-18 16:46:00
为了解决我的机械革命无界 14 pro 笔记本在 linux debian testing(forky) 下的自带麦克风、自带扬声器、插入 3.5mm 耳机这三个场景下,对应硬件都能正常工作的问题,遂有了此文。
前景提要:机械革命无界14Pro笔记本debian forky成功驱动内置扬声器和麦克风
| 项目 | 值 |
|---|---|
| 机型 | MECHREVO WUJIE14 PRO |
| CPU | 12th Gen Intel Core i7-12650H |
| 声卡 | Intel Alder Lake PCH-P HD Audio (8086:51c8) |
| Codec | Realtek ALC256 (10ec:0256) |
| 子系统 ID | 1d05:170b |
| 固件 | SOF (Sound Open Firmware) 签名固件 2025.05.1 |
| OS | Debian forky/sid, GNOME 50, Wayland |
| 内核 | 7.0.10+deb14-amd64 |
| PipeWire | 1.6.6 + WirePlumber 1.6.6 |
| ALSA UCM2 | alsa-ucm-conf 1.2.15.3-1 |
确保以下三个场景全部正常工作:
| 场景 | 状态 |
|---|---|
| 内置数字麦克风(DMIC) | 始终正常 |
| 内置扬声器 | 始终正常 |
| 3.5mm 耳机插入后 | 修复前无声,修复后正常 |
插入 3.5mm 耳机后声音仍然从笔记本内置扬声器输出,耳机无声音。系统设置输入设备显示正常(内置数字麦克风可用)。
┌─────────────────────────────────────────────────────────┐
│ 问题 1:硬件插孔检测不工作 │
│ ALSA 控制 "Headphone Jack" 始终 = off │
│ 即使耳机物理插入,Codec (Node 0x21) 的 pin sense 未触发 │
│ 可能原因:SOF 驱动与 ALC256 pin sense 事件处理有兼容问题 │
├─────────────────────────────────────────────────────────┤
│ 问题 2:UCM2 启动时禁用 Auto-Mute │
│ /usr/share/alsa/ucm2/HDA/init.conf │
│ → cset "name='Auto-Mute Mode' off" │
│ 设计意图:让 PipeWire 用户态管理切换,但 UCM2 配置有缺陷 │
├─────────────────────────────────────────────────────────┤
│ 问题 3:Speaker 和 Headphones 在不同 HiFi Profile 中 │
│ 两者共用 PlaybackPCM "hw:0",ACP 拆分成了两个互斥 Profile │
│ Headphones 依赖 JackControl,端口永远 "not available" │
│ 导致 PipeWire 无法激活耳机 DSP 通路 │
└─────────────────────────────────────────────────────────┘
model= 参数无效snd_soc_skl_hda_dsp),声卡名 sof-hda-dsp
snd-hda-intel 模块虽然被加载,但依赖计数为 0,不参与实际驱动/etc/modprobe.d/alsa-alc256.conf 中配置的 options snd-hda-intel model=xxx 在 SOF 下不生效snd-intel-dspcfg.dsp_driver=1)会丢失内置 DMIC ┌──────────┐
hw:0 PCM ──────┤ DAC 0x02 │──┬── Pin 0x14 (Speaker) ── 扬声器
│ (Speaker)│ │
└──────────┘ │
├── Pin 0x1b (unused)
└── Pin 0x21 (HP β) ── 耳机(辅)
┌──────────┐
hw:0 PCM ──────┤ DAC 0x03 │───── Pin 0x21* (HP α) ── 耳机(主)
│(Headphone)│
└──────────┘
* 表示活动连接
关键:两个 DAC 接收同一路 PCM 音频流,SOF DSP 固件根据激活的 Profile 控制哪个 DAC 通路工作。
| 尝试 | 方法 | 结果 | 原因 |
|---|---|---|---|
| 1 |
model=laptop-amic → headset-mic
|
无效 | SOF 驱动忽略 model= 参数 |
| 2 | 方案A:加 dsp_driver=1 切传统 HDA + headset-mic
|
耳机无效、麦消失 | 传统 HDA 不支持 DMIC;headset-mic 合并插孔类型不匹配 |
| 3 | SOF 下手动切 Headphones Profile | 端口 not available 无法路由 | JackControl 依赖失败检测 |
| 4 | Speaker Profile 下手动 amixer 开耳机 | 无声音 | DSP 未激活耳机通路,DAC 0x03 无 stream |
| 5 | amixer toggle 脚本(操作 Playback Switch) | 调音量时扬声器被激活 | WirePlumber EnableSequence 每回路由激活都重开 Speaker |
绕过硬件插孔检测,通过切换 Profile 来切换耳机/扬声器,让 WirePlumber 独立管理每个 Profile 的音量。
1. 修改 UCM2 配置,移除耳机 JackControl
# 备份
sudo cp /usr/share/alsa/ucm2/HDA/HiFi-analog.conf \
/usr/share/alsa/ucm2/HDA/HiFi-analog.conf.bak
# 注释 JackControl 行(保留缩进)
sudo sed -i 's/^\([[:space:]]*\)JackControl "${var:hpjack}"/\1#JackControl "${var:hpjack}"/' \
/usr/share/alsa/ucm2/HDA/HiFi-analog.conf
修改位置:/usr/share/alsa/ucm2/HDA/HiFi-analog.conf 第 156 行
PlaybackSwitch "${var:hpvol} Playback Switch"
- JackControl "${var:hpjack}"
+ #JackControl "${var:hpjack}"
效果:Headphones 端口不再依赖 Headphone Jack ALSA 控制,始终显示为可用(如同 Speaker 的 availability unknown)。
2. 创建快捷键切换脚本
~/.local/bin/toggle-audio.sh:
#!/bin/bash
# 在扬声器和耳机之间切换
CARD="alsa_card.pci-0000_00_1f.3-platform-skl_hda_dsp_generic"
SPK_PROFILE="HiFi (HDMI1, HDMI2, HDMI3, Mic1, Mic2, Speaker)"
HP_PROFILE="HiFi (HDMI1, HDMI2, HDMI3, Headphones, Mic1, Mic2)"
SPK_SINK="alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__Speaker__sink"
HP_SINK="alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__Headphones__sink"
current=$(pactl list cards 2>/dev/null | grep "Active Profile" | grep -o "Speaker")
if [ -n "$current" ]; then
pactl set-card-profile "$CARD" "$HP_PROFILE"
sleep 0.3
pactl set-default-sink "$HP_SINK"
for i in $(pactl list sink-inputs short 2>/dev/null | awk '{print $1}'); do
pactl move-sink-input "$i" "$HP_SINK" 2>/dev/null
done
notify-send -a "音频切换" "已切换到耳机" -i audio-headphones
else
pactl set-card-profile "$CARD" "$SPK_PROFILE"
sleep 0.3
pactl set-default-sink "$SPK_SINK"
for i in $(pactl list sink-inputs short 2>/dev/null | awk '{print $1}'); do
pactl move-sink-input "$i" "$SPK_SINK" 2>/dev/null
done
notify-send -a "音频切换" "已切换到扬声器" -i audio-speakers
fi
chmod +x ~/.local/bin/toggle-audio.sh
3. 绑定快捷键
GNOME 设置 → 键盘 → 查看及自定义快捷键 → 自定义快捷键 → 添加:
/home/dk/.local/bin/toggle-audio.sh
Super+Alt+S
4. 重启音频服务
systemctl --user restart wireplumber pipewire pipewire-pulse
alsa-ucm-conf 包更新后会覆盖修改的配置文件,需重新执行 sed 命令/usr/share/alsa/ucm2/HDA/HiFi-analog.conf.bak
sudo cp /usr/share/alsa/ucm2/HDA/HiFi-analog.conf.bak /usr/share/alsa/ucm2/HDA/HiFi-analog.conf
| 层级 | 组件 | 说明 |
|---|---|---|
| 用户态 | PipeWire / WirePlumber | 音频路由、流管理、音量控制 |
| 用户态 | ACP (ALSA Card Profile) | 解析 UCM2 配置,生成 Profile/Port |
| 用户态 | ALSA UCM2 | 声卡用例配置(Volume、Switch、Jack、PCM) |
| 内核态 | SOF 固件 | DSP 音频处理管线 |
| 内核态 | snd_soc_skl_hda_dsp |
ASoC machine driver |
| 内核态 | snd_hda_codec_alc269 |
ALC256 Codec 驱动 |
| 硬件 | ALC256 Codec | DAC/ADC/Pin Complex 寄存器 |
| 文件 | 作用 |
|---|---|
/usr/share/alsa/ucm2/HDA/init.conf |
初始化序列(含 Auto-Mute off) |
/usr/share/alsa/ucm2/HDA/HiFi-analog.conf |
模拟设备定义(Speaker/Headphones/Mic) |
/usr/share/alsa/ucm2/Intel/sof-hda-dsp/HiFi.conf |
SOF HiFi 顶层用例 |
/usr/share/alsa/ucm2/Intel/sof-hda-dsp/HiFi-sof.conf |
SOF 特定覆盖(DRC/EQ/固件) |
# 查看声卡
cat /proc/asound/cards
aplay -l
# 查看 Codec 寄存器(Pin Sense、DAC 音量、静音状态)
cat /proc/asound/card0/codec#0
# 查看 ALSA 控制和插孔状态
amixer -c0 contents | grep -E "Jack|Auto-Mute|name="
# 查看 PipeWire 状态
pactl info | grep "Default Sink"
pactl list cards | grep -A2 "Active Profile"
pactl list sinks short
# 查看 snd_hda_intel 是否被使用
ls /sys/module/snd_hda_intel/holders/
cat /sys/module/snd_hda_intel/refcnt
# 查看内核参数
cat /proc/cmdline
# 手动控制 Codec
amixer -c0 cset name='Headphone Playback Switch' on,on
amixer -c0 cset name='Auto-Mute Mode' Enabled
2026-06-14 10:05:00
采用 python 脚本实现(python3)。
相关说明:
--dry-run
JPG,RAW 拍摄文件扩展名是 ARW,HEIF 拍摄扩展名是 HIF (Apple 的 HEIF 照片扩展名是 HEIC)cd /run/media/dk/708D-3AF3/DCIM/15660613/
ls
HDK09429.JPG HDK09432.JPG HDK09435.JPG HDK09438.JPG HDK09441.JPG HDK09444.JPG HDK09447.JPG
HDK09430.JPG HDK09433.JPG HDK09436.JPG HDK09439.JPG HDK09442.JPG HDK09445.JPG HDK09448.JPG
HDK09431.JPG HDK09434.JPG HDK09437.JPG HDK09440.JPG HDK09443.JPG HDK09446.JPG HDK09449.JPG
$python3 ~/Downloads/myapps/delete_unwanted_images.py ./keep.txt --dry-run
========== 执行模式 ==========
DRY RUN
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09429.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09430.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09431.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09433.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09434.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09435.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09436.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09437.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09439.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09443.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09444.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09445.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09446.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09447.JPG
[DRY-RUN] 将删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09448.JPG
========== 保留文件 ==========
保留: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09432.JPG
保留: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09438.JPG
保留: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09440.JPG
保留: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09441.JPG
保留: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09442.JPG
保留: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09449.JPG
========== 统计 ==========
模式: DRY-RUN
计划删除文件数: 15
保留文件数: 6
========== 删除列表 ==========
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09429.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09430.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09431.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09433.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09434.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09435.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09436.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09437.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09439.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09443.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09444.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09445.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09446.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09447.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09448.JPG
========== 保留列表 ==========
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09432.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09438.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09440.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09441.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09442.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09449.JPG
$python3 ~/Downloads/myapps/delete_unwanted_images.py ./keep.txt
========== 执行模式 ==========
REAL DELETE
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09429.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09430.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09431.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09433.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09434.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09435.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09436.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09437.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09439.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09443.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09444.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09445.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09446.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09447.JPG
已删除: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09448.JPG
========== 保留文件 ==========
保留: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09432.JPG
保留: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09438.JPG
保留: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09440.JPG
保留: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09441.JPG
保留: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09442.JPG
保留: /run/media/dk/708D-3AF3/DCIM/15660613/HDK09449.JPG
========== 统计 ==========
模式: DELETE
计划删除文件数: 15
保留文件数: 6
实际删除成功数: 15
========== 删除列表 ==========
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09429.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09430.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09431.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09433.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09434.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09435.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09436.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09437.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09439.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09443.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09444.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09445.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09446.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09447.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09448.JPG
========== 保留列表 ==========
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09432.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09438.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09440.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09441.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09442.JPG
/run/media/dk/708D-3AF3/DCIM/15660613/HDK09449.JPG
ls
HDK09432.JPG HDK09438.JPG HDK09440.JPG HDK09441.JPG HDK09442.JPG HDK09449.JPG keep.txt
脚本内容:
$cat ~/Downloads/myapps/delete_unwanted_images.py
#!/usr/bin/env python3
import os
import sys
IMAGE_EXTS = {".jpg", ".jpeg", ".png", ".arw", ".heic", ".heif", ".hif", ".dng"}
def load_keep_list(path):
exact_keep = set()
stem_keep = set()
with open(path, "r", encoding="utf-8") as f:
for line in f:
raw = line.strip()
if not raw:
continue
stem, ext = os.path.splitext(raw)
if ext: # 有扩展名 → 精确匹配
exact_keep.add(raw)
else: # 无扩展名 → stem 匹配
stem_keep.add(stem)
return exact_keep, stem_keep
def is_image_file(filename):
ext = os.path.splitext(filename)[1].lower()
return ext in IMAGE_EXTS
def main():
if len(sys.argv) < 2:
print("Usage: python3 delete_unwanted_images.py ./keep.txt [--dry-run]")
sys.exit(1)
keep_path = sys.argv[1]
dry_run = "--dry-run" in sys.argv[2:]
root_dir = os.getcwd()
if not os.path.exists(keep_path):
print(f"[ERROR] keep.txt not found: {keep_path}")
sys.exit(1)
exact_keep, stem_keep = load_keep_list(keep_path)
to_delete = []
to_keep = []
# 扫描文件
for root, dirs, files in os.walk(root_dir):
for file in files:
if not is_image_file(file):
continue
full_path = os.path.join(root, file)
stem = os.path.splitext(file)[0]
if (file in exact_keep) or (stem in stem_keep):
to_keep.append(full_path)
else:
to_delete.append(full_path)
deleted_count = 0
print("\n========== 执行模式 ==========")
print("DRY RUN" if dry_run else "REAL DELETE")
# 删除逻辑
for path in to_delete:
if dry_run:
print(f"[DRY-RUN] 将删除: {path}")
else:
try:
os.remove(path)
print(f"已删除: {path}")
deleted_count += 1
except Exception as e:
print(f"[ERROR] 删除失败 {path}: {e}")
# 保留输出
print("\n========== 保留文件 ==========")
for path in to_keep:
print(f"保留: {path}")
# 统计
print("\n========== 统计 ==========")
print(f"模式: {'DRY-RUN' if dry_run else 'DELETE'}")
print(f"计划删除文件数: {len(to_delete)}")
print(f"保留文件数: {len(to_keep)}")
if not dry_run:
print(f"实际删除成功数: {deleted_count}")
# 列表输出
print("\n========== 删除列表 ==========")
for path in to_delete:
print(path)
print("\n========== 保留列表 ==========")
for path in to_keep:
print(path)
if __name__ == "__main__":
main()
keep.txt 内容示例
$cat keep.txt
HDK09432
HDK09438
HDK09440
HDK09441
HDK09442
HDK09449
2026-06-12 16:09:00
gnome 桌面自带这样的功能,右键就能“使用独立显卡启动”,看下图

NVIDIA 官方提供了 PRIME Render Offload 机制,通过环境变量让指定程序走独显渲染:
__NV_PRIME_RENDER_OFFLOAD=1 — 告诉 NVIDIA 驱动将 GL/Vulkan 请求路由到独显__GLX_VENDOR_LIBRARY_NAME=nvidia — 强制 GLX 使用 NVIDIA 的 vendor 库将系统目录下的 .desktop 文件拷贝到用户目录(避免被系统更新覆盖):
cp /usr/share/applications/google-earth-pro.desktop ~/.local/share/applications/
cp /usr/share/applications/wechat.desktop ~/.local/share/applications/
修改 Exec 行,在程序路径前加上环境变量:
sed -i 's|^Exec=/opt/google/earth/pro/google-earth-pro %f|Exec=env __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia /opt/google/earth/pro/google-earth-pro %f|' \
~/.local/share/applications/google-earth-pro.desktop
sed -i 's|^Exec=/usr/bin/wechat %U|Exec=env __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia /usr/bin/wechat %U|' \
~/.local/share/applications/wechat.desktop
让 GNOME Shell 重新加载 .desktop 文件缓存。
nvidia-smi
启动 Google Earth Pro 和 WeChat 后,应看到类似输出:
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| 0 N/A N/A 2327 G /usr/bin/gnome-shell 130MiB |
| 0 N/A N/A 25233 G ...gle/earth/pro/googleearth-bin 112MiB |
| 0 N/A N/A 25399 G ...ns-seed-version --log-level=2 72MiB |
+-----------------------------------------------------------------------------------------+
googleearth-bin 为 Google Earth Pro,...ns-seed-version 为 WeChat 的 GPU 子进程。
--use-gl=egl 参数。~/.local/share/applications/ 下对应的 .desktop 文件即可回到系统默认配置。2026-06-01 10:25:05
GitHub 地址:https://github.com/hellodk34/linux-quick-translate
在 Linux 桌面环境快速查词/翻译句子,绑定系统全局快捷键。支持各种 Linux 发行版和不同的 DE(桌面环境)。详细食用方法请看 GitHub
选中文本 → 复制( Ctrl+C )→ 按 Super+C 弹出结果。
这样在浏览器或者系统中的任何地方阅读英文文献/文章都能快速翻译,复制文章的全部文本也能翻译整篇文章。
截图展示:
欢迎使用!
2026-06-01 10:06:31
使用截图


介绍请看 GitHub,这里懒得再写一遍了。地址 https://github.com/hellodk34/checkitout_weather_android