减小 vmware 虚拟机的硬盘容量,不是压缩

默认情况下,vmware 虚拟机的硬盘空间可以在 vmware 的虚拟机设置里调整大小,但只能『扩展』,却无法缩小。

当输入较小数字时,按钮变灰,无法点击。

 

问题:为什么要缩小虚拟机硬盘

一,vmware 的虚拟硬盘文件 *.vmdk 默认是动态分配空间的,没有数据的虚拟 “硬盘空间” 并不占用真实主机的实际硬盘空间。当虚拟机内需要储存更多数据时,对应的 vmdk 文件会相应增大,以便容纳新增的数据。但当虚拟机内的数据被清理时,已经增大的 vmdk 文件却不会自动缩小。随着虚拟机的不断使用,『只增大不缩小』的情况会逐渐严重,直到 vmdk 体积达到预设的虚拟机硬盘完整容量为止。

  • 向虚拟机内复制文件并随后删除。
  • 设置虚拟机快照并随后删除。
  • 安装各类软件而后卸载 / 利用快照恢复原样

等等各种情况都会增大 vmdk 体积。vmware 针对这种情况提供了 shrink disk(压缩硬盘)功能,也就是在虚拟机数据已经被清除后,整体扫描一遍 vmdk 文件,清理无效数据,缩小真实体积。但这也有两个麻烦:

  1. 因为膨胀永远存在,所以压缩也要经常进行,难免感觉在做无用功。
  2. Linux 下 shrink 功能有 bug,需要配合 dd 命令先以 0 数据充,相当于先撑大再缩小,耗时数倍。参考:第四条豆知识

二,很多情况下,我们安装虚拟机的用途都比较单一,比如干净 WinXP / Win7 测试软件,练习多个 Ubuntu Server 组集群,或在 Linux/Mac 主机上利用 Windows 虚拟机操作网银。虚拟机的实际硬盘占用也往往小于 vmware 的推荐值。这是实际需求方面及可操作方面。

三,强迫症 / 好奇 / 无理由。

于是,根据实际使用情况,适当降低虚拟机的硬盘容量,将『使用膨胀』的上限卡住,释放真实硬盘空间并避免经常的压缩操作,对时间和金钱都有好处。尤其是现在 SSD 逐步标配的阶段,虚拟机硬盘容量设置不当造成的浪费是很可观的。

问题:如何操作

我以一个当初决策不当分配了 40GB 硬盘空间的虚拟机 Windows XP 为例,重新调整的目标为 10GB。一般来说,全新安装的 Windows XP 大约占 4-5GB 空间,则我们还有约 5GB 空间可用来安装测试软件等,足够了。如果不够就自行酌情决定调整目标。

一、清理删除当前虚拟机下的所有快照,如果这些快照很重要不能删,那接下来的操作对你就没意义了。

二、确认虚拟机硬盘是拆分成多个文件的动态分配硬盘。本例子中,该虚拟机的所有文件放在 D:\Program files\Windows XP.vmwarevm 目录下。用 VSCode 打开虚拟机目录下和虚拟机同名的 *.vmdk 文件,如 『Windows XP.vmdk』。找到 # Extent description 部分,检查描述部分,一看就懂了。如图:

打开 vmdk 时几种可能的情况:

  • 如果有多行描述,并且每行写了 SPARSE ,这就是我们需要的类型,拆分+动态分配磁盘。直接跳过后续转格式步骤,进入修改分区步骤即可。
  • 如果有多行描述,但每行写的是 FLAT,则为拆分的预分配磁盘,需要转格式。
  • 只有一行描述,写的是 FLAT,则是单一文件预分配磁盘,也需要转格式。
  • 如果乱码或者提示打不开,则是单一文件动态分配磁盘,还是需要转格式。

VMWare 在新建虚拟机时会默认选择第一种类型,但玩家当初可能出于性能等考虑,选择了其它类型的虚拟硬盘。那么就需要使用 vmware 自带的一个命令行工具 vmware-vdiskmanager.exe转换成第一种类型。该工具在 vmware 安装目录下,默认为 “C:\Program Files (x86)\VMware\VMware Workstation\vmware-vdiskmanager.exe”。

转换方法:

该工具的命令行写法为:

工具名 参数1 源文件 参数2 参数3 目标名称
vmware-vdiskmanager -r(转格式) Windows XP.vmdk(例) -t(目的) 1(目的磁盘类型,1 为拆分+动态分配) newdisk.vmdk

