dsh-duplicate-file-check
2026-11-06 重构:面板改为分组折叠,6 个任务各自独立(状态/进度/开始按钮), 完全一致校验新增「严格(逐字节)」模式;新增随机文件名、按大小移动、按时长移动三个批量改名任务。 抓帧任务会先排除完全一致的文件再统计时长。 重复文件查重(DSH 插件)。两种筛法,对应主人 Java 项目
D:\workspace\rename里simpleCheckAndDelete与checkByDuration的思路,并各修了一处: ## 一、完全重复文件 1. 递归列出所有来源目录的文件,先按大小分组,只处理「同大小、数量 > 1」的组。 2. 组内每个文件取头 / 中 / 尾各 100KB 做字节比对(不是只取文件头)。 - 原 Java 版只查头 100KB,且小文件读满会报错;这里对size < 300KB的文件自适应成三等分,不会越界。 - 用 Buffer 原生字节比较,不经过字符串编码,避免任何字符集歧义。 3. 三处都相同才算重复。按组列出,并标出「保留」的那一个(组内 mtime 最早、路径字典序最前)。 改进了原版:抽样从 1 处变 3 处,误判率下降,成本仍只是每文件 300KB 读。 ## 二、视频抓帧(疑似重复) 1. 只看.mp4。 2. 用 ffprobe 读时长(毫秒),按时长容差(可配,默认 100ms)排序后贪心分组。 3. 组内数量 > 1 才继续(只要不唯一就算疑似)。 4. 每段视频抓前 10 秒、每秒 1 帧,缩成 16×16 灰度;组内两两逐帧算平均绝对差,相似度 ≥ 阈值(默认 0.9)即判为同一段视频。 - 这样能覆盖「转码后字节不同、内容相同」的情况。 ## 参数 - 来源目录:可多个,添加后自动保存。 - 疑似重复输出目录:自动保存、自动创建。 - 时长容差(ms)、抓帧相似度(0.1–1)。 - 配置落在~/.dsh/duplicate-file-check.json。 ## 两个动作 - 删除完全重复文件:每组只保留一个,其余删除。删除前有确认框,失败会逐条报。 - 移动重复文件:把疑似视频组里的文件移动到输出目录,重命名为1xxxxx.mp4,从 100000 起、按输出目录里已有编号续号,避免覆盖。 ## 注意 - 两个写操作都只作用于「最近一次扫描结果」,不会重复执行同一批。 - 扫描是异步的,面板每 1.5 秒轮询进度;扫描中写按钮是禁用的。 - 视频模式只要求「组内 > 1」:只要时长相近的两个视频被抓帧判为相似,就会进结果。 ## 三、批量改后缀 把来源目录里所有.<原后缀>的文件改成.<新后缀>(大小写不敏感,只改扩展名、不动内容)。 - 「预览」先给数字:匹配几个、可改几个、同名冲突几个。 - 「执行改名」有确认框;目标文件已存在时跳过,不覆盖。 - 后缀只允许 1–16 位字母数字,防止写出../这类路径片段。 ## 并发与强制停止 - 扫描全程有界并发:concurrency配置项(0 = 自动,按 CPU 核数、上限 8;可手填 1–32)。 - 目录遍历后,stat → 抽样比对 → ffprobe → 抓帧 各阶段都是并发执行。 - 抓帧/ffprobe 是子进程,并发上限单独收在 8 以内,避免把机器打满。 - 强制停止:扫描、删除、移动、改名执行中都可以点「强制停止」,服务端立刻置停止标志并 SIGKILL 所有在跑的子进程(ffprobe/ffmpeg),各循环在下一个检查点退出,状态显示「已停止」。 - 「停止」只终止正在进行的操作,不会回滚已经完成的删除/移动/改名——已做的事照实算数。
统一编码(MOV / AVI / WMV → MP4)
- 按文件头判定,不看扩展名:MOV 认
ftyp+qt品牌,AVI 认RIFF....AVI,WMV 认 ASF 的 16 字节头。改错后缀的文件也能认出来,本来就是 MP4 的会跳过。 - 命中后先移动到「对比目录」,再转成同名 MP4(
clip.avi→clip.mp4);同一目录里已有同名文件时自动加(1)、(2),不覆盖。 - 转码参数对齐原片:分辨率、帧率、视频码率(同时设 maxrate/bufsize)、音频取样率、声道数、音频码率;视频统一 H.264 + yuv420p,音频 AAC,并加
+faststart。 - 保留原文件默认勾选:原件留在对比目录里。取消勾选时,转码成功的原件才会被删除;失败的一律保留。
边界处理(2026-11-06 加固)
- 可变帧率:先比较
avg_frame_rate与r_frame_rate,差值 <1% 才按恒定帧率加-r;否则用-fps_mode passthrough保留原始时间戳,不补帧不丢帧。 - 码率缺失:源没有
bit_rate时,用体积×8/时长 − 音频码率估算视频码率;仍然估不出就用 CRF 18。 - 多音轨与元数据:
-map 0:a?保留全部音轨,-map_metadata 0保留标题/拍摄时间等元数据。 - 失败回位:转码失败或无法解析的文件会被搬回来源原路径(同名被占则加
.failed),不在对比目录里冒充结果。 - 空间预检:开始前按总大小 ×1.2 估算,目标盘不够就提前报错,不会转到一半失败。
- 输出校验:先写
.<名字>.mp4.part,校验非空、可解析、时长与原片相差不超过 2 秒或 2%,通过后才改名并(在未勾选保留时)删除原件。 - 旋转:读 Display Matrix / rotate 标签,90°/270° 时交换宽高,竖拍不会被压扁。
统一编码的可选项
- 智能直通(默认开):源文件本来就是 H.264 + AAC 且非 HDR 时,只换容器不重编码——秒级完成、零画质损失。关掉则一律重编码。
- 编码器:
x264(默认,兼容最好)/NVIDIA NVENC/Intel QSV/AMD AMF。运行时探测可用性,选中的编码器不存在会退回 x264 并写日志。 - HDR 处理:
强制 8bit(默认)/色调映射到 SDR/保留 HDR(HEVC)。色调映射需要 ffmpeg 的 zscale 真正可用,程序会实测一次;不可用时降级为强制 8bit 并在日志里说明,不会让整个任务失败。
其他行为
- 移动类任务(按大小 / 按时长)的目标目录不能在来源目录内部,会被直接拒绝,避免下次运行把结果再搬一遍。
- 「移动/删除/改后缀/转码」执行期间,所有动作按钮保持禁用,直到状态轮询确认任务已经在跑(或 6 秒兜底解锁),不再有 1.5 秒的可点窗口。
No comments yet. Be the first to write one.