视频质量门禁

SKILL前端设计
前端设计 未标注权限 许可证不明确
安装这个技能

视频生产质量门禁 — 7道关卡自动化检查,全部通过才交付。覆盖HTML结构、时间线、TTS朗读、时长匹配、音频质量、动画执行、视觉抽检。

一句话选型结论

按资料字段整理

视频质量门禁是前端设计类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类前端设计 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_d8831e99/video-quality-gates
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

前端设计
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_d8831e99仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验2026-11-06上游最后核验时间 · 数据更新 2026-11-06
正文体量19.7 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
出页面与组件

按描述生成页面结构和组件草稿。

调整样式与布局

改间距、配色与响应式布局。

生成设计说明

把设计稿整理成开发能接的说明。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在前端设计场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
视频质量门禁当前 未标注权限 未标注 未标注 未标注 有
前端设计 只读 GitHub 仓库 882.3 万 Codex、Claude、Cursor 有
Vercel 组合模式 联网访问 GitHub 仓库 385.9 万 Codex、Claude、Cursor 有
Vercel React native skills 前端 只读 GitHub 仓库 246.9 万 Codex、Claude、Cursor 有
adapt 搜索 浏览器控制 GitHub 仓库 202.7 万 Codex、Claude、Cursor 有
使用我的浏览器 浏览器控制 GitHub 仓库 184.8 万 Codex、Claude、Cursor 有

SKILL.md 全文

19.7 KB
模型实际读到的说明书原文,来自技能仓库

视频质量门禁 — 7道关卡

概述

视频生产完成后,必须依次通过7道关卡检查。任一关卡失败,立即停止并告警,不得交付。

品牌标准模板

所有模世界视频必须遵循以下标准:

项目 标准值
品牌名 模世界(禁止写成"膜世界")
英文名 MOSZE
Slogan 手机配件一站式批发
主色调 #2563eb(蓝色)
辅助色 #06b6d4(青色)、#fbbf24(黄色)、#10b981(绿色)、#f44336(红色)
字体 Inter, -apple-system, Helvetica Neue, Arial
分辨率 1080×1920(竖屏)
时长 25秒
Logo位置 底部居中,高度70px
场景数 4个(s1钩子 → s2参数 → s3卖点 → s4品牌)

关卡0:HTML结构检查

时机: HTML文件生成后立即执行
方法: 代码级静态检查

检查项

def gate0_html_structure(html_content: str) -> dict:
    """检查HTML文件结构完整性"""
    results = []

    # 1. doctype存在
    if not html_content.strip().upper().startswith('<!DOCTYPE HTML>'):
        results.append(('FAIL', '缺少<!DOCTYPE html>声明'))
        return {'pass': False, 'details': results}

    # 2. <div id="root">存在
    if '<div id="root">' not in html_content:
        results.append(('FAIL', '缺少<div id="root">容器'))
        return {'pass': False, 'details': results}

    # 3. GSAP script存在
    if 'gsap.timeline' not in html_content:
        results.append(('FAIL', '缺少GSAP时间线代码'))
        return {'pass': False, 'details': results}

    # 4. window.__timelines注册存在
    if 'window.__timelines' not in html_content:
        results.append(('FAIL', '缺少window.__timelines注册'))
        return {'pass': False, 'details': results}

    # 5. 4个场景(支持两种写法:id="s1" 或 class="scene s1")
    for scene_num in ['1', '2', '3', '4']:
        has_id = f'id="s{scene_num}"' in html
        has_class = f'class="scene s{scene_num}"' in html
        if not has_id and not has_class:
            results.append(('FAIL', f'缺少场景 s{scene_num}'))
            return {'pass': False, 'details': results}

    # 6. 选择器格式正确(#root .s1 而非 .s1)
    import re
    gsap_calls = re.findall(r'#root \.s\d+', html_content)
    if not gsap_calls:
        results.append(('WARN', '未使用#root .s1选择器,动画可能不生效'))

    # 7. duration属性匹配
    if 'data-duration="25"' not in html_content:
        results.append(('FAIL', 'data-duration不是25秒'))
        return {'pass': False, 'details': results}

    # 8. 品牌名检查
    if '膜世界' in html_content:
        results.append(('FAIL', '发现错别字"膜世界",应为"模世界"'))
        return {'pass': False, 'details': results}

    results.append(('PASS', 'HTML结构检查通过'))
    return {'pass': True, 'details': results}

