基础工具与工作流 · daymade/claude-code-skills

video-comparer

This skill should be used when comparing two videos to analyze compression results or quality differences. Generates interactive HTML reports with quality metrics (PSNR, SSIM) and frame-by-frame visual comparisons. Triggers when users mention "compare videos", "video quality", "compression analysis", "before/after compression", or request quality assessment of compressed videos.

风险提醒:黄色 · 留意使用AI 侦查报告
作者 daymadeGitHub daymade/claude-code-skills ↗Stars 1392许可 MIT(仓库根 LICENSE,Copyright (c) 2025 daymade;GitHub API spdx MIT)commit d5c4678cb5
agent 宿主通常会约束 skill 执行权限;风险提醒为 AI 侦查观点,不构成质量或安全保证。第三方 skill 仅作拆解与展示,安装使用风险自负,版权归原作者。

1实现原理 · 为什么它能做到

实现路径是单个 Python 脚本编排 ffmpeg/ffprobe:ffprobe 取元数据 → ffmpeg 算 PSNR/SSIM → ffmpeg 按间隔抽帧缩放 → 把帧与指标填进一份 HTML 模板 → 落盘报告。没有模型参与,纯确定性流水线。

video-comparer/scripts/compare.py
for tool in ['ffmpeg', 'ffprobe']:
注:docstring 自述全文:'Compare two videos (original vs compressed) and generate interactive HTML report. Analyzes video metadata, quality metrics (PSNR/SSIM), and creates frame-by-frame comparison UI with slider, side-by-side, and grid viewing modes.';check_ffmpeg_installed 先跑 [tool,'-version'] 预检。

报告不是「先写模板再渲染」,而是「读模板 + 用正则逐块替换占位」——因此对模板结构高度耦合,同一段落换行或元素位置一变即静默失配。

video-comparer/scripts/compare.py
r'<div class="metric-value">[\d.]+ dB</div>\s*<div class="metric-subtitle">偏低</div>',
注:同段落共有 Step 1 到 Step 11 十一条 re.sub/replace(codec、分辨率、码率、体积、PSNR、SSIM、发现的问题、保留较好的方面、技术解释、帧选择按钮、JS 帧数与间隔)。

帧序列不是内嵌进 HTML,而是复制到 HTML 同级的子目录(original/ 与 wechat/),由模板用相对路径引用——即产物是一组文件而非单文件。

video-comparer/scripts/compare.py
Copy frames to a subdirectory next to the HTML output. Args: frames: List of (timestamp, frame_path) tuples output_html_path: Path to the output HTML file subfolder: Subdirectory name (e.g., 'original', 'wechat')
注:实现为 output_dir = output_html_path.parent / subfolder; dest_name = f"frame_{i:03d}.png"; shutil.copy2(frame_path, dest_path)。模板侧对应 src="original/frame_001.png" 与 src="wechat/frame_001.png";调用处为 copy_frames_to_output(original_frames, output_path, 'original') 与 (compressed_frames, output_path, 'wechat')。

输入校验是一等公民:路径 resolve 后检查存在性/是文件/扩展名白名单/可读/体积上限,ffmpeg 与 ffprobe 的存在性单独预检并给出各平台安装指引。

video-comparer/scripts/compare.py
# Configuration constants ALLOWED_EXTENSIONS = {'.mp4', '.mov', '.avi', '.mkv', '.webm'} MAX_FILE_SIZE_MB = 500 FFMPEG_TIMEOUT = 300 # 5 minutes FFPROBE_TIMEOUT = 30 # 30 seconds BASE_FRAME_HEIGHT = 800 FRAME_INTERVAL = 5 # seconds
注:validate_video_file 内有注释 '# Convert to absolute path to prevent directory traversal';文件头注释声明 'Security features: - Path validation and sanitization - Command injection prevention - Resource limits (file size, timeout) - Comprehensive error handling'。

命令注入防护靠「参数列表 + 无 shell=True + 超时」三件套,而不是字符串转义——即 subprocess 的正确用法。

video-comparer/scripts/compare.py
try: result = subprocess.run( args, capture_output=True, timeout=timeout, check=True, text=True ) return result.stdout
注:函数 docstring 明确:'args: Command arguments as list (prevents shell injection)';全目录 grep shell=True 零命中。