该命令中, -r-t 1两部分不需要变化, 目标名称 随意,之后会改名覆盖源文件。 源文件名 根据实际情况变化,而 工具名 通常要带上路径。

所以完整的命令大约是如下样子:

回车以后开始执行转换:

转换完成以后,删除旧的 “windows XP.vmdk” 和多个关联文件 “windows XP-s0xx.vmdk”,然后把新的 newdisk.vmdk 重命名成 “windows XP.vmdk” 以替换。其它 newdisk-s00x.vmdk 不用变。

三,打开虚拟机,进入系统。

  • 在虚机机内,使用分区管理软件将硬盘分区缩小,并将空闲保留在右端,分区块保持在左端。我们的整体目标是从 40GB 缩到 10GB,则现在要多缩一点给后续操作留出余量。如图,暂时缩到 9GB。

  • Windows 7 以上系统,自带的磁盘管理就有『压缩卷』功能可以调整分区大小,WinXP 用的是 DiskGenius 免费版本。Win98 则需要寻找更古老的相应软件。
  • 中途可能需要重启虚拟机,无妨,调整完关闭虚拟机即可。

四,加减乘除:

再次打开 Windows XP.vmdk 文件,定位到 # Extent description 部分。这次重点放在第二部分数字内容上,经计算,该数字为每个分块文件对应虚拟硬盘的簇数量,每簇 512 Byte,2 簇 = 1KB。我们的目标容量为 10GB,也就是:

  • 10(GB)*1024(MB/GB)*1024(KB/MB)= 10485760 KB = 20971520 簇。

检查 # Extent description,前两个文件每个 8323072,则把第三行的数字改为

  • 20971520 – 8323072*2 = 4325376


并删掉后续各行及对应文件,我们就在 vmware 部分完成了虚拟机硬盘大小调整。

五,补足余量:

重开虚拟机。前次调整分区时,预留了 1GB 左右的余量。再次打开分区工具,把剩余未使用空间重新分配给各分区。

因为对计算机分区而言,由于存在分区表、启动扇区等原因,物理上的 10GB 硬盘空间在系统内表现是略小于 10GB 的,『内』『外』之间有差额,这对于虚拟机也一样成立。如果一开始就分区 10GB 而外部调整也等 10GB 的话,再次启动虚拟机就会报分区表错误,界时修改起来反而麻烦。现在这样按先预留余量,而后补足分区操作就没问题了。

六,清理死数据:

由于直接修改了描述文件,改小了簇数量,-s003.vmdk 里原本存于 4325376 之后的数据变成了永久的『死数据』。关闭虚拟机后,需要使用 vmware-vdistmanager -r <源.vmdk> -t 1 <目标.vmdk> 再作一次转换。虽说是转换,但目的却是清理死数据。清理完以后直接单独替换新旧 -s003.vmdk 即可。(想想为什么?)

————————————————-

相关细节:

  • 虚拟机为 Linux 系统时原理一样。利用 GParted 等分区工具,首先缩小使用分区,并调整未分区块到尾端。关机编辑 vmdk 描述,开虚拟机调整补分区足余量,再关机清理死数据即可。
  • 预分配类型的虚拟硬盘必须先 vdiskmanager 转类型,不能直接操作。追求性能的话在编辑完再转回去。不过追求性能的话应该上 SSD,一力降十会。
  • 编辑 .vmx 和 .vmdk 文件不要用 windows 自带的记事本。
  • 虚拟机备份直接复制整个目录即可。
  • 扩容不需要按本文操作,使用 vmware 自带功能即可。

Hybrid Script 附一则:解决 PowerShell 无法双击打开路径含空格文件的 Bug

脚本文件里的 Hybrid Script(混合式脚本)

该文介绍了混合式脚本的原理和示例,这里补充一个实际适用的场景。

问题描述:

在 Windows 下,即使正确关联了 .ps1 的打开方式,Powershell 也无法正常运行脚本,只有一闪而过的报错信息。

正确设置了 PowerShell 的关联

使用录屏软件捕获到这一闪而过的错误信息

而首先打开 PowerShell 终端,并在终端里指定执行脚本,则可以正确执行:

脚本本身没有问题

错误原因:

这个错误原因其实挺显然的——在 Windows 下双击执行,等同于运行 PowerShell.exe,并向其传入了脚本文件的完整地址作为参数。但 Windows Explorer 在传递 %1 时没有加引号,PowerShell.exe 也没有对此做检查。结果就是,只要脚本所在的目录含有空格,PowerShell.exe 就会把空格前半段视为文件地址,而把空格后半段视为另一个运行参数。

