前言 从合肥休息好之后我回到了南京，决定接下来去哪里。因为时间不充足了，所以放弃了川藏线，尽管我还真的没有去过西藏，只走过川西小环线，那就以后再达成这个心愿吧。台风“红霞”刚走不久，“白海豚”又准备在浙江沿海登陆，所以也放弃了沿海自驾。最终确定南太行，这里也是一直魂牵梦绕我的地方。这一段旅程很紧凑，短短四天。 day 1 南京出发，前往河南省新乡市辉县市。整理好行李，去了一趟好想来买一些泡面香肠卤蛋什么的，开上我的斯柯达明锐，冲呀。上午快要11点才真正出发，但因为开的挺快挺顺畅，晚上7点就到了酒店。 下楼吃了一顿辉县特有的麻辣烫，但端上来时我询问是不是你们这边的特色“酸甜口味的麻辣烫”，老板说，“不是，很多人不习惯吃这种口味的，只有你们明确讲了需要酸甜口味才会给你们做那种” 那还有啥办法呢，好可惜，吃不到特色就算了吧，以后还有机会的。 当我做细致的路线攻略时发现天塌了，最近雨季，南太行这边有些地方山体滑坡、落石，导致武家湾和黑毛沟大峡谷封路了。然后我加了一个抖音自驾群获取了最新消息，群主分享了最保险且风景不差的路线，于是我就主要参考了这条线进行第二天的旅程。路线大致是： 宝上路-棋子山-浙水村-东柏坡天路-神龙湾挂壁观景台-井底村-高家台-鲁班天梯-石板岩小镇 美美睡觉，期待明天路上的美景。 day 2 早上7点多出发，加满油前往四十多公里之外的「崖边咖啡」，也就是「宝上路观景台」，或者「赶羊站观景台」。就是今天天气不给力，有很大的雾，暂时散不开，可惜在国家地理杂志封面图拍摄打卡点拍不到很极致的照片了。 到了崖边咖啡，要尽快找空位停车，今天是非工作日并且我来得早可能还好，大家以后想去一定要记得优先停车，多走几步路再看风景都是小事，因为越到后面停车越耽误时间才是大事。国内现在只要稍微人多的地方都是这样的，太多人出来游了，停车老大难。 空气不那么通透，因为雾气弥漫，所以先拉一下长焦拍个特写看看。 初次看到这个崖壁还是很震撼的，左侧崖壁之上就是公路，刚才就从那个方向驶来。很多崖壁像是刀切豆腐一样。 国家地理杂志封面图同款/相似机位，来这就是为了这张照片 2333。 下面应该是5A级景区宝泉旅游区的景区公路。只能景交车才能行驶🙃 我向前走了一段路，看到下面的宝泉旅游区，感慨这个观景位置也很不错啊，还是免费的，除了天气不通透，在这里吹一会山风也觉得来值了。 不知道为啥还是有很多车行驶到武家湾那边，也许还有别的小路或者他们就到途中再折返吧。反正我下山了，驶向了焦作云台山那边，然后走G207国道和乌海线到棋子山，就是网红猪八戒打卡点那里。这段路一直爬坡，还有个让我喜出望外的“叠彩洞”，我原本的攻略并没有这里，自驾群里的攻略也是建议走沿太行高速-郑辉高速-陵侯高速到棋子山，但是最终我选择了走国道，因为风景不在高速上（在的话也没办法停车欣赏和拍照）。这里让我哇哇叫，也太帅了：20条隧道，好几个隧道里都有U型弯，简直太刺激了。不过隧道里有一辆车轮子掉沟里了，大家注意安全驾驶。下图是进隧道之前拍摄的 上到山顶差不多来到了“一斗水村”，我找了荫凉处停车，拿出零食开炫，先垫吧垫吧。山顶处格外凉爽，这瓶AD钙奶都显得格外好喝。 后面继续赶路到棋子山，沿途遇到好看的风景我都尽量停车欣赏，当然停车不能影响别人，也不能给别人带来危险。下面几张这种高山小村落非常的宁静祥和，让人心情愉悦，晚上住在这里应该都不用空调还要盖被子吧。（PS：这里就是山西晋城市陵川县，一个可能不那么知名的避暑圣地） 到了棋子山这边，海拔1500多，山顶是真的凉爽，还有人铺上席子在打牌，好不惬意。 遇到一个大哥，找我搭话，后来和我讨论晚上住哪里，他说前面很多村子都有民宿，但我还坚持回县城住酒店。查了一下距离也才20多公里。 为什么回县城住酒店： 因为县城文明 服务和价格透明 还有更多的美食以及文化可以探索 我出去旅游不是很喜欢住民宿，民宿条件以及老板水平参差不平的。县城是我最爱的落脚点，地级市的市区可能千篇一律，并且价格稍高，但是县城很折中，很有性价比。 速度买好了县城中心的酒店，火速赶往，一路上非常快乐，下山的风景太好了。另外就是要提一下，陵川县城可能因为很多人前来避暑，尤其大批的河南人，加上陵川是晋城市唯一没有开发煤矿的县城，所以他们高度依赖旅游业，于是住宿相比周边其他县城以及物价水平都要稍微高一点。 今天时间还比较早，我在酒店收拾好洗了澡出来逛小县城，发现这个小县城的婚嫁门店还挺多。之前在陕西榆林，那边的街头很多洗脚店。哈哈，还真就反映了当地人民的生活吧。这也是旅行有意思的地方，能感受到不同地方不同人们的生活方式和文化差异。用随身的红米K70 拍了下面8张照片，都有比较大的压缩，方便快速加载。我觉得挺富有生活气息的，回味起来，总感慨同一片土地上，不同时空角落，就上演着截然不同的人间烟火。 这是陵川县城的崇安寺，坐落在陵川县城卧龙岗高地，就处在县城城区里，是全国重点文保单位，民间有 “先有崇安，后有陵川” 的说法。始建年代无确切记载，唐初叫丈八佛寺，北宋太平兴国元年（976）御赐名崇安寺，元明清屡经修缮。寺院建在高台之上，格局很特别：山门古陵楼地势最高，反而高于后方主殿，可以俯瞰整个陵川县城。 “太行小书场”，非常有地域特色了。围绕着太行山，这些地方真可以靠山吃山靠水吃水，当然这不是贬义，这是很正常的市场经济。何况这里是作为文化输出，我非常认同。 晚上9点出酒店来外面车上拿东西，发现只有20度，是真的好凉快啊，穿着短裤都有一丝丝凉意，也快立秋了，但是看了一下江浙沪皖，仍旧是29度，这里避暑真够nice。 day 3 今天正经打卡上文中提到的那几个点。早上并没有刻意早起，吃了当地特色“肉丸方便面”早餐，也就那样，我今天想吃正宗的山西刀削面。 从酒店出来直接前往浙水村，最后有一段很长的下坡，伴着一路的山花和美景，还有好天气，开启了一天的好心情。 路边开满了鲜花~ 小车车虽然是二手的，但是很可靠，还算好开，是EA111 1.4T + 7速干式双离合 DQ200，但是前车主刚换过机电单元。 到达浙水村，这里很有东方瑞士的感觉，上午9点多的阳光洒向大地，而这里只有23.5°C，只要不在阳光下待很久，都会感到非常舒适。但是阳光下待久了还是很晒的。 沿着公路直接打卡，这一路主要行驶在「太行一号旅游公路」，这是山西省打造太行旅游板块的大型交旅融合路网工程。北起忻州繁峙平型关，南至运城垣曲西哄哄村，纵贯忻州、阳泉、晋中、长治、晋城等六市，整体规划总里程 5217 公里，主线约 1225 公里，包含大量支线、连接线，串联起太行山沿线 350 余处自然、人文、红色景点。 到达一处印象深刻的点，这里没有护栏，平台两端都是悬崖峭壁，对面的崖壁很陡峭也很壮观。我在这里还遇到一个老外，他还主动向我说你好，我用蹩脚的英文和它简单交流了几句，他离开的时候还向我竖大拇指，我很感谢他的 kindness。 到达东柏坡天路，这里没有太行第一路（太行十六拐）惊险，这里的沥青路和路况都太好了。太行十六拐（香木河那边）以后有机会再去。这边的峡谷+公路景观不错，刚好也有荫凉处，适合吃点零食和小憩。 沿途美丽村落，这座桥就很山西。 到达神龙湾挂壁公路观景台，这里人实在是太多了，还堵车，当时也中午了太阳还大。对面的崖壁公路现在已不让通行，换成了神龙湾隧道通行，一会去「井底村」会经过。 山脚下这些是黑山羊，拉了个长焦看看👀，他们的活动空间真大！ 这个挂壁公路观景台有不少商业，我点了一份「西红柿鸡蛋刀削面」，应该是真的正宗，面条很好吃，调味也很不错，15元在这种地方已经不算贵了。 吃完午饭前往井底村，在进入神龙湾隧道之前有一个漂亮的月亮桥，但是隧道口没有停车位置，遗憾无法拍下来。这是新的神龙湾隧道，2026‑06‑20正式通车，是「神龙湾挂壁公路‑井底改建项目」的核心控制性工程。 那条老的神龙湾挂壁公路，1985年至2000年，全村八百多村民，自带干粮工具，一锤一钎，15年时间在百米悬崖上硬凿出来全长1526米、拥有39个采光天窗的通道，这曾经是井底村唯一的汽车出山通道。不禁让人感慨，更让人肃然起敬。 驱车到达了井底村，然后很快到达了高家台村，这之间没啥好看的。这时候海拔也一直在下降，我有旅途谢幕的感受，竟然还有一点不舍。 准备去“鲁班天梯”，但是看了一下导航实在是堵的可怕，堵了几公里，刚好我也累了，于是直接导航去了终点站“石板岩小镇”，这里还有漂流的项目，可惜已经超过了下午3点，漂流的票买不到了。海拔下降到700左右，我能明显感受到骄阳似火，于是带着毛巾穿上洞洞鞋去了河里洗洗干净，洗干净了开车才舒服。 接下来规划行程，我打算回南京了。刚好从这里回南京有将近900公里，于是我打算今晚入住中间的某一个小县城，将明日里程三七分。然后买了河南省开封市兰考县的酒店，就直接赶路去兰考县。 开车到酒店的途中有很多感慨，这新乡交通也太差了（整个河南不好说），到处都是三轮车，有敞篷的三轮，有豪华装修的三轮（比如有沙发座椅的三轮车），有遮雨棚的三轮，各种电三轮乱窜，毫无交通规则可言…… 当晚开车我瞪着铜铃般大的眼睛，生怕遇到交通事故。最终安全抵达，享受了一个不错的睡眠。 day 4 今天从兰考县回南京，出发前瞥了一下兰考火车站，裕禄大道和裕禄公园。在兰考加满油出发，小的民营加油站居然还送早餐，我的早餐也省了。 说到民营加油站，昨天从林州（石板岩小镇就是河南安阳市林州市的）到兰考，路上看到巨多的我没见过名字的民营加油站。 东方运输公司加油站 储峰加油站 云龙加油站 兴业石化 中亚石化 卫辉市鑫鑫加油站 核心石化 太行石化 民营加油站是真发达啊…… 回到了南京，热得出奇，和我昨天早上在浙水村那种感受形成了巨大的反差，谁知道今天还是“立秋”。 结语 旅程结束，非常的依依不舍，但是工作要继续，这种旅行本是生活的调味料。短暂山野的日子已落幕，那些绝壁峡谷间的山风都化作心底的片段，妥帖收藏。人终究要回归平凡的烟火日常，旅途不能长久停留，但那些所见所感，会留在记忆里，往后的日子还能慢慢回味。
终于又到了属于我的假期，今年的假期有两个星期，我可要好好安排一下。准备分成两段，第一周去深圳香港澳门，第二周暂时没想好，但是决定了是自驾，皖南很多地方都转过了，所以有几个选项 川藏线 南太行 浙江海岸线，比如仓南168黄金海岸线，中国东海岸1号公路 先写我的深圳香港澳门游记吧，具体的第二周安排我是在出发前一天才真正做好决定的。 day 1 今天的飞机飞深圳，因为台风“红霞”，延误了一个多小时，好在10点多正常降落深圳宝安机场，但是到达我哥那已经晚上12点了。这个台风稍微打乱了我的游览节奏。 day 2 第二天，深圳福田一直在下雨，直到下午天气才稍稍明朗些，但仍然会滴落一些雨滴。不过我在房间待不住，去了深圳湾人才公园打卡，并且拍了一些照片。 这两天深圳比较凉快，反而是南京顶着骄阳，还有35度高温，稍稍成功的一次避暑。找了辆共享单车，沿着深圳湾滨海大道骑了 4 5 公里。海湾区除了湿度太高，其他的条件还是蛮舒适的，因为风多，气温也不是很高。晚上和我哥吃了当地特色“隆江猪脚饭”，还是非常不错滴。 此时台风红霞的中心已经北上，但是深圳仍受其外围云系笼罩，饱含水汽的云团漫过楼宇，层云垂落，缭绕于城市高楼之间，看着颇有意境。 云层太厚，可惜今晚没有晚霞了。不然这个打卡点是个拍摄晚霞、夕阳🌇的好地方。 day 3 今天计划徒步海岸线，看过大海却没有进入过沙滩，刚好去大梅沙，小梅沙走走沙滩。从深铁盐田墟下车，沿着海岸步道（其实叫“盐梅路”）总体是向着东北徒步。今天有一些阳光，还是有些晒人的。 大梅沙，深圳东部大鹏湾的海湾。数百年前这里只是一处偏僻的客家小渔村，世代村民靠出海捕鱼、耕海为生，山海闭塞，与世隔绝深圳盐田。 谁曾想，乘着时代浪潮，昔日的渔家村落，蜕变为如今繁华发达的滨海小镇。月牙形的沙滩、林立的酒店楼宇，山海与城市在此相融。 第一次触到海滩的细沙，细碎的颗粒绵软顺滑，从指缝间悄悄滑落。它们本是山石的碎屑，经海浪千万次拍打打磨，才化为这般细腻模样。潮起潮落，造物的循环仿佛在此触手可及。 今天是工作日，但是海滩上仍然有很多人玩水，如果是炎热的工作日，这里就真的是下饺子。这边的海水挺干净的，确实很适合玩水，不在滨海城市生活的我有些羡慕。 day 4 HK是真的蛮出片的，但是限于篇幅，只挑选了最喜欢的一些分享给大家。今天一大早8点多就到了香港，但是没料到下了大雨，台风的影响仍未结束，这种天气也见怪不怪的。好在下午放晴~ 我最喜欢太平山了，在香港市区生活，处处显得逼仄，街道、居室都局促狭小，高楼挤得很近，但因为香港有很多山，让我觉得又很相得益彰。虽然那些空间不属于你，但大部分也都是公共的，有山有海还有盘山公路，感觉累了就可以跑山，开车到山顶吹吹风，很喜欢这种感觉了。 另外也赞美一下太平山顶看中环以及对面维多利亚港那片的夜景，真的很赞。 晚上回深已经22点多了，都没赶上福田口岸，最终在罗湖口岸抵深。 day 5 又是下雨的一天，加上昨天3万多步走累了，就不想再去香港了，本来还打算续一下签注再去趟香港。 下午去打卡深圳华强北，这个对于我这种数码迷还是挺有吸引力的。打算买个华强北悦虎耳机，高仿 AirPods Pro的，但是搜了一下水太深：又是悦虎，又是洛达，还有杰里、中科蓝汛，还有FlyCC软件验证，各种名词（有主板方案，有芯片名称），这些倒不会出现在展台。但是展台上只有五代、六代、七代、八代，真七代这些模糊的词语，让人眼花缭乱的，不如京东自营买大厂成品 tws 耳机。看了好几家，也试用了一下，感觉还是不错的，就是需求不大，最后就没买。再记录几个有意思的点： 我看有家卖共田的风扇，我说这个图案（logo）明明就是共田，他们居然说不是，倒是没说清楚具体是什么牌子 看到有人手搓电池，是软包的，我发挥e人属性，问他我可以拍一下吗，他表情严肃的拒绝了 😂 我居然买了一个触控笔，哈哈，老板说10元，被我还价到了7元。一头是塑胶的，另一头是导电布那种的，质感挺不错的，来华强北最大收获！（将在下文配图） day 6 我一个人的澳门一日游。一大早7点多乘上了前往珠海拱北口岸的大巴，现在涨价了要49.9，看小红书之前只要19.8，也是最近一年才涨价的，遇到节假日可能还更贵。 澳门老街眼见之处，也总是斑驳陈旧，墙皮剥落，街巷狭小。可一经镜头定格，褪色的墙面、复古的招牌，便沉淀出满满的肌理与故事，世俗的旧貌，化作浓郁的复古氛围感，也很出片。 澳门街头的日本元素相比香港也更多，丰田本田日产的车子，还有三菱，铃木等国内现在很少见的品牌。摩托车也有非常多的 Honda，便利店、居酒屋、唐吉诃德、药妆、动漫 IP，很浓厚的日本氛围。 在美狮美高梅看到了坤坤的演唱会海报，是真的很有风格嘞。 中午都没有吃饭，因为在大三巴一路试吃，还有澳门美高梅和美狮美高梅免费的小食饮品几乎都吃饱了。 下午坐着免费的发财车回口岸，今天也是接近3万步，又是特种兵的一天。 行笔至此，我的深圳香港澳门行就差不多结束了。第二天选择乘坐高铁返回了合肥，在合肥修整两天后我又返回了南京，准备下一场旅程。
机械革命泰钽 plus linux Debian Wayland 独显直连调优全记录
机械革命泰钽 Plus 游戏本在 Linux Debian GNOME Wayland 下流畅使用诊断艰辛历程 一、软硬件配置 硬件 项目 规格 型号 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) 二、双显卡 vs 独显直连：两难抉择 2.1 混合输出模式 (MSHybrid) 的问题 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 混合渲染就更加年轻。十几年的工程积累差距，不是短期内能抹平的。 Waydroid 正常 — Android 容器通过 Mesa 调用 Intel iGPU 做 GPU 加速 腾讯会议各项功能正常 — 屏幕共享打 patch 后也能正常创建分享，别人能看到 桌面流畅度不佳 — GNOME 动画卡顿，窗口拖拽/切换时有可感知的延迟 补充：混合模式下若改用 X11 显示协议，流畅度问题同样可以得到缓解——X11 的 GPU 调度路径更成熟，PRIME 同步开销较低。但笔者不选择此方案，因为 Wayland 是 Linux 桌面显示的明确未来方向，且大部分日常软件（包括通过 XWayland 兼容层运行的）在 Wayland 下已足够稳定。放弃 Wayland 换 X11 是走回头路。 2.2 为什么不能只用 Intel 核显 (iGPU Only) 最理想的情况似乎是 BIOS 设为 iGPU Only，只用 Intel 核显驱动内置屏幕，简单省电。但这是不可能的，原因在于本游戏本的硬件设计： HDMI 和 USB-C（DP Alt Mode）视频输出接口在物理上直连到了 RTX 3060 独显，而非 Intel 核显。 这意味着： 若 BIOS 禁用 NVIDIA 独显（iGPU Only），HDMI 和 USB-C 接口完全无信号输出 笔者日常外接两台显示器（一台 HDMI + 一台 USB-C），这两个接口离开独显就无法使用 所以 iGPU Only 模式从一开始就被硬件设计排除了 因此实际可选的模式只有两种：MSHybrid（双显卡混合输出） 和 dGPU Only（独显直连）。 2.3 独显直连模式 (dGPU Only) 的问题 BIOS 切换为独显直连后，所有渲染由 RTX 3060 承担，桌面流畅度大幅提升。但带来三个问题： 腾讯会议 webcam 黑屏 — 摄像头画面无法显示 腾讯会议屏幕共享失败 — 无法创建分享，别人也看不到（混合模式下打 patch 后已修复的部分，在独显下仍不行） Waydroid 不可用 — 无解（详见下文 2.3） 2.4 Waydroid 在 NVIDIA 独显下不可用的根因 参见 waydroid/waydroid#1619。 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，全面转向 dGPU Only 既然 Waydroid 使用频率不高，而桌面流畅度与日常体验息息相关，最终决定： BIOS 设为 dGPU Only（独显直连），放弃 Waydroid。 3.1 受影响的软件 软件 状态 说明 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 3.2 NVIDIA GPU 锁频服务（提升桌面流畅度） 独显直连能改善流畅度，但 NVIDIA 私有驱动在默认情况下会根据负载动态调整 GPU 频率。桌面合成器（Mutter）的渲染负载波动较大，GPU 在低频↔高频之间频繁切换，导致 GNOME 动画仍有偶尔的掉帧。 为此创建了 nvidia-clock-unlock.service 系统服务，在启动时： 启用 NVIDIA 持久化模式（nvidia-smi -pm 1），防止 GPU 在空闲时进入深度休眠 锁定 GPU 最低频率为 1200 MHz（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 无法完全进入最低功耗状态，闲置功耗略高（对本游戏本影响不大，日常插电使用）。 3.3 死重量但保留的包（为日后切回混合模式留余地） 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 模块时不生效，占空间极小，保留以免日后切回混合模式时需重装。 3.4 内核参数清理 # /etc/default/grub 中以下 i915 参数可删除（独显直连下 i915 模块不加载）： i915.enable_psr=0 i915.enable_fbc=1 i915.enable_guc=3 四、腾讯会议在 dGPU Only 下的完整修复方案 4.1 Webcam 黑屏修复 现象：启动腾讯会议后，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。 4.2 屏幕共享修复 现象：点击"共享屏幕"无反应，或能发起共享但别人看到白屏。 根因（来自 wemeet-screenshare-patch 技术细节）： Hunk 0：libscreen_share_module.so 中 DBus 异步调用顺序错误 — Start 调用放在了 SelectSources 之后而未等待其完成，依赖竞态条件。xdg-desktop-portal-gnome 后端将 SelectSources 立即返回、Start 弹窗等待用户选择显示器，掩盖了此 bug；但在 xdg-desktop-portal-wlr 后端则会必然失败。 Hunk 1a/1b：PipeWire 颜色格式协商硬编码了 BGRx 格式，部分 portal 后端不支持，导致对方看到白屏。补丁中的 libhook.so 劫持缓冲区路径做了 BGRx↔RGBx 转换。 本机修复过程： 按 patch README 执行 Step 1 (运行 python3 patch.py) 和 Step 2 (添加 LD_PRELOAD)，能发起共享但别人看到白屏（颜色格式问题）。 参考 Issue #2，创建并执行 reverse_colors.py 撤销 Hunk 1a/1b 的颜色格式劫持，同时删除 LD_PRELOAD 行。 最终效果：只保留 Hunk 0（DBus 异步调用修复），去掉颜色格式转换，屏幕共享恢复正常，别人能看到且颜色正确。 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 4.3 修复后腾讯会议功能状态 功能 状态 备注 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）组合方案完全可用。 附录 A：相关链接 AUR wemeet-bin 评论：https://aur.archlinux.org/packages/wemeet-bin wemeet-screenshare-patch：https://github.com/Matheritasiv/wemeet-screenshare-patch white screen Issue #2 (实际上这个 issue 就是我创建的)：https://github.com/Matheritasiv/wemeet-screenshare-patch/issues/2 Waydroid NVIDIA 支持讨论：https://github.com/waydroid/waydroid/discussions/1619 附录 B：/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 $*
为了解决我的机械革命无界 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= 参数无效 本机使用 SOF/avs 驱动栈（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 下不生效 修复后该文件应当为空（或直接删除），避免误导 强制使用传统 HDA（snd-intel-dspcfg.dsp_driver=1）会丢失内置 DMIC 音频拓扑（ALC256 Codec 节点路由） ┌──────────┐ 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 涉及知识点 ALSA 驱动栈 层级 组件 说明 用户态 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 寄存器 UCM2 关键文件 文件 作用 /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
记录一下我删除相机 SD 卡当中废片的工作流
采用 python 脚本实现（python3）。支持图片（JPG/ARW/HEIF 等）和视频（MP4 + 配套 XML 元数据）的筛选删除。 相关说明： Linux/mac 电脑，如果你是 windows 电脑那么脚本需要稍加改造 相机当中开启了拍摄的照片按照日期文件夹存储，这种功能，否则可能一个文件夹下的照片数量特别多，你需要维护一个特别长的 keep.txt keep.txt 当中的文件名可以是完整文件名，也可以不包含扩展名。 a. 如果是完整文件名，那脚本就根据完整文件名匹配去保留/删除文件 b. 如果只包含文件名 stem，没有扩展名，将匹配所有包含 stem 的文件名，进而执行保留/删除逻辑。比如 keep.txt 当中有这样一行 HDK09432 ，那这些文件 HDK09432.JPG, HDK09432.ARW, HDK09432.HEIF 都会被保留，这尤其适用于你开启了 JPEG/RAW 拍摄，那么一张图片会有两个文件 支持模拟运行，只需要在最后添加 --dry-run 支持的扩展名：.jpg .jpeg .png .arw .heic .heif .hif .dng .mp4 .xml 索尼视频的 XML 元数据文件会自动匹配对应的 MP4 主文件（如 C0054M01.XML 跟随 C0054.MP4 同进退），无需在 keep.txt 中单独列出 照片工作流 索尼 JPEG 照片扩展名是 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_media.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_media.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 视频工作流 索尼 A7C2 录制视频后，存储卡上的目录结构为 PRIVATE/M4ROOT/CLIP/。与照片不同，视频不按日期分子目录，所有日期的视频文件都平铺在同一个 CLIP/ 目录下，因此 keep.txt 会较长。不过首次维护好之后，每次拍摄后只需要在末尾追加新增的 clip 号即可。 每个视频片段会生成： C0054.MP4 — 视频主文件 C0054M01.XML — 配套元数据文件（自动跟随 MP4 同进退） cd /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/ ls C0054.MP4 C0054M01.XML C0055.MP4 C0055M01.XML C0056.MP4 C0056M01.XML C0057.MP4 C0057M01.XML C0061.MP4 C0061M01.XML C0062.MP4 C0062M01.XML C0063.MP4 C0063M01.XML C0068.MP4 C0068M01.XML C0070.MP4 C0070M01.XML C0071.MP4 C0071M01.XML C0074.MP4 C0074M01.XML C0076.MP4 C0076M01.XML C0077.MP4 C0077M01.XML C0079.MP4 C0079M01.XML C0080.MP4 C0080M01.XML C0083.MP4 C0083M01.XML C0084.MP4 C0084M01.XML C0085.MP4 C0085M01.XML C0086.MP4 C0086M01.XML C0087.MP4 C0087M01.XML C0088.MP4 C0088M01.XML C0089.MP4 C0089M01.XML C0090.MP4 C0090M01.XML C0091.MP4 C0091M01.XML C0092.MP4 C0092M01.XML C0093.MP4 C0093M01.XML C0094.MP4 C0094M01.XML C0095.MP4 C0095M01.XML C0096.MP4 C0096M01.XML keep.txt 内容（只写 stem，不包含扩展名）： $cat keep.txt # start to record keep.txt list C0054 C0055 C0056 C0057 C0061 C0062 C0063 C0068 C0070 C0071 C0074 C0076 C0077 C0080 C0083 C0086 C0092 C0094 C0095 C0096 # 2026-07-04 先模拟运行确认预期： $python3 ~/Downloads/myapps/delete_unwanted_media.py ./keep.txt --dry-run ========== 执行模式 ========== DRY RUN [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0079M01.XML [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0079.MP4 [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0084M01.XML [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0084.MP4 [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0085M01.XML [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0085.MP4 [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0087M01.XML [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0087.MP4 [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0088M01.XML [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0088.MP4 [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0089M01.XML [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0089.MP4 [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0090M01.XML [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0090.MP4 [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0091M01.XML [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0091.MP4 [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0093M01.XML [DRY-RUN] 将删除: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0093.MP4 ========== 保留文件 ========== 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0054M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0054.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0055M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0055.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0056M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0056.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0057M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0057.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0061M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0061.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0062M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0062.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0063M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0063.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0068M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0068.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0071M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0071.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0070M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0070.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0074M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0074.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0077M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0077.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0076M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0076.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0080M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0080.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0083M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0083.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0086M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0086.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0092M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0092.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0094M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0094.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0095M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0095.MP4 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0096M01.XML 保留: /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0096.MP4 ========== 统计 ========== 模式: DRY-RUN 计划删除文件数: 18 保留文件数: 40 ========== 删除列表 ========== /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0079M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0079.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0084M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0084.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0085M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0085.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0087M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0087.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0088M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0088.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0089M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0089.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0090M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0090.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0091M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0091.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0093M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0093.MP4 ========== 保留列表 ========== /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0054M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0054.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0055M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0055.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0056M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0056.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0057M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0057.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0061M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0061.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0062M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0062.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0063M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0063.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0068M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0068.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0071M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0071.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0070M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0070.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0074M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0074.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0077M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0077.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0076M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0076.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0080M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0080.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0083M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0083.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0086M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0086.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0092M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0092.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0094M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0094.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0095M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0095.MP4 /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0096M01.XML /run/media/dk/708D-3AF3/PRIVATE/M4ROOT/CLIP/C0096.MP4 确认无误后去掉 --dry-run 执行实际删除。 脚本内容 $cat ~/Downloads/myapps/delete_unwanted_media.py #!/usr/bin/env python3 import os import sys TARGET_EXTS = {".jpg", ".jpeg", ".png", ".arw", ".heic", ".heif", ".hif", ".dng", ".mp4", ".xml"} 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 or raw.startswith("#"): 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 get_effective_stem(filename, mp4_stems): stem, ext = os.path.splitext(filename) if ext.lower() == ".xml" and mp4_stems: match = "" for mp4_stem in mp4_stems: if len(mp4_stem) > len(match) and stem.startswith(mp4_stem): match = mp4_stem if match: return match return stem def is_target_file(filename): ext = os.path.splitext(filename)[1].lower() return ext in TARGET_EXTS def main(): if len(sys.argv) < 2: print("Usage: python3 delete_unwanted_media.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): mp4_stems = [os.path.splitext(f)[0] for f in files if f.lower().endswith(".mp4")] for file in files: if not is_target_file(file): continue full_path = os.path.join(root, file) stem = get_effective_stem(file, mp4_stems) 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 keep.txt 内容示例（视频，支持 # 注释行）： $cat keep.txt # start to record keep.txt list C0054 C0055 C0056 C0057 C0061 C0062 C0063 C0068 C0070 C0071 C0074 C0076 C0077 C0080 C0083 C0086 C0092 C0094 C0095 C0096 # 2026-07-04
Linux Desktop 使用 NVIDIA 独显驱动 Google Earth Pro 和 WeChat
更新说明 2026年6月17日 09:00 gnome 桌面自带这样的功能，右键就能“使用独立显卡启动”，看下图 原理 NVIDIA 官方提供了 PRIME Render Offload 机制，通过环境变量让指定程序走独显渲染： __NV_PRIME_RENDER_OFFLOAD=1 — 告诉 NVIDIA 驱动将 GL/Vulkan 请求路由到独显 __GLX_VENDOR_LIBRARY_NAME=nvidia — 强制 GLX 使用 NVIDIA 的 vendor 库 适用条件 双显卡（Intel 核显 + NVIDIA 独显）笔记本 已安装 NVIDIA 闭源驱动（nvidia-driver） 桌面环境不限（GNOME / KDE / XFCE 等均可） 操作步骤 1. 修改 .desktop 文件 将系统目录下的 .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 2. 注销并重新登录 让 GNOME Shell 重新加载 .desktop 文件缓存。 3. 验证 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 子进程。 说明 Chrome 未纳入：日常浏览网页、看视频等场景 Intel 核显已足够，独显无感知收益且徒增功耗发热。如有 3D/WebGL 重负载需求，可自行添加 --use-gl=egl 参数。 环境变量直接写在 Exec 行：避免了对 shell alias 或外部脚本的依赖，桌面菜单点击即可生效。 恢复默认：删除 ~/.local/share/applications/ 下对应的 .desktop 文件即可回到系统默认配置。 为什么不使用独显直连？虽然改成独显直连，桌面都会变流畅，大部分程序都会默认走英伟达独显，比如 telegram-desktop，但是对我来说有一个致命性问题，腾讯会议的视频功能无法使用了，摄像头也无法调用，无法分享桌面，别人分享桌面我这边查看也是黑屏，这个问题暂时无法解决，只能依赖腾讯会议那边针对性开发：在英伟达独显上正常工作
GitHub 地址：https://github.com/hellodk34/linux-quick-translate 在 Linux 桌面环境快速查词/翻译句子，绑定系统全局快捷键。支持各种 Linux 发行版和不同的 DE（桌面环境）。详细食用方法请看 GitHub 选中文本 → 复制（ Ctrl+C ）→ 按 Super+C 弹出结果。 单个英文单词：本地 sdcv 词典查询 句子/段落：在线翻译 API 这样在浏览器或者系统中的任何地方阅读英文文献/文章都能快速翻译，复制文章的全部文本也能翻译整篇文章。 截图展示： 欢迎使用！
开发了一个基于和风天气 API 的 Android 天气应用
使用截图 介绍请看 GitHub，这里懒得再写一遍了。地址 https://github.com/hellodk34/checkitout_weather_android
由于 Linux 桌面没有一个好用的天气程序就写了一个跨平台的CheckitoutWeather
vibe coding的程序。暂时构建了 win 和 linux 的。mac 没设备暂时。 开源以及下载地址： GitHub ，使用的和风天气API ，由于 API收费，免费的有额度但是不多，所以开源版是无 api auth的。使用了更新的 JWT 认证，更安全，受支持也更久（类似 LTS ），传统的 API KEY 认证方式将很快受到请求量的限制。 功能： 实时天气：温度、体感温度、湿度、降水、气压、风向风力、能见度 昨日天气 + 未来 7 天预报 空气质量 (AQI) 与首要污染物 紫外线指数与等级描述 日出 / 日落时间 城市搜索、收藏管理 亮色 / 暗色主题切换 使用截图如下 欢迎下载使用。
给 caesium-image-compressor 图片压缩程序构建了 Linux AppImage v2.8.5 最新版
欢迎使用 linux 桌面的朋友们使用，构建脚本都开源了，开源在 https://github.com/hellodk34/caesium-image-compressor 原来有一个维护者 https://github.com/larygwil/caesium-image-compressor 但是他停更了，止步于 v2.6.0 ，并且项目没有开启 issues ，于是我就自己来了。 这个图片压缩程序我昨晚用了，傍晚出去拿相机拍了几张照片，压缩了效果很不错，并且保持了原有分辨率。前段时间我常用索尼的 Creators' App 的 2M 传输的选项，虽然每张照片也还能看，并且体积只有 500KB 左右，但是被砍成了 200 万像素…… 以前我都用 squoosh 的，但是 squoosh 做批量压缩搞个好用的 flow 还是比较麻烦和困难的，这个 GUI 程序正中我的口味。原作者构建了 win/macOS 程序，但是缺少 Linux 这边的构建。 使用截图 随机赠送一张昨晚拍的照片 😁