关卡0.5:时间线验证

时机: HTML结构检查通过后执行
方法: 模拟执行GSAP时间线,验证动画有效性

检查项

def gate05_timeline_validation(html_content: str) -> dict:
    """验证GSAP时间线是否有效"""
    results = []

    # 1. 提取所有tl.to()调用
    import re
    to_calls = re.findall(r'\.to\([^)]+\)', html_content)

    if len(to_calls) < 4:
        results.append(('FAIL', f'GSAP .to()调用过少({len(to_calls)}个,至少需要4个场景动画)'))
        return {'pass': False, 'details': results}

    # 2. 每个场景是否有动画(支持 #root .s1 和 .s1 两种写法)
    scenes_with_anim = set()
    for call in to_calls:
        for scene_num in ['1', '2', '3', '4']:
            if f'.s{scene_num}' in call:
                scenes_with_anim.add(f'.s{scene_num}')

    missing = set(['.s1', '.s2', '.s3', '.s4']) - scenes_with_anim
    if missing:
        results.append(('FAIL', f'以下场景无动画:{missing}'))
        return {'pass': False, 'details': results}

    # 3. 检查时间线总时长(通过解析时间戳估算)
    # 提取所有时间点
    time_points = re.findall(r'},\s*(\d+\.?\d*)\s*\)', html_content)
    if time_points:
        max_time = max(float(t) for t in time_points)
        if max_time < 20:
            results.append(('FAIL', f'时间线最大时间仅{max_time}s,不足25s'))
            return {'pass': False, 'details': results}
        if max_time > 30:
            results.append(('WARN', f'时间线最大时间{max_time}s,超过25s'))

    # 4. 检查是否有重复注册同一场景
    scene_registrations = re.findall(r'set\(\'#root \.s(\d)\'', html_content)
    from collections import Counter
    counts = Counter(scene_registrations)
    for scene, count in counts.items():
        if count > 1:
            results.append(('WARN', f'场景s{scene}被注册{count}次'))

    results.append(('PASS', '时间线验证通过'))
    return {'pass': True, 'details': results}

关卡1:脚本内容检查

时机: 生成配音前执行
方法: 文本扫描 + TTS友好度检测

检查项

def gate1_script_content(texts: list, html_content: str) -> dict:
    """检查配音文本和HTML内容"""
    results = []

    # 1. 错别字扫描
    forbidden = {
        '膜世界': '模世界',
        '精钻膜': '晶钻膜',
        '防窥uvm': '防窥UV膜',
        '壳磁': '壳瓷',
        '电镀丝滑mo': '电镀丝滑膜',
    }

    all_text = ' '.join([t[2] for t in texts]) + html_content
    for wrong, correct in forbidden.items():
        if wrong in all_text:
            results.append(('FAIL', f'发现错别字"{wrong}",应为"{correct}"'))
            return {'pass': False, 'details': results}

    # 2. 品牌名统一检查
    if '鑫源光电' in html_content and '模世界' not in html_content:
        results.append(('WARN', 'HTML中使用鑫源光电但未使用模世界,请确认品牌'))

    # 3. 参数合理性
    # 厚度检查
    thickness_match = re.search(r'(\d+\.?\d*)\s*(mm|厘米|m)', all_text)
    if thickness_match:
        val = float(thickness_match.group(1))
        unit = thickness_match.group(2)
        if unit == '厘米' and val > 0.1:
            results.append(('FAIL', f'厚度{val}厘米不合理,应为{val*10}mm'))
            return {'pass': False, 'details': results}

    # 透光率检查
    trans_match = re.search(r'(\d+\.?\d*)%', all_text)
    if trans_match:
        val = float(trans_match.group(1))
        if val > 100:
            results.append(('FAIL', f'透光率{val}%超过100%,不合理'))
            return {'pass': False, 'details': results}

    # 4. 广告法风险词
    risk_words = ['最', '第一', '绝对', '顶级', '国家级', '独家']
    for word in risk_words:
        if word in all_text:
            results.append(('WARN', f'发现广告法风险词"{word}",建议删除或修改'))

    # 5. TTS友好度检测
    tts_issues = []
    # 检查数字+字母组合
    num_alpha = re.findall(r'(\d+[A-Z]+)', all_text)
    for na in num_alpha:
        tts_issues.append(f'"{na}"可能被TTS误读(如9H读成九H)')

    # 检查小数点
    decimals = re.findall(r'(\d+\.\d+)', all_text)
    for d in decimals:
        tts_issues.append(f'"{d}"可能被TTS读成"零点...",建议确认是否需汉字')

    if tts_issues:
        results.append(('WARN', f'TTS朗读潜在问题:{len(tts_issues)}处'))
        for issue in tts_issues[:3]:
            results.append(('INFO', issue))

    # 6. 标点符号检查(逗号=短停,句号=长停)
    sentences = re.split(r'[。!?]', all_text)
    for s in sentences:
        if len(s) > 50:
            results.append(('WARN', f'句子过长({len(s)}字),建议拆分'))

    results.append(('PASS', '脚本内容检查通过'))
    return {'pass': True, 'details': results}