而通过先启动终端再指定脚本运行正常,就是因为没有传参这个过程,Powershell 自行请求了脚本文件,就能正常执行。

解决办法

解决办法却不容易。修改双击打开时的参数设置为其加上引号,这个太困难了。修改 PowerShell 程序本身,为其添加参数检查更是不可能,只能坐等微软更新。

剩下的只有两种办法,一是永远把 .ps1 脚本放在没有空格的目录里。不但本目录不能有空格,上级目录一直到盘符所在的根目录都不能有空格。这其实也挺麻烦的。

另一种办法就是用混合式脚本:

  • 代码示例:
  • 虽然我们要写的是 PowerShell 脚本,但为了让脚本能支持在含空格的路径下双击执行,我们不得不首先以批处理文件的形式调用 CMD,然后让 CMD 向 PowerShell 正确地传递带上引号的完整路径。这样,PowerShell 就能正确识别脚本文件的位置,执行混合脚本里的 PowerShell 代码段,完成最初预期的功能。

  • 双击运行效果:
  • 混合脚本显示的是 CMD 的黑窗口

    因为混合脚本首先运行的是 CMD,所以窗口变成了黑色。但 PowerShell 的脚本确实正确执行了。

题外话:

  1. 通常这种混合脚本我都会按语言命名为 ***.ps1.bat 以区别普通的 .bat,并提醒用户(也就是我自己)这需要 Windows 安装了 Powershell 才能正确执行。PowerShell 可以从 Windows 的系统组件里添加,Win10 则已经自带了。
  2. 为了截图方便,上文的示例代码最后一行其实又用到了 CMD 代码的 pause,所以这个示例代码严格来说是 CMD → Powershell → CMD 的三阶混合脚本。

[风暴英雄语音站] 如何帮助更新数据

1. 下载 这个文件📚,解压出一个 vos-master 目录。目录不大,解压到哪里都行。

2. 打开目录 vos-master,你只需要关心其中的 static 目录,其它文件都可以删掉。

3. static 目录下,有个 libs.csv 文件。右键点击它,用记事本打开

虽然是 csv 文件,但由于文本编码格式(UTF-8)原因,如果你直接双击用 Excel 打开,会出现中文乱码的问题。解决办法有几种:

  1. 用 Excel 导入方式:先打开 Excel,再通过菜单 数据 → 自文本 导入 csv,并在『文件原始格式』选择 65001: Unicode (UTF-8)。
  2. 使用现代化的文本编辑软件:VS CodeSublime Text 并借助其强大的插件功能更方便地编辑

4. 找到你想修改的英雄/地图/播报员的名字。比如 失落的维京人。它的中文名后跟随有四个逗号分隔的数字,,”200,201,202,203″,记住这些数字。
5. 打开和 libs.csv 同层的 sheets 目录,找到里面四个文件,200.csv、201.csv、202.csv、203.csv,按步骤 3 一样方式打开。
6. 打开 hero.thnuclub.com 页面,选择失落的维京人并切换为『显示文件名』模式。
7. 逐行比较 csv 文件和页面语音的内容,根据文件名一一对应,修正 csv 文件内的错误。修改完成以后,将改正的 csv 通过邮件或者 QQ 发给我。我会更新到线上。
8. 你的名字将会出现在这里:。这里的位置很大。

————
其它事项:

1. 有些英雄/地图有多个 sheet,有些只有一个,目前为止播报员都只有一个 sheet。
2. 你发回给我的文件不需要强求 csv,用 .xls 或者其它的格式都可以,只需要保证内容正确,格式我会转换。
3. 你可以只修订中文部分,或者只修订英文部分。但请按至少一个 sheet 里的一种语言为单位订正数据,尽量避免改一两行便要求更新。
4. 编辑时注意逗号的位置,不要修改中英文台词名的其它内容,避免出现列偏差。
5. 如果你懂得 git,也可以直接发送 pull request。
6. 感谢你的帮助。

脚本文件里的 Hybrid Script(混合式脚本)

因为日常需要,经常写一些脚本命令,比如 Windows CMD / PowerShell / bash 之类的。最近学习了一种新的脚本类型:Hybrid script,即混合式脚本,是在一个脚本文件内,同时使用多个语言的语法和对应功能。比如以下这段代码:

这段代码的功能是调用 youtube-dl.exe,按预先准备的待下载视频列表指示,下载所有视频。有趣的是,如果你通过拖拽的方式,把列表放到脚本文件图标上,则脚本直接开始按列表下载。

