基础工具与工作流 · 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.

L4 高权限 · 分级授权与审计V1 已固定执行命令联网读写文件Dual-pass Audit
Author daymadeGitHub daymade/claude-code-skills ↗Stars 1392License MIT(仓库根 LICENSE,Copyright (c) 2025 daymade;GitHub API spdx MIT)Commit d5c4678cb5
管控等级描述 skill 的能力与建议配套的管控措施,不代表质量或安全认证,也不表示可用或不可用。是否使用由用户和管理者决定。不同 agent 宿主对权限的约束各不相同,请勿假定宿主一定会提供安全兜底。第三方 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外部依赖

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

4管控建议与判定依据

建议配套管控措施
面向 Agent
分级或逐次授权,建议在沙箱运行
面向管理者
审批流程、可回滚、全程审计
判定依据(文件路径与关键语句摘要)
  • scripts/: 执行本地脚本或命令: python3 scripts/compare.py <original> <compressed> [-o out.html] [--interva
  • 网络端点: 声明外部网络访问: 生成的报告页会由浏览器加载 https://unpkg.com/img-comparison-slider@8/dist/{styles.css,in
  • 本地工作目录: 文件读写与工件输出: 写出 HTML 报告到 -o 指定路径(默认 ./comparison.html):open(output_path, 'w', encoding='
审计说明: 。依据: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 仅存在于参考文档);以及需要跨格式/跨分辨率内容对齐的场景(工具假设两段视频同内容、时长接近)。
    Install Agent-Ready
    ① Verified Mirror 2026-09-15
    Option A · Direct DownloadDownload video-comparer.tar.gz
    sha256: f6f34839800154ed…
    Option B · Copy Guide for Agent
    install.json
    agent 读 JSON 指南后会自动从本站下载安装,无需更多说明。
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit d5c4678cb5.