关卡2:时长匹配检查

时机: 配音生成后、渲染前执行
方法: 对比配音时长与场景动画时间窗口

检查项

def gate2_duration_match(audio_files: dict, html_content: str) -> dict:
    """检查配音时长与场景时间窗口是否匹配"""
    results = []

    # 1. 获取每个音频文件的实际时长
    import subprocess
    audio_durations = {}
    for name, path in audio_files.items():
        if os.path.exists(path):
            cmd = ['ffprobe', '-v', 'error', '-show_entries', 'format=duration',
                   '-of', 'default=noprint_wrappers=1:nokey=1', path]
            proc = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
            if proc.returncode == 0:
                audio_durations[name] = float(proc.stdout.strip())

    # 2. 提取HTML中每个场景的时间窗口
    # s1: 0-5s, s2: 5-13s, s3: 13-20s, s4: 20-25s
    scene_windows = {
        's1': (0, 5),
        's2': (5, 13),
        's3': (13, 20),
        's4': (20, 25),
    }

    # 3. 对比音频时长与场景窗口
    for name, duration in audio_durations.items():
        scene_num = name[1]  # s1 -> 1
        scene_id = f's{scene_num}'
        if scene_id in scene_windows:
            start, end = scene_windows[scene_id]
            window = end - start

            if duration > window + 2:  # 允许2秒缓冲
                results.append(('FAIL', f'{name}时长{duration:.1f}s超过场景窗口{window}s(超限{duration-window:.1f}s)'))
                return {'pass': False, 'details': results}
            elif duration < window - 5:  # 少于窗口5秒告警
                results.append(('WARN', f'{name}时长{duration:.1f}s远小于场景窗口{window}s'))

    # 4. 总时长检查
    total_audio = sum(audio_durations.values())
    if total_audio > 27:  # 25秒+2秒缓冲
        results.append(('WARN', f'总配音时长{total_audio:.1f}s,接近或超过25秒'))

    results.append(('PASS', '时长匹配检查通过'))
    return {'pass': True, 'details': results}

关卡2.5:音频质量检查

时机: 渲染前执行
方法: ffprobe检测静音、爆音、音量突变

检查项

def gate25_audio_quality(audio_files: dict) -> dict:
    """检查音频文件质量"""
    results = []

    import subprocess

    for name, path in audio_files.items():
        if not os.path.exists(path):
            results.append(('FAIL', f'{name}文件不存在'))
            return {'pass': False, 'details': results}

        # 1. 检测开头静音(前0.5秒应有声音)
        cmd = ['ffprobe', '-v', 'error', '-show_entries', 'format_tags=loudness',
               '-of', 'default=noprint_wrappers=1:nokey=1', path]
        proc = subprocess.run(cmd, capture_output=True, text=True, timeout=10)

        # 2. 检测总体音量(RMS)
        cmd = ['ffmpeg', '-i', path, '-af', 'astats=metadata=1:reset=0',
               '-f', 'null', '-']
        proc = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
        stderr = proc.stderr

        # 检查是否有静音段(RMS < -60dB)
        if 'Flat factor' in stderr:
            # 提取RMS值
            import re
            rms_match = re.search(r'RMS level db: (-?\d+\.?\d*)', stderr)
            if rms_match:
                rms = float(rms_match.group(1))
                if rms < -60:
                    results.append(('WARN', f'{name}平均音量过低({rms}dB)'))

        # 3. 检测文件大小合理性
        size = os.path.getsize(path)
        if size < 1000:  # 小于1KB通常为静音或空文件
            results.append(('FAIL', f'{name}文件大小仅{size}字节,可能为空或静音'))
            return {'pass': False, 'details': results}

    results.append(('PASS', '音频质量检查通过'))
    return {'pass': True, 'details': results}