如果没有拖拽,而是双击打开脚本文件,则会跳出一个选择文件的 Windows 对话框,让用户选择一个或者多个列表,然后再开始下载。

这是一个用户体验相对比较好的方法。虽然这脚本只是自用,但我自己也是比较烦命令行的。至于任务是下载视频,或者处理音频,亦或删除目录什么的,只是中段执行不同,和本文主旨无关。

这脚本的核心难点,便是『如果没有拖拽列表文件,则打开窗口让用户选』这个需求点。CMD 是没有 Windows 图形界面下的对话框功能的,但 PowerShell 有。因此便有了这个 Hybrid Script 脚本。

脚本前半段是 Batch 代码,输入下载列表文件路径,执行下载。这个『下载列表文件路径』,或者是用户拖拽获得,或者是用户在选择窗口中操作获得。后半段则是 .ps1 代码,用来绘制选择窗口并把列表路径返回 CMD。

但问题在于,两种代码并不兼容。CMD 并不能识别 PowerShell 代码,而 PS 也无法识别 Batch 代码。如果普通的执行对方的代码,一定会报错的。

于是我们看到,上面这段代码里似乎有几行奇怪的代码:

没错,就是这几行特殊代码,以及另一个非常重要的变量 %~f0 ,决定了 Hybrid Script 的可行性。

事实上, <# ..... #> 是 PowerShell 的注释代码,PS1 执行器遇到它时,会直接忽略两者中间的所有内容,执行后面的代码。而 <# :hybrid.bat 对 CMD 而言是个没有指定目标的左向重定向命令。因此 CMD 确实执行了第一行,但没有任何效果。

对于 PS 的结束注释符号 #>,在 CMD 看来确实有意义。但我们提前用 goto :EOF 直接跳到脚本最末(End-Of-File)的办法,把这一行以及后面的所有代码都跳过了。于是这些代码在 CMD 下的对错就无关紧要了。

也就是说,在 CMD 眼睛里,这段代码其实是这样的:

而在 PowerShell 眼里,这段代码是这样的:

以上都明确以后,中间那句 'powershell -noprofile "iex (${%~f0} | out-string)"' 的作用也就容易理解了——Batch 脚本调用了 PowerShell 的执行器,并把这个 hybrid.bat 自己(在 Batch 代码中, %~f0 这个变量就是指脚本文件自己)传递给了 PowerShell。

PowerShell 接到消息以后,又执行了一遍这个 Hybrid.bat。这次是 PS 视角,因此上来就忽略了前面整大段的“注释”,直接从 Add-Type -AssemblyName System.Windows.Forms 这段开始,绘制窗口,等待用户选择,获得列表文件路径,然后再返回给 CMD。CMD 最后再执行
for /f "delims=" %%I in ( ...... ) do ( ...... ) 的部分,并根据
goto :EOF 的指示,跳过剩余代码,避免了在 CMD 环境下的报错。

因此,为了正确执行功能,Hybrid Script 的核心思想是:

1. 利用两种语言的注释符号的不同,隐藏非执行环境下的代码。
2. 灵活应用两种语言的特性,确保任一语言下的注释符号本身,对于另一种语言没有负面效果。
3. 首先执行的语言 A,需要把脚本文件自身的路径,传递给另一种语言 B 的执行器。
4. B 语言的执行器,忽略掉被 B 语言注释符号包裹起来的 A 语言代码,执行 B 的代码,如果需要的话,把执行结果返回给 A。
5. A 继续执行剩下的部分,忽略掉被 A 语言的注释符号包裹起来的 B 语言代码。
6. Hybrid Script 至少会执行两遍,可能更多。

———————————————

充分理解 Hybrid Script 思想以后,我们就知道这并不仅仅限于 Batch 和 PowerShell 脚本的混合了。常用的几种脚本语言都可以实现混合代码。实践中:

1. Windows Batch & Windows PowerShell
2. Windows Batch & Linux Bash
3. Windows Batch & Python
4. Windows Batch & Javascript
5. Linux Bash & Python
6. Linux Bash & Javascript
7. NodeJS & Python
8. …

等等组合都可以写出相应的混合代码脚本。

Hybrid Script 能同时利用两种甚至多种语言的方便特性。并且对于各语言组合,相互注释的『套路』是固定的,几部分代码实际功能如何变化并不影响套路。但其实整体来说适用性不广,一来机器上需要同时有两种语言的运行环境,二来 Python JS C# 等几种主流语言都有完备的功能集和函数库,不需要跨语言写作。三来,即使真的需要两种语言,大部分情况下也可以写成两个脚本互相调 用执行。