在算指标前先做「两段视频是否同一内容」的一致性校验(时长差阈值、压缩后反而变大时告警),避免把不同视频的对比当成质量分析输出。

video-comparer/scripts/compare.py
""" Validate that two videos are likely the same content. Args: metadata1: First video metadata (original) metadata2: Second video metadata (compressed) duration_threshold: Maximum allowed duration difference in seconds allow_size_increase: If False, warn when compressed is larger
注:属少见设计:多数对比工具直接出数字,不做内容一致性前置。

2核心能力

01视频元数据提取(codec / 分辨率 / 帧率 / 码率 / 时长 / 体积)
02PSNR / SSIM 质量指标计算与压缩率统计
03按间隔抽帧并统一缩放到 800px 高以便逐帧对比
04三种查看模式(滑块 / 并排 / 网格)+ 50%-200% 缩放
05参数化与批处理(-o 输出路径、--interval 抽帧间隔、shell 循环批量对比)
06自动生成「发现的问题 / 保留较好的方面 / 技术解释」三块结论文本
07输入校验与资源限制(扩展名白名单、500MB 上限、ffmpeg 300s / ffprobe 30s 超时)
08可调常量文档(各常量对处理时间、输出体积、画质权衡的影响)

3外部依赖

类型依赖
cliffmpeg(必需;抽帧、缩放、算 PSNR/SSIM)
cliffprobe(必需;元数据提取)
clipython3(3.8+,脚本运行时;仅标准库)
packageimg-comparison-slider(Web Component,报告页从 CDN 加载,非随包分发)
networkunpkg(第三方 CDN;打开报告时由浏览器发起请求)
networkffmpeg 官网(文档里的安装指引链接,非运行时依赖)

4风险提醒 风险提醒:黄色 · 留意使用

风险提醒:黄色 · 留意使用
  • 「self-contained / works offline」是错误声明,会导致误用 — 实际产物是 HTML + original/ + wechat/ 目录,且滑块组件从 unpkg CDN 加载。若按文档只取走 HTML 文件、或在离线环境打开,会丢帧或失去滑块功能。建议以实际产物结构为准(整目录一起搬,且需联网才有滑块)。
  • 报告页存在第三方 CDN 供应链暴露 — 任何打开报告的人都会向 unpkg.com 请求并执行 img-comparison-slider 的脚本。若报告被当作内部静态文件流转,这属于未预期的对外请求;CDN 内容一旦被篡改即影响所有打开者。介意的话可把该 JS/CSS 下载到本地并改写模板引用。
  • 输出目录会被静默覆盖 — 脚本在与报告同级处创建 original/ 与 wechat/ 并写入 frame_001.png…,未检查已存在同名内容;对同一输出目录重复运行会覆盖旧帧(旧报告帧数更多时还会残留多余帧,导致报告与实物不一致)。
  • 文档漂移面较大 — README 行数(696 vs 实际 1036)、架构清单(漏 configuration.md)、base64 内嵌声明、CDN 声明与 SKILL.md 互相矛盾;README 与 SKILL.md 对同一产物给出不同描述。使用者应先以代码与产物实测为准。
  • 模板正则耦合,改动易静默失效 — 报告生成依赖对固定模板文本的 11 处 re.sub/replace(含 r'<div class="frame-selector">.*?</div>' 这类 DOTALL 匹配)。一旦改模板结构,替换会静默不生效(正则无匹配也不报错),产出的报告会保留占位内容。
  • 默认专用词汇与非微信场景不匹配 — 帧目录写死 wechat/、标签写「微信视频号」「微信重新编码」。用于其他平台(B 站/抖音/YouTube)时产物文案会张冠李戴,需改模板与源码常量。
风险提醒:黄色,留意使用。依据:skill 自身代码不接触网络、不读任何凭证或环境变量、不做安全降级(无 TLS 关闭、无反爬、无 sudo),唯一外部能力是调用本机 ffmpeg/ffprobe,属可预期的本地工具调用。实际存在三点注意:①外发对象虽非脚本所为,但生成的报告页会从 unpkg 拉取 img-comparison-slider 的 JS/CSS——任何打开该报告的人都会向第三方 CDN 发起请求并执行其脚本,属产物侧供应链暴露;②输出目录中会创建 original/ 与 wechat/ 并覆盖同名 frame_*.png,未做存在性保护;③文档声称报告「self-contained / works offline」与实现不符(实际为 HTML + 两个帧目录 + CDN 依赖),属误导性声明而非安全降级,但会让使用者在离线场景下误判可用性。综合为黄档:常规本地工具行为 + 一处产物侧第三方依赖,未见凭证读取或安全降级。

5第二遍独立确认

  • [discrepancy] SKILL.md 的『frames 以 base64 内嵌进 self-contained HTML』声明是否成立 — 不成立,是本次侦查发现的最重问题。SKILL.md 第 99 行:'The script extracts frames at specified intervals (default: 5 seconds), scales them to consistent height (800px) for comparison, and embeds them as base64 data URLs in self-contained HTML. Temporary files are automatically cleaned after processing.' 实际实现是把帧复制到 HTML 同级子目录:copy_frames_to_output 的 docstring 即 'Copy frames to a subdirectory next to the HTML output.',dest_name = f"frame_{i:03d}.png"、shutil.copy2(frame_path, dest_path),调用处为 copy_frames_to_output(original_frames, output_path, 'original') 与 (compressed_frames, output_path, 'wechat')。全目录 grep base64/b64encode/data:image 在 .py 与 .html 中零命中(仅出现在 README 的依赖清单与 configuration.md 的说明文字里)。模板侧确认用相对路径:<img slot="first" id="originalImage" src="original/frame_001.png" ...>。即产物是「HTML + original/ + wechat/」一整个目录,不是单文件。
  • [discrepancy] SKILL.md 的『Self-contained format (no server required, works offline)』是否成立 — 不成立(两条独立原因)。SKILL.md 第 108 行原文:'- Self-contained format (no server required, works offline)'。①存在外部 CDN 依赖:template.html 第 7-8 行加载 https://unpkg.com/img-comparison-slider@8/dist/styles.css 与 .../index.js,断网时滑块组件不可用;②依赖同级帧目录(见上一条),单独拷走 HTML 会丢帧。值得注意的是 README 自己承认了 CDN 依赖(依赖清单写 'img-comparison-slider (loaded from CDN)'),却同时在架构说明里声称 template.html 具备 'Base64-encoded image embedding'——即 README 内部亦不自洽,且与 SKILL.md 的 offline 声明互相矛盾。
  • [discrepancy] README 的『Architecture』信息是否与文件系统/实现一致 — 三处不符:①行数——README 写 'compare.py # Main comparison script (696 lines)',实测 wc -l = 1036 行;②架构清单只列 video_metrics.md 与 ffmpeg_commands.md 两份 reference,漏掉实际存在且被 SKILL.md 明确引用的 references/configuration.md;③把 template.html 描述为 'Base64-encoded image embedding',与实现不符(见第 1 条)。
  • [discrepancy] 文档是否宣称了未实现的能力(VMAF 等) — SKILL.md 层面是对的:它只说两个指标(PSNR、SSIM),与脚本一致(grep -i vmaf 在 compare.py 中零命中)。但 references/video_metrics.md(4 处 VMAF)与 references/ffmpeg_commands.md(3 处,含 'VMAF Calculation' 小节)都提供了 VMAF 的定义与 ffmpeg 命令。即参考材料覆盖了脚本未实现的第三指标——不是夸大声明(SKILL.md 未据此承诺),而是「参考材料超出工具能力」,使用者若按 reference 期待 VMAF 输出会落空。
  • [ok] 三条安全声明(path validation / command injection prevention / resource limits)是否有代码对应 — 逐条核实成立:①path validation —— validate_video_file 内 Path(path).resolve()、exists()、is_file()、后缀白名单 ALLOWED_EXTENSIONS、os.access(R_OK)、体积上限 MAX_FILE_SIZE_MB=500;②command injection prevention —— run_ffmpeg_command 以参数列表调用 subprocess.run(docstring:'args: Command arguments as list (prevents shell injection)'),全文无 shell=True;③resource limits —— FFMPEG_TIMEOUT=300、FFPROBE_TIMEOUT=30,且 TimeoutExpired 有专门异常映射。声明未夸大。
  • [ok] 是否存在未声明的网络/凭证行为 — 反例检索失败:compare.py 的 import 段为 argparse/json/logging/os/re/subprocess/sys/tempfile/time/pathlib/typing,无 urllib/requests/socket/http;全目录 grep token/secret/password/api_key/getenv/os.environ 零命中;无 base64 大块、无 >200 字符无空格长行。结论成立。
  • [discrepancy] 模板的『通用性』呈现与内容是否相符 — SKILL.md/README 把它呈现为通用的视频压缩对比工具,但 assets/template.html 的文案与路径是微信专用的:标签为「🎬 原始视频 (AVC)」与「📱 微信视频号 (HEVC)」、替换目标里有 '<div class="metric-subtitle">微信重新编码</div>'、帧相对路径写死 'wechat/frame_001.png',且 compare.py 的复制调用也写死 subfolder='wechat'(而非 'compressed')。结论:工具可用,但默认产物带有上游使用场景的专用词汇;非微信场景需自行改模板与源码常量。
  • [ok] pin commit 与 skill.path 是否与任务书表格一致 — git rev-parse HEAD = d5c4678cb5d4fd6acc9c922690df035dbd33d247,与任务书表格『库内 HEAD』逐字一致;目录位于仓库根,相对路径 video-comparer;本目录最后一次提交 878f947(2026-09-07)。GitHub API 复核 MIT / stars 1392 / pushed 2026-09-15T09:30:04Z。

6结论

  • 安全实现扎实:路径 resolve + 扩展名白名单 + 体积上限 + 参数列表 subprocess(无 shell=True)+ 双超时,三条安全声明在代码中都有对应,不是空话。
  • 先做「两段视频是否同一内容」的一致性校验(时长差阈值、压缩后反而更大时告警),避免输出无意义的质量结论。
  • 指标解读有配套参考(PSNR/SSIM 量程、质量分档、压缩目标与码率指引),输出不是裸数字。
  • 可调常量与其影响被文档化,调参有据可依(体积/时间/画质三角)。
  • 交互报告形态好:滑块 / 并排 / 网格三模式 + 缩放 + 帧选择按钮,便于人工判断压缩是否伤及观感。
  • 适合:适合:需要判断「视频压缩后画质掉了多少」的人——自媒体/视频工作者对比平台二次压缩前后的画质、开发者验证转码参数、以及想知道码率降了但观感是否可接受的情形。单命令 + 本地交互报告,无需服务端,也不需要 Python 第三方包。
    不适合:不适合:期望产出单个可离线分发的 HTML 文件的场景(实际是目录包且依赖 CDN);不能安装 ffmpeg 的环境(硬依赖);需要 VMAF 等更贴近感知的指标的场景(脚本只算 PSNR/SSIM,VMAF 仅存在于参考文档);以及需要跨格式/跨分辨率内容对齐的场景(工具假设两段视频同内容、时长接近)。
    安装 agent 直装可复制
    ① 本站镜像 更新 2026-09-15
    方式 A · 人下载镜像包下载 video-comparer.tar.gz
    sha256: f6f34839800154ed…
    方式 B · JSON 格式安装指南,复制给 agent
    安装指南
    agent 读 JSON 指南后会自动从本站下载安装,无需更多说明。
    ② 上游 GitHub · 原始来源
    能访问 GitHub?直接去上游安装(实时版,可能已更新)GitHub 原始 ↗
    本页镜像锁定 commit d5c4678cb5;上游为实时仓库。
    来源信息 GitHub 原始
    作者 / 仓库daymade / daymade/claude-code-skills
    Stars1392
    最近推送2026-09-15
    本 skill commitd5c4678cb5
    许可MIT(仓库根 LICENSE,Copyright (c) 2025 daymade;GitHub API spdx MIT)
    本站信息
    收录日期2026-09-06
    分类基础工具与工作流
    侦查报告AI 侦查 · 2 遍 · 2026-09-06
    本站镜像与 GitHub 原始是不同来源:本站锁定 commit 快照经 /r2 分发;GitHub 为实时上游,内容可能已更新。
    同分类邻近