关卡3:渲染结果检查

时机: 视频渲染完成后执行
方法: 文件检查 + 像素对比验证动画执行

检查项

def gate3_render_result(video_path: str, audio_path: str) -> dict:
    """检查渲染结果"""
    results = []

    import subprocess
    import os

    # 1. 文件存在性
    if not os.path.exists(video_path):
        results.append(('FAIL', '渲染视频文件不存在'))
        return {'pass': False, 'details': results}

    # 2. 文件大小检查
    size = os.path.getsize(video_path)
    if size < 10000:  # 小于10KB异常
        results.append(('FAIL', f'视频文件仅{size}字节,渲染可能失败'))
        return {'pass': False, 'details': results}

    # 3. 视频时长检查
    cmd = ['ffprobe', '-v', 'error', '-show_entries', 'format=duration',
           '-of', 'default=noprint_wrappers=1:nokey=1', video_path]
    proc = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
    if proc.returncode == 0:
        duration = float(proc.stdout.strip())
        if abs(duration - 25) > 2:  # 允许2秒误差
            results.append(('FAIL', f'视频时长{duration:.1f}s,预期25s'))
            return {'pass': False, 'details': results}

    # 4. 音频合并检查
    if os.path.exists(audio_path):
        cmd = ['ffprobe', '-v', 'error', '-select_streams', 'a:0',
               '-show_entries', 'stream=codec_type',
               '-of', 'default=noprint_wrappers=1:nokey=1', video_path]
        proc = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
        if 'audio' not in proc.stdout:
            results.append(('FAIL', '视频文件中无音频轨道'))
            return {'pass': False, 'details': results}

    # 5. 动画执行验证(首帧vs中帧像素差异)
    # 截取0s帧和12.5s帧
    frame0 = video_path.replace('.mp4', '_frame0.png')
    frame_mid = video_path.replace('.mp4', '_frame_mid.png')

    subprocess.run(['ffmpeg', '-y', '-ss', '0', '-i', video_path,
                    '-frames:v', '1', frame0], capture_output=True, timeout=30)
    subprocess.run(['ffmpeg', '-y', '-ss', '12.5', '-i', video_path,
                    '-frames:v', '1', frame_mid], capture_output=True, timeout=30)

    if os.path.exists(frame0) and os.path.exists(frame_mid):
        # 计算像素差异
        import cv2
        img0 = cv2.imread(frame0)
        img_mid = cv2.imread(frame_mid)

        if img0 is not None and img_mid is not None:
            diff = cv2.absdiff(img0, img_mid)
            diff_ratio = np.count_nonzero(diff) / (img0.size / 3)

            if diff_ratio < 0.05:  # 差异小于5%
                results.append(('FAIL', '动画可能未执行(首帧与中帧差异<5%)'))
                return {'pass': False, 'details': results}

    results.append(('PASS', '渲染结果检查通过'))
    return {'pass': True, 'details': results}

关卡4:视觉抽检

时机: 所有关卡通过后执行
方法: 截取关键帧,用vision模型检查画面

检查项

def gate4_visual_review(video_path: str) -> dict:
    """视觉抽检 — 关键帧画面检查"""
    results = []

    # 截取5个关键帧
    keyframes = {
        '0s': '0',
        '5s': '5',
        '13s': '13',
        '20s': '20',
        '24s': '24',
    }

    frame_paths = {}
    for name, time_str in keyframes.items():
        frame_path = video_path.replace('.mp4', f'_kf_{name}.png')
        subprocess.run(['ffmpeg', '-y', '-ss', time_str, '-i', video_path,
                        '-frames:v', '1', frame_path], capture_output=True, timeout=30)
        if os.path.exists(frame_path):
            frame_paths[name] = frame_path

    # 调用vision模型检查
    # 注意:这里需要vision工具,在skill执行时动态调用
    results.append(('INFO', f'已截取{len(frame_paths)}个关键帧'))
    results.append(('INFO', '请使用vision工具检查以下关键帧:'))
    for name, path in frame_paths.items():
        results.append(('INFO', f'  {name}: {path}'))

    # 检查项(人工+vision):
    # 1. 文字是否清晰可读
    # 2. 品牌名是否正确(模世界)
    # 3. Logo是否完整显示
    # 4. 颜色是否符合品牌标准
    # 5. 是否有明显排版错误

    results.append(('PASS', '视觉抽检完成(请人工确认)'))
    return {'pass': True, 'details': results}