只有很少的几种情况下需要考虑 Hybrid Script,包括:

1. 因为传播渠道问题,不适合拆分成多个脚本的。比如互联网上常见的『复制粘贴代码到记事本改后缀为 .bat 然后双击运行』。
2. 代码票友,对 A 语言和 B 语言都不甚精通,或者从 A 转 B 的学习过程中,B 还不甚了解,需要用 A 语言的代码补足。
3. A 语言确实功能有限,但胜在编码方便历史普及率高。而产品虽需要却也只需要 B 的极小功能。比如本文示例。
4. 写着玩。
========
5. 解决 PowerShell 无法正确处理文件路径带空格的 BUG,参见:

Hybrid Script 附一则:解决 PowerShell 无法双击打开路径含空格文件的 Bug

Excel Match() 函数的通配特性

今天遇到一个奇怪的情况,在使用形如:

=Match(A2,A:A,0)

的 Excel 公式查找时,居然返回了 #N/A 的结果。逻辑上来说,在自己所在的数组里查找自己,不应该得到错误结果,事实上这个公式的值只可能是 1 或者 2 才对。

经过检查,发现问题出在字符 ~ (波浪号)上,即键盘上 ESC 键的下方,数字 1 的左边那个键的 Shift 上档符号。

Excel 官方帮助文档 中,找到了相关的解释。

如果 match_type 为 0 且 lookup_value 为文本字符串,您可在 lookup_value 参数中使用通配符 – 问号 (?) 和星号 (*) 。问号匹配任意单个字符;星号匹配任意一串字符。如果要查找实际的问号或星号,请在字符前键入波形符 (~)。

这里提到了,当使用 Match() 函数进行精确的文本查找时可以使用通配符 ? 和 *,当用户确实需要查找问号/星号时,则可以用 ~? 和 ~* 来表示。这里没有提到的是,如果用户需要查找 ~,其实也需要通过两个波浪号 ~~ 来表示。转义符自身也需要转义表达,也算是一般规则了。

所以,如果一个单元格中包含了波浪号 ~,则当这个单元格作为被查找的数据的一部分时,是正常的。但当它同时作为 lookup_value 时,则会在转义后变得无实际意义。于是导致了 Match() 函数查找自身所在数组时产生的错误结果。

遇到这个问题时,我正在处理由家用下载机长年积累下的大量动画片资源。用 Bash 获得所有的动画目录名、文件名,并试图尽量删减一些重复资源。文件名系统中并不存在『 ? * : < > | / \ ” 』等符号,但偏偏允许波浪号 ~ 的存在。又因为在 Excel 的默认字体中,波浪号并不显示为扭曲的波浪形状,而是略长的横线,如图,于如是尴尬便发生了。

解决办法:

给 lookup_value 添加一个 SUBSTITUTE() 函数进行修正,即:

即可得到期望结果。

一句话总结:

当 match_type 为 0 且 lookup_value 为文本字符串时,使用 =Match() 函数时需要注意 lookup_value 是否包含 ~ 、?、* 并根据需要预先做处理。

Ikaruga 评测

★ Ikaruga「斑鸠」 on Steam ★

来,跟我念:

黑机吃黑弹躲白弹打白鸡留黑鸡给白队友遇白光切白机。
白机吃白弹躲黑弹打黑鸡留白鸡给黑队友遇黑光切黑机。

黑白黑白黑白黑黑白白黑黑黑黑白黑白黑白黑白黑白黑黑黑白黑,
变变变变变变变定变定变定定定变变变变变变变变变变定定变变。

黑白黑黑白白白黑白白黑白黑白白黑黑白黑白黑黑黑白白黑黑黑黑黑白白白黑黑黑白黑黑白白黑黑白黑白黑黑黑黑白白白白白白,
变躲吸吸变吸吸躲吸吸躲吸变躲躲吸吸躲吸躲吸吸吸放大招吸吸吸吸变吸吸变吸吸变躲躲吸吸变吸躲吸躲吸吸吸躲变吸吸放大招。

……差不多这个感觉。

Ikaruga 斑鸠

如果说彩京、虫姬、东方是用层层叠叠的华丽弹幕压迫你的灵魂让你手脚冰凉让你奋起反抗让你一世积累尽殁此役,那么斑鸠则是用至简与朴素唤醒你心底的温暖,唤起你对理想与光明世界的向往。

