2025-07-13 17:05:16
家里卫生间的锁有些不太灵,于是买了一把球形锁,打算自己换上。
在换的过程中发现原有球形锁的螺帽出现了不同程度的生锈,以及拧动过程中导致的滑丝,在搜索了诸多解决方案之后,发现了一个相对有效果的方法,这里记录一下,以备日后查阅。
使用热吹风对着螺丝吹5分钟以上,吹完之后迅速泼上冷水(冰水效果更佳),然后再尝试使用螺丝刀拧松。
原理就是热胀冷缩。在尝试此方法之前,我使用了网传的加电胶布,以及暴力拆除,均没有太多效果。
此次更换卫生间门把手,也让我得到了一些启发,第一就是在容易发生生锈的环境中,不一定要等到物品最终丧失功能再选择更换,完全可以提前更换,这样就可以避免等到真正丧失物理功能需要更换时,拆卸过程中螺丝滑丝等诸多问题。
第二就是为什么在更换卫生间球形锁的过程中,我会进入心流状态,短暂忘却了现实时间的流逝,一门心思只想如何完成更换,目前有诸多猜测,但无法形成完整结论,待进一步探讨。
第三,在安装完成之后,我意识到普通锁的内部结构其实并不是特别复杂,也没有特别的精妙,这似乎也应证了那一句,这世上本没有锁,偷的人多了,才有了锁,以及锁只防君子,防不了小人。
利用热胀冷缩解决螺丝滑丝问题最先出现在龙鲲博客。
2025-07-05 13:54:29
长话短说。需要观看一个没有字幕的外语视频,然后发现PotPlayer(以下简称:Pot)支持自动识别字幕并且可以实时翻译,这里记录一下折腾过程。
一共分为两步,第一步是自动识别字幕。
Pot内单击右键,选择字幕->创建有声字幕->创建有声字幕。
转换引擎:选择Whisper-Faster,点击下载按钮,下载引擎。
型号:选择small(更高版本对算力要求更高,视情况选择)。
型号由于众所周知的原因,无法直接进行下载,可以选择使用魔搭社区进行下载。
faster-whisper-small https://www.modelscope.cn/models/angelala00/faster-whisper-small/files
下载后点击型号两字,会跳转型号存放路径,将下载的文件移动至该文件即可。
然后点击开始按钮,即可开始生成当前语言的字幕文件。
第二步则是实时翻译,原理是借助翻译产品的API来实时进行翻译。
目前内置的翻译产品API除必应首年免费以外,其他均需收费使用。
PS:必应首年免费,注册也略微麻烦,非必要不推荐尝试。
这里有热心网友开发了国内百度翻译的插件,下载地址如下:
https://github.com/fjqingyou/PotPlayer_Subtitle_Translate_Baidu
文件下载之后移动至PotPlayer\Extension\Subtitle\Translate路径,重启Pot即可正常使用。
将百度翻译的API填入Pot内,即可正常开始实时翻译,由于国内产品注册没有难度,这里不做过多介绍。
路径:选择字幕->实时字幕翻译->实时字幕翻译设置。
个人使用之后感觉效果还可以,但是问题也很多,例如,电脑配置较低的情况下,字幕识别的速度相对来说比较慢,再者实时翻译可能存在接口的调用频率限制,例如限制在多少秒钟内只允许调用多少次,所以导致部分内容无法正常显示,当然也有可能是原字幕文件本身夹杂了多种语言,这种情况下,手动翻译都会出错,而API只是代替手动,自然而然也会出错了。
参考:
https://blog.csdn.net/duke_ding2/article/details/144973709
https://www.cnblogs.com/chasingdreams2017/p/18746470
http://www.potplayercn.com/course/potplayer-generate-subtitles-from-voice.html
2025-07-04 10:29:30
======2025.7.4 13:44 更新======
因为除了用B站学习以外,可能还会浏览一些其他视频,但其他视频并不需要跳转片头片尾。
所以,迭代这个版本,增加功能如下:
1、对指定BV号视频跳过片头片尾
2、可自定义每个视频的跳过时间
如果没有这两个需求,可以继续使用V1.2的版本。
PS:两个版本均兼容B站空降助手。
// ==UserScript== // [url=home.php?mod=space&uid=170990]@name[/url] B站指定视频片头片尾跳过 // [url=home.php?mod=space&uid=467642]@namespace[/url] [url=http://tampermonkey.net/]http://tampermonkey.net/[/url] // [url=home.php?mod=space&uid=1248337]@version[/url] 1.4 // @description 仅对指定BV号视频跳过片头片尾,可自定义每个视频的跳过时间 // [url=home.php?mod=space&uid=686208]@AuThor[/url] l9zp6 // [url=home.php?mod=space&uid=195849]@match[/url] [url=https://www.bilibili.com/video/]https://www.bilibili.com/video/[/url]* // @match [url=https://www.bilibili.com/bangumi/play/]https://www.bilibili.com/bangumi/play/[/url]* // [url=home.php?mod=space&uid=609072]@grant[/url] GM_getValue // @grant GM_setValue // @grant GM_addStyle // ==/UserScript== (function() { 'use strict'; // ========================== 配置区域 ========================== // 默认跳过时间(当未指定视频的自定义时间时使用) const DEFAULT_INTRO_SKIP_TIME = 0; // 默认不跳过片头 const DEFAULT_OUTRO_SKIP_TIME = 0; // 默认不跳过片尾 // 指定视频的自定义跳过时间(支持多个BV号) // 格式: 'BV号': { intro: 片头时间, outro: 片尾时间 } const CUSTOM_SKIP_TIMES = { 'BV14yzCYgE9Y': { intro: 10, outro: 5 }, // 示例1:自定义此BV号的跳过时间 'BV14yzCYgE9S': { intro: 5, outro: 3 }, // 示例2:添加更多BV号 // 可继续添加更多BV号配置... }; // ============================================================= // 存储状态信息 let lastVideoKey = ''; // 视频唯一标识 let lastUrl = ''; // 上次的完整URL let isWaitingForNextVideo = false; // 是否等待下一个视频 let lastProcessTime = 0; // 上次处理时间 let skipCooldown = false; // 跳过冷却标志 let forceProcess = false; // 强制处理标志 // 添加样式 GM_addStyle(` .skip-hint { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: rgba(0, 0, 0, 0.7); color: white; padding: 10px 20px; border-radius: 5px; font-size: 18px; z-index: 10000; opacity: 0; transition: opacity 0.3s; } .skip-hint.show { opacity: 1; } `); // 创建提示元素 function createHintElement() { const hint = document.createElement('div'); hint.className = 'skip-hint'; document.body.appendChild(hint); return hint; } // 获取播放器元素 function getPlayer() { return document.querySelector('bwp-video, video'); } // 获取播放器容器 function getPlayerContainer() { return document.querySelector('#bilibili-player, .bpx-player-container'); } // 显示提示 function showHint(text) { let hint = document.querySelector('.skip-hint'); if (!hint) { hint = createHintElement(); } hint.textContent = text; hint.classList.add('show'); // 获取播放器容器 const playerContainer = getPlayerContainer(); // 检查是否全屏 const isFullscreen = document.fullscreenElement || document.webkitFullscreenElement; if (playerContainer && !isFullscreen) { // 非全屏状态,将提示添加到播放器容器内 playerContainer.appendChild(hint); // 重置位置样式 hint.style.top = '50%'; hint.style.left = '50%'; hint.style.transform = 'translate(-50%, -50%)'; } else { // 全屏状态,提示保持在body内 document.body.appendChild(hint); } setTimeout(() => { hint.classList.remove('show'); }, 2000); // 提示显示2秒 } // 获取当前视频的BV号 function getCurrentBVId() { const pathMatch = location.pathname.match(/\/video\/(BV\w+)/); return pathMatch ? pathMatch[1] : ''; } // 生成视频唯一标识(只考虑BV号和p参数) function generateVideoKey() { const bvid = getCurrentBVId(); if (!bvid) return ''; const pMatch = location.search.match(/[?&]p=(\d+)/); const pValue = pMatch ? `_p${pMatch[1]}` : ''; return `${bvid}${pValue}`; } // 获取当前视频的跳过时间配置 function getSkipTimes() { const bvid = getCurrentBVId(); // 如果是指定视频,使用自定义时间,否则使用默认时间 if (CUSTOM_SKIP_TIMES[bvid]) { console.log(`使用自定义跳过时间 for ${bvid}:`, CUSTOM_SKIP_TIMES[bvid]); return CUSTOM_SKIP_TIMES[bvid]; } return { intro: DEFAULT_INTRO_SKIP_TIME, outro: DEFAULT_OUTRO_SKIP_TIME }; } // 检查视频是否在指定列表中 function isVideoIncluded() { const bvid = getCurrentBVId(); return !!CUSTOM_SKIP_TIMES[bvid]; } // 获取视频标题 function getVideoTitle() { const titleElement = document.querySelector('h1.title, .media-info-title'); return titleElement ? titleElement.textContent.trim() : ''; } // 检查是否是新视频 function isNewVideo() { const currentVideoKey = generateVideoKey(); const currentUrl = location.href; let isNew = currentVideoKey !== lastVideoKey; // 如果URL相同但需要强制处理 if (!isNew && currentUrl === lastUrl && forceProcess) { console.log('强制处理相同URL的视频'); isNew = true; forceProcess = false; } if (isNew) { console.log('检测到新视频:', currentVideoKey); lastVideoKey = currentVideoKey; lastUrl = currentUrl; } else if (currentUrl !== lastUrl) { console.log('URL参数变化但视频未变:', currentUrl); lastUrl = currentUrl; } return isNew; } // 获取并更新记忆进度 function processMemoryProgress(player) { // 如果不是指定视频,直接返回 if (!isVideoIncluded()) return; const videoKey = generateVideoKey(); if (!videoKey) return; const memoryTime = GM_getValue(`bilibili_memory_${videoKey}`, 0); const { intro } = getSkipTimes(); // 如果记忆进度在片头时间之后,不做处理 if (memoryTime > intro) { console.log(`检测到记忆进度:${memoryTime}秒,超过片头时间${intro}秒,不跳过`); return; } // 如果是新视频且进度为0,跳转到片头跳过时间 if (player.currentTime <= intro) { console.log(`跳转到片头跳过时间:${intro}秒`); player.currentTime = intro; showHint(`已跳过${intro}秒片头`); } } // 检查片尾并跳过 function checkAndSkipOutro(player, duration) { // 如果不是指定视频,直接返回 if (!isVideoIncluded()) return; // 防止无限循环跳转 if (skipCooldown) return; const { outro } = getSkipTimes(); const currentTime = player.currentTime; // 检查是否在片尾区域 if (duration - currentTime <= outro) { // 防止在短时间内重复跳转 const now = Date.now(); if (now - lastProcessTime < 2000) { console.log('检测到重复跳转尝试,跳过此次操作'); return; } lastProcessTime = now; // 设置冷却期 skipCooldown = true; setTimeout(() => { skipCooldown = false; }, 2000); // 跳转到离片尾0.5秒处,确保能触发下一集 player.currentTime = duration - 0.5; console.log(`已跳过${outro}秒片尾,跳转到${duration - 0.5}秒`); showHint(`已跳过${outro}秒片尾`); // 标记为等待下一个视频,并设置强制处理 isWaitingForNextVideo = true; forceProcess = true; } } // 检查是否应该处理新视频 function shouldProcessNewVideo(player) { if (!player) return false; // 如果正在等待下一个视频且播放器已加载新视频 if (isWaitingForNextVideo && player.currentTime < 5) { console.log('检测到自动连播的新视频'); isWaitingForNextVideo = false; return true; } // 检查是否是新视频 return isNewVideo(); } // 主处理函数 function processVideo() { const player = getPlayer(); if (!player) return; // 检查是否应该处理新视频 if (shouldProcessNewVideo(player)) { console.log('检测到需要处理的新视频:', getVideoTitle()); // 处理记忆进度 processMemoryProgress(player); } // 保存进度 const videoKey = generateVideoKey(); if (videoKey) { GM_setValue(`bilibili_memory_${videoKey}`, player.currentTime); } // 检查片尾 if (player.duration && player.duration > 0) { checkAndSkipOutro(player, player.duration); } } // 初始化 function init() { console.log('B站片头片尾跳过脚本已加载'); // 监听播放器状态变化 const player = getPlayer(); if (player) { player.addEventListener('loadedmetadata', () => { console.log('播放器加载了新的元数据'); processVideo(); }); player.addEventListener('timeupdate', () => { // 播放器时间更新时检查 processVideo(); }); } // 监听URL变化 new MutationObserver(() => { console.log('检测到URL变化'); setTimeout(() => { processVideo(); }, 300); }).observe(document, { childList: true, subtree: true, attributes: true, attributeFilter: ['href'] }); // 定时检查 setInterval(() => { const player = getPlayer(); if (player && !player.paused) { processVideo(); } }, 1000); // 初始处理 setTimeout(processVideo, 1000); } // 等待页面加载完成 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();
======2025.7.4 原文======
众所周知,目前B站已经成为了最大的学习乐园之一,拥有海量的学习资源。
但在学习的过程中,很多的学习视频会考虑宣传等目的,在片头或者片尾加上与视频内容实质无关的片段,极其影响学习。
因为太久没写Javascript,以及不喜欢重复造轮子的想法,在尝试完市面上大部分的脚本之后。
我选择使用AI编写了脚本的大部分代码,目前已稳定支持全自动跳过固定片头片尾。
// ==UserScript== // @name B站片头片尾跳过 // @namespace http://tampermonkey.net/ // @version 1.2 // @description 自动跳过B站前10秒片头和后5秒片尾,支持任意URL参数 // @author l9zp6 // @match https://www.bilibili.com/video/* // @match https://www.bilibili.com/bangumi/play/* // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // ==/UserScript== (function() { 'use strict'; // 配置参数 const INTRO_SKIP_TIME = 10; // 片头跳过时间(秒) const OUTRO_SKIP_TIME = 5; // 片尾跳过时间(秒) const SHOW_TIME = 2; // 提示显示时间(秒) // 存储上一次的视频信息 let lastVideoKey = ''; // 视频唯一标识(忽略无关参数) let lastUrl = ''; // 上次的完整URL let isWaitingForNextVideo = false; // 是否正在等待下一个视频 let lastProcessTime = 0; // 上次处理时间 let skipCooldown = false; // 跳过冷却标志 let forceProcess = false; // 强制处理标志 // 添加样式 GM_addStyle(` .skip-hint { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: rgba(0, 0, 0, 0.7); color: white; padding: 10px 20px; border-radius: 5px; font-size: 18px; z-index: 10000; opacity: 0; transition: opacity 0.3s; } .skip-hint.show { opacity: 1; } `); // 创建提示元素 function createHintElement() { const hint = document.createElement('div'); hint.className = 'skip-hint'; document.body.appendChild(hint); return hint; } // 获取播放器元素 function getPlayer() { return document.querySelector('bwp-video, video'); } // 获取播放器容器 function getPlayerContainer() { return document.querySelector('#bilibili-player, .bpx-player-container'); } // 显示提示 function showHint(text) { let hint = document.querySelector('.skip-hint'); if (!hint) { hint = createHintElement(); } hint.textContent = text; hint.classList.add('show'); // 获取播放器容器 const playerContainer = getPlayerContainer(); // 检查是否全屏 const isFullscreen = document.fullscreenElement || document.webkitFullscreenElement; if (playerContainer && !isFullscreen) { // 非全屏状态,将提示添加到播放器容器内 playerContainer.appendChild(hint); // 重置位置样式 hint.style.top = '50%'; hint.style.left = '50%'; hint.style.transform = 'translate(-50%, -50%)'; } else { // 全屏状态,提示保持在body内 document.body.appendChild(hint); } setTimeout(() => { hint.classList.remove('show'); }, SHOW_TIME * 1000); } // 生成视频唯一标识(只考虑BV号和p参数) function generateVideoKey() { const pathMatch = location.pathname.match(/\/video\/(BV\w+)/); if (!pathMatch) return ''; const bvid = pathMatch[1]; const pMatch = location.search.match(/[?&]p=(\d+)/); const pValue = pMatch ? `_p${pMatch[1]}` : ''; return `${bvid}${pValue}`; } // 获取视频标题 function getVideoTitle() { const titleElement = document.querySelector('h1.title, .media-info-title'); return titleElement ? titleElement.textContent.trim() : ''; } // 检查是否是新视频 function isNewVideo() { const currentVideoKey = generateVideoKey(); const currentUrl = location.href; let isNew = currentVideoKey !== lastVideoKey; // 如果URL相同但需要强制处理 if (!isNew && currentUrl === lastUrl && forceProcess) { console.log('强制处理相同URL的视频'); isNew = true; forceProcess = false; } if (isNew) { console.log('检测到新视频:', currentVideoKey); lastVideoKey = currentVideoKey; lastUrl = currentUrl; } else if (currentUrl !== lastUrl) { console.log('URL参数变化但视频未变:', currentUrl); lastUrl = currentUrl; } return isNew; } // 获取并更新记忆进度 function processMemoryProgress(player) { const videoKey = generateVideoKey(); if (!videoKey) return; const memoryTime = GM_getValue(`bilibili_memory_${videoKey}`, 0); // 如果记忆进度在片头时间之后,不做处理 if (memoryTime > INTRO_SKIP_TIME) { console.log(`检测到记忆进度:${memoryTime}秒,超过片头时间,不跳过`); return; } // 如果是新视频且进度为0,跳转到片头跳过时间 if (player.currentTime <= INTRO_SKIP_TIME) { console.log(`跳转到片头跳过时间:${INTRO_SKIP_TIME}秒`); player.currentTime = INTRO_SKIP_TIME; showHint(`已跳过${INTRO_SKIP_TIME}秒片头`); } } // 检查片尾并跳过 function checkAndSkipOutro(player, duration) { // 防止无限循环跳转 if (skipCooldown) return; const currentTime = player.currentTime; // 检查是否在片尾区域 if (duration - currentTime <= OUTRO_SKIP_TIME) { // 防止在短时间内重复跳转 const now = Date.now(); if (now - lastProcessTime < 2000) { console.log('检测到重复跳转尝试,跳过此次操作'); return; } lastProcessTime = now; // 设置冷却期 skipCooldown = true; setTimeout(() => { skipCooldown = false; }, 2000); // 跳转到离片尾0.5秒处,确保能触发下一集 player.currentTime = duration - 0.5; console.log(`已跳过${OUTRO_SKIP_TIME}秒片尾,跳转到${duration - 0.5}秒`); showHint(`已跳过${OUTRO_SKIP_TIME}秒片尾`); // 标记为等待下一个视频,并设置强制处理 isWaitingForNextVideo = true; forceProcess = true; } } // 检查是否应该处理新视频 function shouldProcessNewVideo(player) { if (!player) return false; // 如果正在等待下一个视频且播放器已加载新视频 if (isWaitingForNextVideo && player.currentTime < 5) { console.log('检测到自动连播的新视频'); isWaitingForNextVideo = false; return true; } // 检查是否是新视频 return isNewVideo(); } // 主处理函数 function processVideo() { const player = getPlayer(); if (!player) return; // 检查是否应该处理新视频 if (shouldProcessNewVideo(player)) { console.log('检测到需要处理的新视频:', getVideoTitle()); // 处理记忆进度 processMemoryProgress(player); } // 保存进度 const videoKey = generateVideoKey(); if (videoKey) { GM_setValue(`bilibili_memory_${videoKey}`, player.currentTime); } // 检查片尾 if (player.duration && player.duration > OUTRO_SKIP_TIME) { checkAndSkipOutro(player, player.duration); } } // 初始化 function init() { console.log('B站片头片尾跳过脚本已加载'); // 监听播放器状态变化 const player = getPlayer(); if (player) { player.addEventListener('loadedmetadata', () => { console.log('播放器加载了新的元数据'); processVideo(); }); player.addEventListener('timeupdate', () => { // 播放器时间更新时检查 processVideo(); }); } // 监听URL变化 new MutationObserver(() => { console.log('检测到URL变化'); setTimeout(() => { processVideo(); }, 300); }).observe(document, { childList: true, subtree: true, attributes: true, attributeFilter: ['href'] }); // 定时检查 setInterval(() => { const player = getPlayer(); if (player && !player.paused) { processVideo(); } }, 1000); // 初始处理 setTimeout(processVideo, 1000); } // 等待页面加载完成 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();
本脚本是专门为了学习而编写的脚本,也只有在学习时使用该脚本才有可能有相应的效果,严禁将此脚本内容用于任何商业或非法用途,对于因违反此说明而产生的任何法律后果,用户需自行承担全部责任。
2025-06-28 18:48:52
下午上微信看了一下,发现落花问我CSDN的文件可不可以下载,稍微瞅了一眼,感觉是VIP才能下载的文件。
由于我浏览器有去广告+内容农场的插件和脚本,上一次访问CSDN已经忘了是什么时候。
众所周知,CSDN很多的付费文件的出处并非首发,所以一般情况,如果CSDN有的文件,那么互联网应该很多地方都有发布。
那么我们只要在访问CSDN的时候,把标题复制搜索一下,即可找到可以下载的渠道,例如CSDN标题为:易语言-XX框架源码(最后一个版本)。
必应搜索:易语言-XX框架源码(最后一个版本),即可找到相关资源,这里推荐可以使用: Andi AI搜索,效率会更快一点。
CSDN付费文件下载思路(非技术方法)最先出现在龙鲲博客。
2025-06-24 22:54:42
晚上家里台式电脑在通过微信打开表格文件时,开始频繁出现“我们遇到了一个无法恢复的问题,您的文件已经自动保存到备份文件夹中,请勿担忧。如果此错误反复发生,请将错误报告发送给我们”。
在网上查找了相关的解决方案,例如关闭火绒的文件扫描、重置WPS的自带设置、安装WPS教育版,均无法很好的解决问题。
这里记录一下折中的解决方案:
安装WPS教育专版:https://ncre.neea.edu.cn/html1/report/1507/861-1.htm
优势:具备通用性,功能全面,不会出现教育版以及特制版本使用异常的问题,包括不限于过期、无法登录等。
劣势:没有WPS最新功能,UI相对最新版不够好看,可能不支持宏之类的高级功能(一般人也用不上)。
2025-06-20 15:16:43
由于最近开启了各大运营商的骚扰屏蔽服务,手机上几乎看不到什么骚扰短信了,但有一类短信开始出现在了我的视野当中,也就是公益短信。
正常情况下,公益短信的接收我并反对,但部分省份的公益短信着实让人觉得有些反感,具体表现为发送频率过高,以及发送范围过广。
例如以某省为例,有时候一天能收到好几条公益短信,以及发送的内容与用户实际并无关联。
例如我曾在A省工作,办理了一个手机号码,后面由于工作变动,去了其他省份,但号码因此留用。
此时A省的天气预警跟我已经没有实质关联,我不关注也无需关注该类预警信息,但此类短信却一直在发送。
这里简单介绍一下关闭方法:
1、广东电信可以发送如下短信自助关闭:
【中国电信】尊敬的客户,格式错误。请按以下格式重新输入:QX#数字代码(需屏蔽短信类型的数字代码)。
QX#10 屏蔽10000端口所有类型短信
QX#11 屏蔽10000端口服务关怀类短信
QX#12 屏蔽10000端口营销宣传类短信
QX#13 屏蔽10000端口政府公益类短信
QX#14 屏蔽10000端口紧急类短信
QX#20 屏蔽10001端口所有类型短信
QX#21 屏蔽10001端口服务关怀类短信
QX#22 屏蔽10001端口营销宣传类短信
QX#23 屏蔽10001端口政府公益类短信
QX#24 屏蔽10001端口紧急类短信
2、联系运营商要求关闭公益短信。
3、借助运营商骚扰屏蔽业务屏蔽发送公益短信的号码。(该方法不适用通过10000和10001发送的公益短信)
最后,如非必要,例如像我个人上面的情况,不建议关闭公益短信!
如何屏蔽与个人没有实质关联的公益短信最先出现在龙鲲博客。