执行流程

视频生成完成
    │
    ▼
关卡0:HTML结构检查 ──── 失败 → 停止,返回错误
    │ 通过
    ▼
关卡0.5:时间线验证 ──── 失败 → 停止,返回错误
    │ 通过
    ▼
关卡1:脚本内容检查 ──── 失败 → 停止,返回错误
    │ 通过(WARN允许继续)
    ▼
关卡2:时长匹配检查 ──── 失败 → 停止,返回错误
    │ 通过
    ▼
关卡2.5:音频质量检查 ── 失败 → 停止,返回错误
    │ 通过
    ▼
关卡3:渲染结果检查 ──── 失败 → 停止,返回错误
    │ 通过
    ▼
关卡4:视觉抽检 ──────── 人工确认
    │
    ▼
交付视频

告警规则

  • FAIL:必须修复,不得跳过
  • WARN:记录问题,可继续但需在交付报告中说明
  • INFO:提示信息,不影响流程

交付报告格式

## 视频质量门禁报告

- 关卡0 HTML结构:✅ 通过
- 关卡0.5 时间线验证:✅ 通过
- 关卡1 脚本内容:⚠️ WARN(TTS朗读问题3处)
- 关卡2 时长匹配:✅ 通过
- 关卡2.5 音频质量:✅ 通过
- 关卡3 渲染结果:✅ 通过
- 关卡4 视觉抽检:✅ 通过

总耗时:X秒

注意事项

  1. 关卡0-2.5是自动化检查,无需人工干预
  2. 关卡3的像素对比需要opencv-python,如未安装则跳过
  3. 关卡4需要vision模型,如不可用则改为人工检查
  4. 任一关卡FAIL,立即停止流程,不得交付
  5. 品牌名"模世界"是最高优先级检查,发现"膜世界"直接FAIL

关联文件

  • references/integration-matrix.md — 所有引用本skill的视频生产流程清单
  • scripts/quality_gate.py — 自动化执行脚本

Pitfalls(实战经验)

音频截断陷阱(2026-07-08发现 ⭐)

症状:视频文件存在、时长正确、有音频轨道,但实际时长只有21秒而不是25秒。

原因:ffmpeg合成时用了-shortest参数,音频只有21秒所以视频被截断到21秒。

修复:配音短于25秒时,用ffmpeg -af "apad=pad_dur=X"填充到25秒,再用-shortest合成。

# 错误做法:直接 -shortest
ffmpeg -i video.mp4 -i audio.m4a -c:v copy -shortest final.mp4  # 可能被截断

# 正确做法:先填充音频
AUDIO_DUR=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 audio.m4a)
if (( $(echo "$AUDIO_DUR < 23" | bc -l 2>/dev/null || echo 0) )); then
    ffmpeg -y -i audio.m4a -af "apad=pad_dur=$((25-${AUDIO_DUR%.*}))" -t 25 audio_padded.m4a
    ffmpeg -y -i video.mp4 -i audio_padded.m4a -c:v copy -c:a aac -b:a 192k -shortest final.mp4
else
    ffmpeg -y -i video.mp4 -i audio.m4a -c:v copy -c:a aac -b:a 192k -shortest final.mp4
fi

场景选择器兼容(2026-07-08发现)

V7模板使用class="scene s1"而非id="s1"。关卡0和关卡0.5必须同时检查两种写法。

TTS误报(2026-07-08发现)

关卡1的TTS友好度检测会扫描整个HTML(包括CSS类名如6B、4ECDC),产生大量误报。实际只需检查配音文本文件,不应扫描HTML源码中的class/id。

常见问题

5 问
答案由本站依据条目字段整理
视频质量门禁怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_d8831e99/video-quality-gates。安装方式为未标注。装完刷新技能列表或重开客户端。

视频质量门禁支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

视频质量门禁权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

视频质量门禁收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

视频质量门禁用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 2026-11-06。