这个世界没有遮天蔽日的弹幕,每一个子弹都可以直接吸收无需躲避,
这个世界没有血条畸长的敌人,即使是关底 Boss 也挡不住几轮蓄能爆发,
这个世界的敌人甚至还会在死去时抛出剩余的能量帮你充能,
这个世界不断地告诉你什么叫理想、试练、信念、现实与轮回。
这个世界总是将光明放在你的眼前,触手可及。

一个完美的世界。

这个世界里里唯一不完美的是你。是屏幕前双手颤抖面目狰狞的你,是竭力紧抓手柄胡乱变色仓皇逃窜的你。但这个世界依然爱着你,从内到外都爱着你。

没有 给你任何 随机出现的敌人,只有约定之时,只有约定之地。
她给了你远超需要的强大技能, 蓄能爆发,让你在瞬间打倒最强大的敌人。
她给了你 异色双倍伤害,给了你 三同色击破链式加分,给了你破敌 残弹 额外蓄能。
她还给了你 竖屏模式,将显示器旋为竖置,世界便扩大八分。
她甚至给了你 单手柄双机模式,让最孤独的你也能与自己一起游戏。
她唯独只是 没有 给你 网络联机 模式,她是完美的,她不需要的,便是不需要的。

你只需要做好一件事,在该变白时变白,该变黑时变黑,你就能回应她的爱,双双走向高潮。

你怎么就做不到呢。

甚至最后的最后,她为了如此不成器的你,把 无限命模式 也给了你。

完美的她,深深地爱着毫不完美的你,爱着什么都做不到的你,爱着靠无限命死乞白赖撒泼打混的你,爱到了最后。

这份爱,只需 36 人民币,打折 18。

守望先锋 1.14 版本后更改了底层数据格式

参考老文章: Overwatch Toolchain 解包方式考察,OW 音频小站一直以来使用原始文件 hash 的办法,便每次更新以后,都能区分旧数据和新增数据,使得每次更新的条目数量都在合理范围。但从版本 1.14 开始,暴雪更新了内部数据格式,这个是由蓝帖明确提到的,目的是减少之后的每次客户端更新时的下载。

但这对本小站来说不亚于一次冲击。这意味着,直到 1.13 版为止的条目,和从 1.17 版开始的所有条目,无法从数据角度建立『新』与『旧』的联系。

也就是说,明明从用户角度来说是同一句台词,音频波形也一致,但由于 OW 内部格式的变化,导致 hash 计算的结果变化,使得从数据角度来说,它们变成了两个不同的条目。

比如: D.VaD.Va 一分,坏蛋零分。(1.17 版本) 的 hash 计算结果是 5908654fbc3965232689836abb249c57,而
D.VaD.Va 一分,坏蛋零分。(1.16 或更早版本) 的 hash 计算结果是 1d99c1739f5b0844f57f3a1a5fbb4580。

我做了很多尝试,试图恢复一些信息,把这些本质相同的音频重新联系起来,有些成功了,有些失败了。最后我把匹配成功部分更新到原有条目上,匹配失败的部分按『新增音频』对待,添加到数据库里。

  1. 尝试使用音频分析软件批量比较,如果成功,理论上这是最好的办法。
    • 这是本质的解决办法,如果两个音频文件的波形完全一致,则两个音频当然是一样的。
    • 尝试了 Audacity 和 Similarity,前者缺乏批量功能,后者无法对这种只有一两秒的音频进行比较,均告失败。
  2. 尝试使用新版本拆解工具拆解旧客户端,失败,但得到了启发。
  3. 因为拆解所用的 Toolchain 工具链(简称 TC)本身有自己的文件名系统,而我亦保留了过去所有版本的原始拆解数据,理论上能通过新旧版本文件的相同路径名等信息恢复联系。
  4. 测试以上两条 D.VA 音频的 TC 路径分别为:
    • 旧(1.13):cn\heroes\D.Va\Sound Dump Full\_Base\000300000057\000000020231.wem
    • 新(1.18):cn\HeroVoice\D.Va\00000000059F.078\000000020231.wem
  5. 测试成功。
  6. 进入实操,发现由于旧版本拆解工具的不完全,数据存在错误,依然有许多坑要填:
    • 一,多个不同的 TC 文件名对应同一个 hash,即多个 1.18 新文件条目对应同一个 1.13 旧条目 hash,错误在旧版拆解工具自带的文件名系统有 bug。
      • 解决办法是视为多个条目,并将旧条目的听写内容更新到各个新条目上。
      • 对于网站用户来说,同一个关键词可能会搜索出几条内容,但其中应该至少有一条是对得上的
    • 二,同一个 TC 文件名对应多个一个 hash,即同一个 1.18 新文件条目对应多条旧的 1.13 旧条目,显然错误还是旧版折解工具的不完善
      • 解决办法只能是人工筛选按多条里面正确的那条。
      • 大约一共有 1200 条这种类型的错误,一条一条听完。网站用户肯定会得到正确的结果,因为这部分我都筛完了。

这次更新正常应当在 1.14 新版数据格式更新,1.17 新版拆解软件开发成熟以后更新,但这数据处理是真 TM 麻烦啊,烦死了。

近期用到的一些命令合集

Grep 字典式匹配输出

SED 若干则

CMD 快速删除文件

Excel:从右往左查找某个字符。

原理,使用 Substitute() 将所查找的字符替换为空,则长度差代表该字符出现的次数。将该次数作为 substitute 函数的第四参数,用一个特殊字符再度进行 Substitute() 替换,然后 Find() 该特殊字符。

写了个简易的多个网页连续截图脚本

目前适用于 ngacn 论坛帖子,效果图如下:

启动脚本后,会依次询问你 nga 的帖子 id,总页码数量和帖子名称。脚本会自动检查是否之前已经抓取过该帖子并在上次抓取的最后一页开始继续往下抓取。

每个帖子的抓取结果会放在独立的目录,并以”帖子id”-“自定义名称”的形式储存

注意事项:

  1. 脚本会优先检查是否有 $tid-xxx 形式的目录,只要 $tid 一致,脚本就认为本次会在旧的内容基础上往后抓取截图,xxx 的名称可以是任意的,不检查。假如已经存在一个 『12345-上山打老虎』 的目录,而你第二次输入的是 『12345-钻石王老五』,则实际更新的依然是『12345-上山打老虎』 目录。
  2. 目录名称中间的减号必须保留,否则脚本会忽略已存在的目录,按新目录工作执行。目录内的 1.update.sh 文件也必须保留。
  3. 我的运行环境是 Win10 64 位 1703 版本,不保证在其它机器上能正常运行。在 Win10 下脚本文件可以直接双击打开,在Win7 下可能需要右键点击并选择用 Git Bash 打开。
  4. 需要预先安装该脚本所需要的环境才能正常运行,包括 node、bash 等。

 

安装与准备工作:

  1. 下载并安装 Node for win 使 Windows 获得本截图脚本所需的 node 语言支持: 下载网址: https://nodejs.org/en/download/ ,选择下载 LTS 版本下对应的 32位 或 64  位 Windows Installer。安装一路 next 就行。
  2. 下载并安装 Git for win 使 Windows 也能使用 Bash 脚本。下载网址:https://git-for-windows.github.io/ ,也是一路 next 默认安装就行。
  3. 从开始菜单找到 Git Bash,,点击运行,在黑色窗口内依次输入以下内容:
    效果:
  4. 新建一个目录,起个名,比如叫『nga截图收藏夹』之类的。
  5. 在目录下新建一个文本文件,复制粘贴以下代码:
    随便起个名,并把后缀名改为 .sh。如何修改后缀名请自行百度。

使用:

  1. 双击,依次输入帖子 id,最后一页页码和标题就可以用了。

尾注:

  1. 如果你懂得简单的编程,可以尝试阅读脚本,并自行修改以抓取其它网站的贴子。这个脚本的原理就是利用 nga 帖子很有规律的地址,通过指定帖子 tid、页码 pageid 拼接出需要抓取的指定页面网址,然后反复调用 pageres 去抓取。实际进行抓取的是一个叫 pageres 的 npm 小程序。
  2. 如果你懂得简单的 JS,你可以自行指定 pageres 的抓取参数,甚至包括登录的 cookie 等,以实现『个性化抓取』。
  3. 如果你会完整的 node 开发,希望这个脚本也能为你提供一些参考。

ow.thnuclub.com 更新与计划更新

小站因为忙停更了一段时间,结果被各种催更。值此国庆佳节加之周末免费,趁势也更新一下,再开些空头支票。

  • Done:更新末日铁拳、地平线月球基地及其它英雄新增语音。(1.13 版客户端拆解)
  • 时间有限,只处理了增量更新部分。旧数据的疏漏错误更新后依然存在。他日有空再逐步更新旧数据。

  • Done:去掉了早期开发的赞与踩功能。
  • 在去年小站刚出来时,曾指望让热心用户通过 vote / devote 功能,把『有内容的音频』也就是台词、音乐等条目上浮到前几页,让意义不大的嘈杂环境音下沉。但事实看来结果不好,一来是用户并没有很好地理解该功能。后台数据显示,被踩得最多的是源氏的龙神拔刀,其次是麦爹的午时已到。想必是冤魂太多,多少发泄一下吧╮( ̄▽ ̄”)╭。二来呢,我看到这个数据以后也就懒病发作,没有继续考虑改进该功能了。后来还短暂地改成『倒放音频』,也就是猎奇一番,甚不实用。今日该功能彻底取消,就当是当年那几千投票,终于修正成果了吧。

  • Done:调整了下界面,加了圆角、阴影,js 代码的报错部分也处理了。
  • 主要新增数据会用黄色标签显示在上方。条目按钮加了细微的圆角和渐变阴影,整体会更柔和一些。同时每页条目数从 200 条减少到 100 条,相应的显然页码数量也加了一倍。因为网页背景本身是守望的全屏截图,故整体风格不会有大的变化,没有前后对比,不仔细看的话应该看不出来。修正 JS 报错这事其实也可做可不做,只要不搞死页面,能正常执行功能,jQuery 也就这样了。

  • Done:加了打赏按钮。
  • 这个没啥说的,目前平均也就每周一罐可乐,但听见叮咚声时的好心情很值钱。摊开算收益的话应该现在就把小站关掉,每年能省千儿块服务器钱。

  • Done:更新 36729 条音频的 MP3,音质略有提升。
  • 音频文件的处理路径是游戏客户端→.wem格式→.ogg格式→.mp3格式,理论上每一步都会有损耗。为了能在网页上直接播放必须使用 MP3,但之前在把 OGG 转为 MP3 时我选的是 LameXP 里的质量等级 2(一共 10 级),现在我想通了,把质量等级改成了最高的 0。当然,质量越高,mp3 的体积也越大,从质量 2 到质量 0 体积平均会增大 50%,也就是大概每个文件 20KB 会增加到 30KB。

    这对视频制作者会有所帮助,下载的音频在嵌入视频后的音效会有略微的提升。对 Lame 编码而言,质量 2 到质量 0,新增的数据主要集中在轻微的、高频的或者低频音域。这些音域的补足会让音频的回声、立体感和通透性更好一点点点点,就当是信则有吧。

    缺点是,对于使用手机流量访问的用户流量的消耗会增加。目前统计的平均每条数据大概是 28KB,请量力而行。至于对网页响应速度则是几乎没影响的,你的主要延迟是来自于与 Github.io 这个网站(我拿来存音频源)之间的通讯延迟,至于下载的数据是 20KB 还是 30KB,差的不过是 0.0x 秒而已。

  • Done:当条目文字很长时改用换行式,取代当前的隐藏式。
  • 这个功能和上一条类似,不难,但是会比较烦。换行以后会涉及到每行高度的变化,于是打开编辑面板时的对齐代码就需要调整。同时变化的高度也意味着右侧的齿轮按钮也要相应变化,现在它的高度是写死的。更麻烦的是 Input 框的高度自适应我没做过,可能要换用 contenteditable 的 div,要调整不少代码。好处当然也是显而易见的,长句子台词可以一次看完整了。

    Input 框暂时先不修改了,太麻烦要查资料,一时搞不定。条目本身现在是换行式的了。

  • Done:编辑条目时按 Ctrl+Enter 直接提交当前条目并自动打开下一条的编辑界面并同时播放音频。
  • 我自己,目前还是小站音频条目听写的第一贡献者,我觉得我在编辑条目时遇到的麻烦,你们肯定也遇到了。这个 Ctrl+Enter 的连续编辑提交功能应该会对热心的贡献者比较有帮助。当然伸手党是永远不会遇到这种麻烦的,但谁管你们那么多呢。

    我还没写过根据键盘组合键执行功能的代码,不过想必 Google 一下很容易就能得到答案。这功能不难,但是会比较烦。

 

  • Todo:编辑界面的标签钩选稍微改进一点。
  • 打算把现在的钩选换成和顶部筛选框类似的变色选中,顺便加上和英雄主题色相同的背景色。估计也挺麻烦的,tag 数据都是根据数据库生成的,现在数据库里没有英雄颜色,于是得改后端代码了。

  • Todo:逐步修正音频标签数据。
  • 这个没啥说的,其实主要依靠的是拆解软件的更新。之所以写在这里,是因为现有拆解结果,在数据处理上还能有少许改进,只是要花不少时间。

你看,写完这个,又快天亮了。