chore: add GitHub Actions release workflow, signing docs, ignore sidecar binaries
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: '版本号 (例如 1.5.16)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build-macos:
|
||||
name: Build macOS (Universal)
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Setup Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: x86_64-apple-darwin,aarch64-apple-darwin
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: tauri-app
|
||||
run: npm ci
|
||||
|
||||
- name: Build macOS Universal
|
||||
working-directory: tauri-app
|
||||
run: npm run tauri -- build --target universal-apple-darwin
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos-universal
|
||||
path: |
|
||||
tauri-app/src-tauri/target/universal-apple-darwin/release/bundle/dmg/*.dmg
|
||||
tauri-app/src-tauri/target/universal-apple-darwin/release/bundle/macos/*.app
|
||||
|
||||
build-windows:
|
||||
name: Build Windows (x64)
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Setup Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: x86_64-pc-windows-msvc
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: tauri-app
|
||||
run: npm ci
|
||||
|
||||
- name: Build Windows x64
|
||||
working-directory: tauri-app
|
||||
shell: pwsh
|
||||
run: npm run tauri -- build --target x86_64-pc-windows-msvc
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: windows-x64
|
||||
path: |
|
||||
tauri-app/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe
|
||||
tauri-app/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/msi/*.msi
|
||||
@@ -22,3 +22,5 @@ __pycache__/
|
||||
test_kick.sh
|
||||
.playwright-mcp/
|
||||
*.seed_materials_cache.json
|
||||
tauri-app/src-tauri/binaries/*
|
||||
.tauri-signing-key
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
# GitHub Actions 发版方案(免费双平台构建)
|
||||
|
||||
> 利用 GitHub Actions 免费的 macOS + Windows runner,实现零成本的双平台自动构建。
|
||||
|
||||
---
|
||||
|
||||
## 一、方案优势
|
||||
|
||||
| 对比项 | GitLab CI(原有) | GitHub Actions(新方案) |
|
||||
|--------|------------------|------------------------|
|
||||
| macOS runner | 需要自维护 Mac 物理机 | ✅ GitHub 免费提供(`macos-latest`) |
|
||||
| Windows runner | 需要自维护 Windows 物理机 | ✅ GitHub 免费提供(`windows-latest`) |
|
||||
| 并发构建 | 依赖 runner 在线状态 | ✅ 随时触发,并行执行 |
|
||||
| 产物保留 | 30 天(可配置) | 90 天(默认) |
|
||||
| 成本 | 维护 runner 硬件/电费 | ✅ 公有仓库完全免费 |
|
||||
|
||||
---
|
||||
|
||||
## 二、前置准备
|
||||
|
||||
### 2.1 确认代码已推送到 GitHub
|
||||
|
||||
GitHub Actions 只能构建 **GitHub 仓库**中的代码。如果你的代码只在 GitLab,需要:
|
||||
|
||||
```bash
|
||||
# 在 GitHub 创建空仓库,然后添加远程地址
|
||||
git remote add github https://github.com/你的用户名/美家卡智影.git
|
||||
git push github master
|
||||
git push github --tags
|
||||
```
|
||||
|
||||
### 2.2 配置 GitHub Secrets(只需做一次)
|
||||
|
||||
进入 GitHub 仓库 → **Settings → Secrets and variables → Actions → New repository secret**
|
||||
|
||||
| Secret 名称 | 值 | 说明 |
|
||||
|------------|-----|------|
|
||||
| `TAURI_SIGNING_PRIVATE_KEY` | `dW50cnVzdGVk...`(私钥完整内容) | Tauri updater 签名私钥 |
|
||||
| `TAURI_SIGNING_PRIVATE_KEY_PASSWORD` | (留空,不创建) | 若私钥有密码则填,当前无密码 |
|
||||
|
||||
> 私钥从 `tauri-app/.tauri-signing-key` 文件中复制全部内容。
|
||||
|
||||
---
|
||||
|
||||
## 三、触发构建的两种方式
|
||||
|
||||
### 方式一:推送 Git tag(推荐,用于正式发版)
|
||||
|
||||
```bash
|
||||
# 1. 更新版本号
|
||||
python scripts/bump-version.py 1.5.16
|
||||
|
||||
# 2. 提交并推送
|
||||
git add -A
|
||||
git commit -m "release: v1.5.16"
|
||||
git push github master
|
||||
|
||||
# 3. 推送 tag 自动触发 GitHub Actions
|
||||
git tag v1.5.16
|
||||
git push github v1.5.16
|
||||
```
|
||||
|
||||
推送 tag 后,GitHub Actions 自动开始构建:
|
||||
- `build-macos`:在 `macos-latest` runner 上构建 Universal `.dmg`
|
||||
- `build-windows`:在 `windows-latest` runner 上构建 `.exe` + `.msi`
|
||||
|
||||
### 方式二:手动触发(用于测试或紧急打包)
|
||||
|
||||
进入 GitHub 仓库 → **Actions → Release → Run workflow**
|
||||
- 输入版本号(如 `1.5.16`)
|
||||
- 点击 **Run workflow**
|
||||
|
||||
---
|
||||
|
||||
## 四、获取构建产物
|
||||
|
||||
构建完成后(约 10-20 分钟):
|
||||
|
||||
1. 进入 GitHub 仓库 → **Actions**
|
||||
2. 点击最新的 workflow run
|
||||
3. 页面底部 **Artifacts** 区域下载:
|
||||
- `macos-universal` → 包含 `.dmg` 和 `.app`
|
||||
- `windows-x64` → 包含 `.exe` 和 `.msi`
|
||||
|
||||
---
|
||||
|
||||
## 五、发布更新包(手动执行)
|
||||
|
||||
下载产物后,解压到本地目录,执行发版脚本:
|
||||
|
||||
```bash
|
||||
# 1. 创建产物目录结构
|
||||
mkdir -p bundle/macos
|
||||
mkdir -p bundle/dmg
|
||||
mkdir -p bundle/nsis
|
||||
mkdir -p bundle/msi
|
||||
|
||||
# 2. 将下载的 artifact 解压并放入对应目录
|
||||
# macos-universal.zip → bundle/dmg/xxx.dmg, bundle/macos/xxx.app
|
||||
# windows-x64.zip → bundle/nsis/xxx.exe, bundle/msi/xxx.msi
|
||||
|
||||
# 3. 执行发版脚本
|
||||
cd python-api
|
||||
python scripts/publish_release.py \
|
||||
--version 1.5.16 \
|
||||
--notes "修复视频导出崩溃\n优化启动速度" \
|
||||
--bundle-dir ../bundle
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、注意事项
|
||||
|
||||
### 6.1 macOS 签名
|
||||
GitHub Actions 的 `macos-latest` runner **没有 Apple Developer 证书**,构建出的 `.app`/`.dmg` 与本地构建一样,是未签名的。用户在首次打开时仍需手动允许。
|
||||
|
||||
**后续升级**:购买 Apple Developer Program 后,在 workflow 中添加:
|
||||
```yaml
|
||||
env:
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
```
|
||||
|
||||
### 6.2 Windows 签名
|
||||
同理,未配置 `WINDOWS_CERTIFICATE` 时,`.exe` 会有 SmartScreen 提示。购买证书后配置 GitHub Secrets 即可自动签名。
|
||||
|
||||
### 6.3 产物自动上传到 Release(可选进阶)
|
||||
|
||||
如需让 GitHub 自动创建 Release 页面并上传产物,可在 workflow 末尾添加:
|
||||
|
||||
```yaml
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: |
|
||||
tauri-app/src-tauri/target/**/bundle/dmg/*.dmg
|
||||
tauri-app/src-tauri/target/**/bundle/nsis/*.exe
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、文件清单
|
||||
|
||||
| 文件 | 作用 |
|
||||
|------|------|
|
||||
| `.github/workflows/release.yml` | GitHub Actions 工作流定义 |
|
||||
| `tauri-app/.tauri-signing-key` | 私钥源文件(本地保存) |
|
||||
| `tauri-app/src-tauri/tauri.key.pub` | 公钥(已提交 Git) |
|
||||
@@ -0,0 +1,165 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
检查提示词素材库标题与数据库三级分类名的一致性
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def extract_db_categories(sql_path: str) -> set[str]:
|
||||
"""从 seed_categories.sql 提取所有三级分类 name"""
|
||||
with open(sql_path, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
# 匹配 level=3 的 name
|
||||
matches = re.findall(r"VALUES \('[^']+', '([^']+)', \d+, 3,", content)
|
||||
return set(matches)
|
||||
|
||||
|
||||
def extract_prompt_titles(prompts_dir: str) -> dict[str, list[str]]:
|
||||
"""从提示词文件提取素材库标题"""
|
||||
results = {}
|
||||
dir_path = Path(prompts_dir)
|
||||
|
||||
for txt_file in dir_path.rglob("*.txt"):
|
||||
with open(txt_file, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
# 查找【内置完整素材库标题】或【内置素材库标题】部分
|
||||
marker1 = "【内置完整素材库标题】"
|
||||
marker2 = "【内置素材库标题】"
|
||||
|
||||
start_idx = -1
|
||||
for marker in [marker1, marker2]:
|
||||
idx = content.find(marker)
|
||||
if idx != -1:
|
||||
start_idx = idx + len(marker)
|
||||
break
|
||||
|
||||
if start_idx == -1:
|
||||
continue
|
||||
|
||||
# 提取标题列表(到下一个【标记或文件末尾)
|
||||
section = content[start_idx:]
|
||||
# 找下一个【标记
|
||||
next_marker = section.find("【")
|
||||
if next_marker != -1:
|
||||
section = section[:next_marker]
|
||||
|
||||
# 逐行解析,去除空行和注释
|
||||
titles = []
|
||||
for line in section.strip().split("\n"):
|
||||
line = line.strip()
|
||||
if not line or line.startswith("(") or line.startswith("备注"):
|
||||
continue
|
||||
# 去除可能的编号前缀如 "1、" 或 "- "
|
||||
line = re.sub(r"^\d+[、.]\s*", "", line)
|
||||
line = re.sub(r"^[-•]\s*", "", line)
|
||||
if line:
|
||||
titles.append(line)
|
||||
|
||||
if titles:
|
||||
results[str(txt_file.relative_to(dir_path))] = titles
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def normalize_for_compare(text: str) -> str:
|
||||
"""标准化用于比较(去除空格和特殊字符)"""
|
||||
return re.sub(r"\s+", "", text)
|
||||
|
||||
|
||||
def main():
|
||||
db_path = Path(__file__).parent.parent / "python-api" / "scripts" / "seed_categories.sql"
|
||||
prompts_dir = Path(__file__).parent.parent / "python-api" / "app" / "ai" / "prompts" / "system"
|
||||
|
||||
db_categories = extract_db_categories(str(db_path))
|
||||
prompt_titles = extract_prompt_titles(str(prompts_dir))
|
||||
|
||||
print(f"数据库三级分类总数: {len(db_categories)}")
|
||||
print(f"包含素材库标题的提示词文件数: {len(prompt_titles)}")
|
||||
print()
|
||||
|
||||
# 汇总所有提示词中的标题
|
||||
all_prompt_titles = set()
|
||||
for file, titles in prompt_titles.items():
|
||||
for t in titles:
|
||||
all_prompt_titles.add(t)
|
||||
|
||||
print(f"提示词中素材库标题总数(去重): {len(all_prompt_titles)}")
|
||||
print()
|
||||
|
||||
# 对比:提示词中有但数据库中没有的
|
||||
in_prompt_not_db = []
|
||||
for title in all_prompt_titles:
|
||||
if title not in db_categories and normalize_for_compare(title) not in {normalize_for_compare(c) for c in db_categories}:
|
||||
in_prompt_not_db.append(title)
|
||||
|
||||
# 对比:数据库中有但提示词中没有的
|
||||
in_db_not_prompt = []
|
||||
prompt_normalized = {normalize_for_compare(t) for t in all_prompt_titles}
|
||||
for cat in db_categories:
|
||||
if cat not in all_prompt_titles and normalize_for_compare(cat) not in prompt_normalized:
|
||||
in_db_not_prompt.append(cat)
|
||||
|
||||
# 统计按二级分类分组
|
||||
db_by_parent = defaultdict(list)
|
||||
for cat in db_categories:
|
||||
# 从分类名推断父分类,如 "卧室原始结构-毛坯基础" → "毛坯基础"
|
||||
parts = cat.split("-")
|
||||
if len(parts) >= 2:
|
||||
parent = parts[-1]
|
||||
else:
|
||||
parent = "其他"
|
||||
db_by_parent[parent].append(cat)
|
||||
|
||||
print("=" * 60)
|
||||
print("【不一致统计】")
|
||||
print("=" * 60)
|
||||
|
||||
print(f"\n1. 提示词中有但数据库中无(可能为错误或过时标题): {len(in_prompt_not_db)} 个")
|
||||
if in_prompt_not_db:
|
||||
for t in sorted(in_prompt_not_db):
|
||||
print(f" - {t}")
|
||||
else:
|
||||
print(" (无)")
|
||||
|
||||
print(f"\n2. 数据库中有但提示词中无(缺少素材引用): {len(in_db_not_prompt)} 个")
|
||||
if in_db_not_prompt:
|
||||
# 按父分类分组
|
||||
by_parent = defaultdict(list)
|
||||
for cat in in_db_not_prompt:
|
||||
parts = cat.split("-")
|
||||
parent = parts[-1] if len(parts) >= 2 else "其他"
|
||||
by_parent[parent].append(cat)
|
||||
|
||||
for parent in sorted(by_parent.keys()):
|
||||
cats = by_parent[parent]
|
||||
print(f"\n 【{parent}】({len(cats)}个)")
|
||||
for cat in sorted(cats):
|
||||
print(f" - {cat}")
|
||||
else:
|
||||
print(" (无)")
|
||||
|
||||
# 统计各提示词文件中的标题数量
|
||||
print(f"\n3. 各提示词文件素材库标题数量:")
|
||||
for file in sorted(prompt_titles.keys()):
|
||||
titles = prompt_titles[file]
|
||||
# 计算该文件中与数据库不一致的数量
|
||||
mismatched = [t for t in titles if t not in db_categories and normalize_for_compare(t) not in {normalize_for_compare(c) for c in db_categories}]
|
||||
status = f" ⚠️ 有{mismatched}个不一致" if mismatched else " ✅ 一致"
|
||||
print(f" {file}: {len(titles)}个标题{status}")
|
||||
if mismatched:
|
||||
for m in mismatched:
|
||||
print(f" ❌ {m}")
|
||||
|
||||
# 总体匹配率
|
||||
matched = len(all_prompt_titles) - len(in_prompt_not_db)
|
||||
match_rate = (matched / len(all_prompt_titles) * 100) if all_prompt_titles else 0
|
||||
print(f"\n总体匹配率: {match_rate:.1f}% ({matched}/{len(all_prompt_titles)})")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
网红开篇素材归集脚本
|
||||
====================
|
||||
|
||||
把所有重命名后的 .mp4 复制到一个统一目录,方便批量上传。
|
||||
|
||||
用法:
|
||||
python3 scripts/collect_viral_opening.py
|
||||
|
||||
输出:
|
||||
/Users/0fun/Desktop/网红开篇_upload/ ← 41 个 mp4 平铺在此
|
||||
"""
|
||||
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main():
|
||||
src_dir = Path("/Users/0fun/Desktop/网红开篇")
|
||||
out_dir = Path("/Users/0fun/Desktop/网红开篇_upload")
|
||||
out_dir.mkdir(exist_ok=True)
|
||||
|
||||
copied = 0
|
||||
for mp4_file in sorted(src_dir.rglob("*.mp4")):
|
||||
if mp4_file.name.startswith("."):
|
||||
continue
|
||||
|
||||
dest = out_dir / mp4_file.name
|
||||
shutil.copy2(mp4_file, dest)
|
||||
copied += 1
|
||||
print(f"✓ {mp4_file.name}")
|
||||
|
||||
print(f"\n✅ 共复制 {copied} 个文件到: {out_dir}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,206 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
网红开篇素材批量入库脚本
|
||||
============================
|
||||
|
||||
功能:
|
||||
1. 遍历指定目录下的 .mp4 视频
|
||||
2. 按规则 md5(父目录名_原文件名) 生成新文件名
|
||||
3. 用 ffprobe 提取视频时长
|
||||
4. 生成七牛云上传命令 + 数据库 INSERT SQL
|
||||
|
||||
用法:
|
||||
cd /Users/0fun/work/meijiaka-zy
|
||||
python scripts/import_viral_opening.py \
|
||||
--src "/Users/0fun/Desktop/网红开篇" \
|
||||
--bucket "meijiaka-zy" \
|
||||
--prefix "materials" \
|
||||
--domain "https://media.liche.cn"
|
||||
|
||||
输出:
|
||||
- scripts/viral_opening_upload.sh # 七牛云批量上传命令
|
||||
- scripts/viral_opening_insert.sql # 数据库 INSERT 语句
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
# 目录名 → 三级分类 slug 映射(与 seed_categories.sql 对应)
|
||||
FOLDER_TO_SLUG = {
|
||||
"暴力拆除-恶搞开篇": "wanghong-egao-blcc",
|
||||
"搞笑涂料施工-恶搞开篇": "wanghong-egao-gxtlsg",
|
||||
"工地恶搞-恶搞开篇": "wanghong-egao-gdeg",
|
||||
"贴砖恶搞-恶搞开篇": "wanghong-egao-tzeg",
|
||||
"吸睛画面-恶搞开篇": "wanghong-egao-xjhm",
|
||||
"炫技-恶搞开篇": "wanghong-egao-xj",
|
||||
"防水翻车漏水-施工翻车镜": "wanghong-fanche-fsfcls",
|
||||
}
|
||||
|
||||
|
||||
def get_video_duration(filepath: str) -> float | None:
|
||||
"""用 ffmpeg -i 提取视频时长(秒),保留 2 位小数"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["ffmpeg", "-i", filepath],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=30,
|
||||
)
|
||||
# ffmpeg 把信息输出到 stderr,解析 Duration: 00:00:04.25
|
||||
import re
|
||||
match = re.search(r"Duration:\s+(\d+):(\d+):(\d+\.\d+)", result.stderr)
|
||||
if match:
|
||||
hours, minutes, seconds = match.groups()
|
||||
total = float(hours) * 3600 + float(minutes) * 60 + float(seconds)
|
||||
return round(total, 2)
|
||||
except Exception as e:
|
||||
print(f" ⚠️ 读取时长失败: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def md5_filename(parent_name: str, original_name: str) -> str:
|
||||
"""
|
||||
生成新文件名:md5(父目录名_原文件名).mp4
|
||||
|
||||
示例:
|
||||
父目录名: 暴力拆除-恶搞开篇
|
||||
原文件名: 5月16日(13).mp4
|
||||
拼接: 暴力拆除-恶搞开篇_5月16日(13).mp4
|
||||
md5: a3f7b2c8... (32位十六进制)
|
||||
结果: a3f7b2c8....mp4
|
||||
"""
|
||||
raw = f"{parent_name}_{original_name}"
|
||||
md5_hex = hashlib.md5(raw.encode("utf-8")).hexdigest()
|
||||
return f"{md5_hex}.mp4"
|
||||
|
||||
|
||||
def scan_videos(src_dir: str) -> list[dict]:
|
||||
"""扫描目录,返回视频信息列表"""
|
||||
videos = []
|
||||
src_path = Path(src_dir)
|
||||
|
||||
for mp4_file in sorted(src_path.rglob("*.mp4")):
|
||||
# 跳过 macOS 系统文件
|
||||
if mp4_file.name.startswith("."):
|
||||
continue
|
||||
|
||||
parent_folder = mp4_file.parent.name
|
||||
original_name = mp4_file.name
|
||||
|
||||
# 检查分类映射
|
||||
slug = FOLDER_TO_SLUG.get(parent_folder)
|
||||
if not slug:
|
||||
print(f"⚠️ 未找到分类映射: {parent_folder}/{original_name},跳过")
|
||||
continue
|
||||
|
||||
new_filename = md5_filename(parent_folder, original_name)
|
||||
|
||||
print(f"📹 处理: {parent_folder}/{original_name} → {new_filename}")
|
||||
duration = get_video_duration(str(mp4_file))
|
||||
if duration is None:
|
||||
print(f" ❌ 无法读取时长,跳过")
|
||||
continue
|
||||
|
||||
videos.append({
|
||||
"original_path": str(mp4_file),
|
||||
"parent_folder": parent_folder,
|
||||
"original_name": original_name,
|
||||
"new_filename": new_filename,
|
||||
"slug": slug,
|
||||
"duration": duration,
|
||||
})
|
||||
|
||||
return videos
|
||||
|
||||
|
||||
def generate_outputs(videos: list[dict], bucket: str, prefix: str, domain: str) -> None:
|
||||
"""生成上传脚本和入库 SQL"""
|
||||
script_dir = Path(__file__).parent
|
||||
|
||||
# 1. 生成上传脚本
|
||||
upload_script = script_dir / "viral_opening_upload.sh"
|
||||
with open(upload_script, "w", encoding="utf-8") as f:
|
||||
f.write("#!/bin/bash\n# 网红开篇素材批量上传脚本\n\n")
|
||||
for v in videos:
|
||||
cdn_url = f"{domain}/{bucket}/{prefix}/{v['new_filename']}"
|
||||
f.write(
|
||||
f"# {v['parent_folder']}/{v['original_name']} ({v['duration']}s)\n"
|
||||
f"# qshell put {bucket} {prefix}/{v['new_filename']} "
|
||||
f"'{v['original_path']}'\n"
|
||||
f"# 或: qshell fput {bucket} {prefix}/{v['new_filename']} "
|
||||
f"'{v['original_path']}'\n\n"
|
||||
)
|
||||
os.chmod(upload_script, 0o755)
|
||||
|
||||
# 2. 生成入库 SQL
|
||||
sql_file = script_dir / "viral_opening_insert.sql"
|
||||
with open(sql_file, "w", encoding="utf-8") as f:
|
||||
f.write("-- 网红开篇素材入库 SQL\n")
|
||||
f.write("-- 共 {} 个视频\n\n".format(len(videos)))
|
||||
f.write("BEGIN;\n\n")
|
||||
|
||||
for v in videos:
|
||||
cdn_url = f"{domain}/{bucket}/{prefix}/{v['new_filename']}"
|
||||
f.write(
|
||||
"INSERT INTO mjk_broll_materials "
|
||||
"(category_id, title, url, duration, usage_count, status, created_at, updated_at)\n"
|
||||
"SELECT id, '{}', '{}', {}, 0, 'active', NOW(), NOW()\n"
|
||||
"FROM mjk_broll_categories WHERE slug = '{}' AND level = 3;\n".format(
|
||||
v["new_filename"],
|
||||
cdn_url,
|
||||
v["duration"],
|
||||
v["slug"],
|
||||
)
|
||||
)
|
||||
f.write(
|
||||
"-- 来源: {} | 时长: {}s | 分类: {}\n\n".format(
|
||||
v["parent_folder"],
|
||||
v["duration"],
|
||||
v["slug"],
|
||||
)
|
||||
)
|
||||
|
||||
f.write("COMMIT;\n")
|
||||
|
||||
# 3. 生成映射 JSON(方便核对)
|
||||
mapping_file = script_dir / "viral_opening_mapping.json"
|
||||
with open(mapping_file, "w", encoding="utf-8") as f:
|
||||
json.dump(videos, f, ensure_ascii=False, indent=2)
|
||||
|
||||
print(f"\n✅ 生成完成:")
|
||||
print(f" - 上传脚本: {upload_script}")
|
||||
print(f" - 入库 SQL: {sql_file}")
|
||||
print(f" - 映射 JSON: {mapping_file}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="网红开篇素材批量入库")
|
||||
parser.add_argument("--src", default="/Users/0fun/Desktop/网红开篇", help="素材源目录")
|
||||
parser.add_argument("--bucket", default="meijiaka-zy", help="七牛云 bucket")
|
||||
parser.add_argument("--prefix", default="materials", help="七牛云路径前缀")
|
||||
parser.add_argument("--domain", default="https://media.liche.cn", help="CDN 域名")
|
||||
args = parser.parse_args()
|
||||
|
||||
if not Path(args.src).exists():
|
||||
print(f"❌ 目录不存在: {args.src}")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"🔍 扫描目录: {args.src}\n")
|
||||
videos = scan_videos(args.src)
|
||||
|
||||
if not videos:
|
||||
print("❌ 未找到可处理的视频")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"\n📊 共找到 {len(videos)} 个视频")
|
||||
generate_outputs(videos, args.bucket, args.prefix, args.domain)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
网红开篇素材批量重命名脚本
|
||||
============================
|
||||
|
||||
按规则 md5(父目录名_原文件名) 重命名本地视频文件。
|
||||
|
||||
用法:
|
||||
python3 scripts/rename_viral_opening.py
|
||||
|
||||
效果:
|
||||
/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/5月16日(13).mp4
|
||||
→ /Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/2eaf1185....mp4
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def md5_filename(parent_name: str, original_name: str) -> str:
|
||||
raw = f"{parent_name}_{original_name}"
|
||||
return hashlib.md5(raw.encode("utf-8")).hexdigest() + ".mp4"
|
||||
|
||||
|
||||
def main():
|
||||
src_dir = Path("/Users/0fun/Desktop/网红开篇")
|
||||
renamed = []
|
||||
|
||||
for mp4_file in sorted(src_dir.rglob("*.mp4")):
|
||||
if mp4_file.name.startswith("."):
|
||||
continue
|
||||
|
||||
parent_folder = mp4_file.parent.name
|
||||
original_name = mp4_file.name
|
||||
new_name = md5_filename(parent_folder, original_name)
|
||||
|
||||
if mp4_file.name == new_name:
|
||||
continue # 已经重命名过
|
||||
|
||||
new_path = mp4_file.parent / new_name
|
||||
|
||||
print(f"{original_name}\n → {new_name}")
|
||||
mp4_file.rename(new_path)
|
||||
renamed.append({
|
||||
"original": original_name,
|
||||
"new": new_name,
|
||||
"folder": parent_folder,
|
||||
"path": str(new_path),
|
||||
})
|
||||
|
||||
print(f"\n✅ 共重命名 {len(renamed)} 个文件")
|
||||
|
||||
# 保存重命名记录
|
||||
record = Path(__file__).parent / "viral_opening_renamed.json"
|
||||
with open(record, "w", encoding="utf-8") as f:
|
||||
json.dump(renamed, f, ensure_ascii=False, indent=2)
|
||||
print(f"📄 记录已保存: {record}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,211 @@
|
||||
-- 网红开篇素材入库 SQL
|
||||
-- 共 41 个视频
|
||||
|
||||
BEGIN;
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'b3aff6db0536a8d7f51277bd17a449b3.mp4', 'https://media.liche.cn/meijiaka-zy/materials/b3aff6db0536a8d7f51277bd17a449b3.mp4', 4.02, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xjhm' AND level = 3;
|
||||
-- 来源: 吸睛画面-恶搞开篇 | 时长: 4.02s | 分类: wanghong-egao-xjhm
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '845c6856746752c319239869d03d2def.mp4', 'https://media.liche.cn/meijiaka-zy/materials/845c6856746752c319239869d03d2def.mp4', 4.5, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xjhm' AND level = 3;
|
||||
-- 来源: 吸睛画面-恶搞开篇 | 时长: 4.5s | 分类: wanghong-egao-xjhm
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '4819ccec34b556b6a686503c8496d2d2.mp4', 'https://media.liche.cn/meijiaka-zy/materials/4819ccec34b556b6a686503c8496d2d2.mp4', 9.17, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xjhm' AND level = 3;
|
||||
-- 来源: 吸睛画面-恶搞开篇 | 时长: 9.17s | 分类: wanghong-egao-xjhm
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '2073d7ca41856cc162ac3a86881eeee8.mp4', 'https://media.liche.cn/meijiaka-zy/materials/2073d7ca41856cc162ac3a86881eeee8.mp4', 6.32, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xjhm' AND level = 3;
|
||||
-- 来源: 吸睛画面-恶搞开篇 | 时长: 6.32s | 分类: wanghong-egao-xjhm
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '0097dceb9c7218d66f4b31d9ad47aee3.mp4', 'https://media.liche.cn/meijiaka-zy/materials/0097dceb9c7218d66f4b31d9ad47aee3.mp4', 5.43, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xjhm' AND level = 3;
|
||||
-- 来源: 吸睛画面-恶搞开篇 | 时长: 5.43s | 分类: wanghong-egao-xjhm
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '811ad18d3f8e5cf3792460e4aabf1744.mp4', 'https://media.liche.cn/meijiaka-zy/materials/811ad18d3f8e5cf3792460e4aabf1744.mp4', 5.2, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xjhm' AND level = 3;
|
||||
-- 来源: 吸睛画面-恶搞开篇 | 时长: 5.2s | 分类: wanghong-egao-xjhm
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '7f1ec7aeab78ee64171fa6685c4439fc.mp4', 'https://media.liche.cn/meijiaka-zy/materials/7f1ec7aeab78ee64171fa6685c4439fc.mp4', 8.01, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xjhm' AND level = 3;
|
||||
-- 来源: 吸睛画面-恶搞开篇 | 时长: 8.01s | 分类: wanghong-egao-xjhm
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'df3223bb4de53e197ddd944ed5d2e5d5.mp4', 'https://media.liche.cn/meijiaka-zy/materials/df3223bb4de53e197ddd944ed5d2e5d5.mp4', 8.8, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xjhm' AND level = 3;
|
||||
-- 来源: 吸睛画面-恶搞开篇 | 时长: 8.8s | 分类: wanghong-egao-xjhm
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'a2c9adea107f99cdc5f6fb6b02236579.mp4', 'https://media.liche.cn/meijiaka-zy/materials/a2c9adea107f99cdc5f6fb6b02236579.mp4', 7.11, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xjhm' AND level = 3;
|
||||
-- 来源: 吸睛画面-恶搞开篇 | 时长: 7.11s | 分类: wanghong-egao-xjhm
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'c77b5e546cb0393a5e7c3c4cea3bebb2.mp4', 'https://media.liche.cn/meijiaka-zy/materials/c77b5e546cb0393a5e7c3c4cea3bebb2.mp4', 6.62, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xjhm' AND level = 3;
|
||||
-- 来源: 吸睛画面-恶搞开篇 | 时长: 6.62s | 分类: wanghong-egao-xjhm
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'a29f7c2ffa5a39326d6aed18f0c6df8d.mp4', 'https://media.liche.cn/meijiaka-zy/materials/a29f7c2ffa5a39326d6aed18f0c6df8d.mp4', 5.04, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xjhm' AND level = 3;
|
||||
-- 来源: 吸睛画面-恶搞开篇 | 时长: 5.04s | 分类: wanghong-egao-xjhm
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'e7cc059acaca9d9286c547c1f9f3c39f.mp4', 'https://media.liche.cn/meijiaka-zy/materials/e7cc059acaca9d9286c547c1f9f3c39f.mp4', 5.02, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xjhm' AND level = 3;
|
||||
-- 来源: 吸睛画面-恶搞开篇 | 时长: 5.02s | 分类: wanghong-egao-xjhm
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '8c5bbf96530c1a03b9f084d13e06c7c9.mp4', 'https://media.liche.cn/meijiaka-zy/materials/8c5bbf96530c1a03b9f084d13e06c7c9.mp4', 7.34, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gdeg' AND level = 3;
|
||||
-- 来源: 工地恶搞-恶搞开篇 | 时长: 7.34s | 分类: wanghong-egao-gdeg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '24c662049e2db23c8ad8e39b188d769c.mp4', 'https://media.liche.cn/meijiaka-zy/materials/24c662049e2db23c8ad8e39b188d769c.mp4', 5.02, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gdeg' AND level = 3;
|
||||
-- 来源: 工地恶搞-恶搞开篇 | 时长: 5.02s | 分类: wanghong-egao-gdeg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '6f9c760668d743102ae4e6e0943a658f.mp4', 'https://media.liche.cn/meijiaka-zy/materials/6f9c760668d743102ae4e6e0943a658f.mp4', 4.25, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gdeg' AND level = 3;
|
||||
-- 来源: 工地恶搞-恶搞开篇 | 时长: 4.25s | 分类: wanghong-egao-gdeg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '44622ad5abe2e66279550bc7f95dcc6b.mp4', 'https://media.liche.cn/meijiaka-zy/materials/44622ad5abe2e66279550bc7f95dcc6b.mp4', 6.08, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gdeg' AND level = 3;
|
||||
-- 来源: 工地恶搞-恶搞开篇 | 时长: 6.08s | 分类: wanghong-egao-gdeg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '4f2290dd81773eaada0a3a0cc8adf115.mp4', 'https://media.liche.cn/meijiaka-zy/materials/4f2290dd81773eaada0a3a0cc8adf115.mp4', 5.04, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gdeg' AND level = 3;
|
||||
-- 来源: 工地恶搞-恶搞开篇 | 时长: 5.04s | 分类: wanghong-egao-gdeg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '8021088c304e09ac93929660530d68ab.mp4', 'https://media.liche.cn/meijiaka-zy/materials/8021088c304e09ac93929660530d68ab.mp4', 8.01, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gdeg' AND level = 3;
|
||||
-- 来源: 工地恶搞-恶搞开篇 | 时长: 8.01s | 分类: wanghong-egao-gdeg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'b25deff3d658d6b5e1f82715d5b32e6c.mp4', 'https://media.liche.cn/meijiaka-zy/materials/b25deff3d658d6b5e1f82715d5b32e6c.mp4', 8.01, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gdeg' AND level = 3;
|
||||
-- 来源: 工地恶搞-恶搞开篇 | 时长: 8.01s | 分类: wanghong-egao-gdeg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '93e95bedaf905e63613d5971ecbde77d.mp4', 'https://media.liche.cn/meijiaka-zy/materials/93e95bedaf905e63613d5971ecbde77d.mp4', 5.02, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gdeg' AND level = 3;
|
||||
-- 来源: 工地恶搞-恶搞开篇 | 时长: 5.02s | 分类: wanghong-egao-gdeg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '17705678ad0757af9e70fd1ca4579882.mp4', 'https://media.liche.cn/meijiaka-zy/materials/17705678ad0757af9e70fd1ca4579882.mp4', 8.01, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gdeg' AND level = 3;
|
||||
-- 来源: 工地恶搞-恶搞开篇 | 时长: 8.01s | 分类: wanghong-egao-gdeg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '6ea04c0905384386643a43ad3d8c62e8.mp4', 'https://media.liche.cn/meijiaka-zy/materials/6ea04c0905384386643a43ad3d8c62e8.mp4', 4.02, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gxtlsg' AND level = 3;
|
||||
-- 来源: 搞笑涂料施工-恶搞开篇 | 时长: 4.02s | 分类: wanghong-egao-gxtlsg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'c1c71478b19779df6d6231c76147c00e.mp4', 'https://media.liche.cn/meijiaka-zy/materials/c1c71478b19779df6d6231c76147c00e.mp4', 4.02, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gxtlsg' AND level = 3;
|
||||
-- 来源: 搞笑涂料施工-恶搞开篇 | 时长: 4.02s | 分类: wanghong-egao-gxtlsg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'fd03a112a4b9e7edc4534648d17b5cff.mp4', 'https://media.liche.cn/meijiaka-zy/materials/fd03a112a4b9e7edc4534648d17b5cff.mp4', 4.02, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gxtlsg' AND level = 3;
|
||||
-- 来源: 搞笑涂料施工-恶搞开篇 | 时长: 4.02s | 分类: wanghong-egao-gxtlsg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '70ea7edb5173568fa8079da9fe7da0bf.mp4', 'https://media.liche.cn/meijiaka-zy/materials/70ea7edb5173568fa8079da9fe7da0bf.mp4', 7.34, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gxtlsg' AND level = 3;
|
||||
-- 来源: 搞笑涂料施工-恶搞开篇 | 时长: 7.34s | 分类: wanghong-egao-gxtlsg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '688a3f761f110c7ce320a7a124baf191.mp4', 'https://media.liche.cn/meijiaka-zy/materials/688a3f761f110c7ce320a7a124baf191.mp4', 5.04, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gxtlsg' AND level = 3;
|
||||
-- 来源: 搞笑涂料施工-恶搞开篇 | 时长: 5.04s | 分类: wanghong-egao-gxtlsg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '0750b373b8d293020e593c0fb6ca973b.mp4', 'https://media.liche.cn/meijiaka-zy/materials/0750b373b8d293020e593c0fb6ca973b.mp4', 4.11, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gxtlsg' AND level = 3;
|
||||
-- 来源: 搞笑涂料施工-恶搞开篇 | 时长: 4.11s | 分类: wanghong-egao-gxtlsg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '33a38a924ca3ee44ae651c452b742799.mp4', 'https://media.liche.cn/meijiaka-zy/materials/33a38a924ca3ee44ae651c452b742799.mp4', 5.02, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-gxtlsg' AND level = 3;
|
||||
-- 来源: 搞笑涂料施工-恶搞开篇 | 时长: 5.02s | 分类: wanghong-egao-gxtlsg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '2eaf1185874d48136e3fbc62e908d455.mp4', 'https://media.liche.cn/meijiaka-zy/materials/2eaf1185874d48136e3fbc62e908d455.mp4', 4.25, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-blcc' AND level = 3;
|
||||
-- 来源: 暴力拆除-恶搞开篇 | 时长: 4.25s | 分类: wanghong-egao-blcc
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'd9fe52d52a13c5fcd15736f342f082fe.mp4', 'https://media.liche.cn/meijiaka-zy/materials/d9fe52d52a13c5fcd15736f342f082fe.mp4', 7.62, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-blcc' AND level = 3;
|
||||
-- 来源: 暴力拆除-恶搞开篇 | 时长: 7.62s | 分类: wanghong-egao-blcc
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'c252875cd6948d0f38062cb07538194d.mp4', 'https://media.liche.cn/meijiaka-zy/materials/c252875cd6948d0f38062cb07538194d.mp4', 6.78, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-blcc' AND level = 3;
|
||||
-- 来源: 暴力拆除-恶搞开篇 | 时长: 6.78s | 分类: wanghong-egao-blcc
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'dd1cee83a3366ff11bd00df286193d0b.mp4', 'https://media.liche.cn/meijiaka-zy/materials/dd1cee83a3366ff11bd00df286193d0b.mp4', 6.34, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-blcc' AND level = 3;
|
||||
-- 来源: 暴力拆除-恶搞开篇 | 时长: 6.34s | 分类: wanghong-egao-blcc
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'e36d1bceeebaadf20ccc5f8dfeb1ab97.mp4', 'https://media.liche.cn/meijiaka-zy/materials/e36d1bceeebaadf20ccc5f8dfeb1ab97.mp4', 3.02, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xj' AND level = 3;
|
||||
-- 来源: 炫技-恶搞开篇 | 时长: 3.02s | 分类: wanghong-egao-xj
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'a19a83b9a3b5f32daf154a46b457bb69.mp4', 'https://media.liche.cn/meijiaka-zy/materials/a19a83b9a3b5f32daf154a46b457bb69.mp4', 3.55, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xj' AND level = 3;
|
||||
-- 来源: 炫技-恶搞开篇 | 时长: 3.55s | 分类: wanghong-egao-xj
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '92baf7b9594e89c5f366fb77168a4879.mp4', 'https://media.liche.cn/meijiaka-zy/materials/92baf7b9594e89c5f366fb77168a4879.mp4', 4.02, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xj' AND level = 3;
|
||||
-- 来源: 炫技-恶搞开篇 | 时长: 4.02s | 分类: wanghong-egao-xj
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, 'a2c58cb2c6a1f2c1dec111f2fcefecc8.mp4', 'https://media.liche.cn/meijiaka-zy/materials/a2c58cb2c6a1f2c1dec111f2fcefecc8.mp4', 5.04, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-xj' AND level = 3;
|
||||
-- 来源: 炫技-恶搞开篇 | 时长: 5.04s | 分类: wanghong-egao-xj
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '62d4bc30cccf74a3300f40c3952470d3.mp4', 'https://media.liche.cn/meijiaka-zy/materials/62d4bc30cccf74a3300f40c3952470d3.mp4', 8.01, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-tzeg' AND level = 3;
|
||||
-- 来源: 贴砖恶搞-恶搞开篇 | 时长: 8.01s | 分类: wanghong-egao-tzeg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '9a134ff2649212d5f33069c850df385f.mp4', 'https://media.liche.cn/meijiaka-zy/materials/9a134ff2649212d5f33069c850df385f.mp4', 9.01, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-tzeg' AND level = 3;
|
||||
-- 来源: 贴砖恶搞-恶搞开篇 | 时长: 9.01s | 分类: wanghong-egao-tzeg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '00d6b249ce62c2553a23e3d93e460d91.mp4', 'https://media.liche.cn/meijiaka-zy/materials/00d6b249ce62c2553a23e3d93e460d91.mp4', 8.03, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-egao-tzeg' AND level = 3;
|
||||
-- 来源: 贴砖恶搞-恶搞开篇 | 时长: 8.03s | 分类: wanghong-egao-tzeg
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '73e70b1aacab4e4ddaa06f361ff1c07e.mp4', 'https://media.liche.cn/meijiaka-zy/materials/73e70b1aacab4e4ddaa06f361ff1c07e.mp4', 8.01, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-fanche-fsfcls' AND level = 3;
|
||||
-- 来源: 防水翻车漏水-施工翻车镜 | 时长: 8.01s | 分类: wanghong-fanche-fsfcls
|
||||
|
||||
INSERT INTO mjk_broll_materials (category_id, title, url, duration, usage_count, status, created_at, updated_at)
|
||||
SELECT id, '6d770fb02e2bbb6000b8123fe5a9fb55.mp4', 'https://media.liche.cn/meijiaka-zy/materials/6d770fb02e2bbb6000b8123fe5a9fb55.mp4', 7.5, 0, 'active', NOW(), NOW()
|
||||
FROM mjk_broll_categories WHERE slug = 'wanghong-fanche-fsfcls' AND level = 3;
|
||||
-- 来源: 防水翻车漏水-施工翻车镜 | 时长: 7.5s | 分类: wanghong-fanche-fsfcls
|
||||
|
||||
COMMIT;
|
||||
@@ -0,0 +1,330 @@
|
||||
[
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(19).mp4",
|
||||
"parent_folder": "吸睛画面-恶搞开篇",
|
||||
"original_name": "5月16日(19).mp4",
|
||||
"new_filename": "b3aff6db0536a8d7f51277bd17a449b3.mp4",
|
||||
"slug": "wanghong-egao-xjhm",
|
||||
"duration": 4.02
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(23).mp4",
|
||||
"parent_folder": "吸睛画面-恶搞开篇",
|
||||
"original_name": "5月16日(23).mp4",
|
||||
"new_filename": "845c6856746752c319239869d03d2def.mp4",
|
||||
"slug": "wanghong-egao-xjhm",
|
||||
"duration": 4.5
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(24).mp4",
|
||||
"parent_folder": "吸睛画面-恶搞开篇",
|
||||
"original_name": "5月16日(24).mp4",
|
||||
"new_filename": "4819ccec34b556b6a686503c8496d2d2.mp4",
|
||||
"slug": "wanghong-egao-xjhm",
|
||||
"duration": 9.17
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(26).mp4",
|
||||
"parent_folder": "吸睛画面-恶搞开篇",
|
||||
"original_name": "5月16日(26).mp4",
|
||||
"new_filename": "2073d7ca41856cc162ac3a86881eeee8.mp4",
|
||||
"slug": "wanghong-egao-xjhm",
|
||||
"duration": 6.32
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(27).mp4",
|
||||
"parent_folder": "吸睛画面-恶搞开篇",
|
||||
"original_name": "5月16日(27).mp4",
|
||||
"new_filename": "0097dceb9c7218d66f4b31d9ad47aee3.mp4",
|
||||
"slug": "wanghong-egao-xjhm",
|
||||
"duration": 5.43
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(33).mp4",
|
||||
"parent_folder": "吸睛画面-恶搞开篇",
|
||||
"original_name": "5月16日(33).mp4",
|
||||
"new_filename": "811ad18d3f8e5cf3792460e4aabf1744.mp4",
|
||||
"slug": "wanghong-egao-xjhm",
|
||||
"duration": 5.2
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(36).mp4",
|
||||
"parent_folder": "吸睛画面-恶搞开篇",
|
||||
"original_name": "5月16日(36).mp4",
|
||||
"new_filename": "7f1ec7aeab78ee64171fa6685c4439fc.mp4",
|
||||
"slug": "wanghong-egao-xjhm",
|
||||
"duration": 8.01
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(37).mp4",
|
||||
"parent_folder": "吸睛画面-恶搞开篇",
|
||||
"original_name": "5月16日(37).mp4",
|
||||
"new_filename": "df3223bb4de53e197ddd944ed5d2e5d5.mp4",
|
||||
"slug": "wanghong-egao-xjhm",
|
||||
"duration": 8.8
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(38).mp4",
|
||||
"parent_folder": "吸睛画面-恶搞开篇",
|
||||
"original_name": "5月16日(38).mp4",
|
||||
"new_filename": "a2c9adea107f99cdc5f6fb6b02236579.mp4",
|
||||
"slug": "wanghong-egao-xjhm",
|
||||
"duration": 7.11
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(39).mp4",
|
||||
"parent_folder": "吸睛画面-恶搞开篇",
|
||||
"original_name": "5月16日(39).mp4",
|
||||
"new_filename": "c77b5e546cb0393a5e7c3c4cea3bebb2.mp4",
|
||||
"slug": "wanghong-egao-xjhm",
|
||||
"duration": 6.62
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(4).mp4",
|
||||
"parent_folder": "吸睛画面-恶搞开篇",
|
||||
"original_name": "5月16日(4).mp4",
|
||||
"new_filename": "a29f7c2ffa5a39326d6aed18f0c6df8d.mp4",
|
||||
"slug": "wanghong-egao-xjhm",
|
||||
"duration": 5.04
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(8).mp4",
|
||||
"parent_folder": "吸睛画面-恶搞开篇",
|
||||
"original_name": "5月16日(8).mp4",
|
||||
"new_filename": "e7cc059acaca9d9286c547c1f9f3c39f.mp4",
|
||||
"slug": "wanghong-egao-xjhm",
|
||||
"duration": 5.02
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(1).mp4",
|
||||
"parent_folder": "工地恶搞-恶搞开篇",
|
||||
"original_name": "5月16日(1).mp4",
|
||||
"new_filename": "8c5bbf96530c1a03b9f084d13e06c7c9.mp4",
|
||||
"slug": "wanghong-egao-gdeg",
|
||||
"duration": 7.34
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(12).mp4",
|
||||
"parent_folder": "工地恶搞-恶搞开篇",
|
||||
"original_name": "5月16日(12).mp4",
|
||||
"new_filename": "24c662049e2db23c8ad8e39b188d769c.mp4",
|
||||
"slug": "wanghong-egao-gdeg",
|
||||
"duration": 5.02
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(14).mp4",
|
||||
"parent_folder": "工地恶搞-恶搞开篇",
|
||||
"original_name": "5月16日(14).mp4",
|
||||
"new_filename": "6f9c760668d743102ae4e6e0943a658f.mp4",
|
||||
"slug": "wanghong-egao-gdeg",
|
||||
"duration": 4.25
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(25).mp4",
|
||||
"parent_folder": "工地恶搞-恶搞开篇",
|
||||
"original_name": "5月16日(25).mp4",
|
||||
"new_filename": "44622ad5abe2e66279550bc7f95dcc6b.mp4",
|
||||
"slug": "wanghong-egao-gdeg",
|
||||
"duration": 6.08
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(3).mp4",
|
||||
"parent_folder": "工地恶搞-恶搞开篇",
|
||||
"original_name": "5月16日(3).mp4",
|
||||
"new_filename": "4f2290dd81773eaada0a3a0cc8adf115.mp4",
|
||||
"slug": "wanghong-egao-gdeg",
|
||||
"duration": 5.04
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(34).mp4",
|
||||
"parent_folder": "工地恶搞-恶搞开篇",
|
||||
"original_name": "5月16日(34).mp4",
|
||||
"new_filename": "8021088c304e09ac93929660530d68ab.mp4",
|
||||
"slug": "wanghong-egao-gdeg",
|
||||
"duration": 8.01
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(35).mp4",
|
||||
"parent_folder": "工地恶搞-恶搞开篇",
|
||||
"original_name": "5月16日(35).mp4",
|
||||
"new_filename": "b25deff3d658d6b5e1f82715d5b32e6c.mp4",
|
||||
"slug": "wanghong-egao-gdeg",
|
||||
"duration": 8.01
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(7).mp4",
|
||||
"parent_folder": "工地恶搞-恶搞开篇",
|
||||
"original_name": "5月16日(7).mp4",
|
||||
"new_filename": "93e95bedaf905e63613d5971ecbde77d.mp4",
|
||||
"slug": "wanghong-egao-gdeg",
|
||||
"duration": 5.02
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日.mp4",
|
||||
"parent_folder": "工地恶搞-恶搞开篇",
|
||||
"original_name": "5月16日.mp4",
|
||||
"new_filename": "17705678ad0757af9e70fd1ca4579882.mp4",
|
||||
"slug": "wanghong-egao-gdeg",
|
||||
"duration": 8.01
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(10).mp4",
|
||||
"parent_folder": "搞笑涂料施工-恶搞开篇",
|
||||
"original_name": "5月16日(10).mp4",
|
||||
"new_filename": "6ea04c0905384386643a43ad3d8c62e8.mp4",
|
||||
"slug": "wanghong-egao-gxtlsg",
|
||||
"duration": 4.02
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(11).mp4",
|
||||
"parent_folder": "搞笑涂料施工-恶搞开篇",
|
||||
"original_name": "5月16日(11).mp4",
|
||||
"new_filename": "c1c71478b19779df6d6231c76147c00e.mp4",
|
||||
"slug": "wanghong-egao-gxtlsg",
|
||||
"duration": 4.02
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(20).mp4",
|
||||
"parent_folder": "搞笑涂料施工-恶搞开篇",
|
||||
"original_name": "5月16日(20).mp4",
|
||||
"new_filename": "fd03a112a4b9e7edc4534648d17b5cff.mp4",
|
||||
"slug": "wanghong-egao-gxtlsg",
|
||||
"duration": 4.02
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(28).mp4",
|
||||
"parent_folder": "搞笑涂料施工-恶搞开篇",
|
||||
"original_name": "5月16日(28).mp4",
|
||||
"new_filename": "70ea7edb5173568fa8079da9fe7da0bf.mp4",
|
||||
"slug": "wanghong-egao-gxtlsg",
|
||||
"duration": 7.34
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(5).mp4",
|
||||
"parent_folder": "搞笑涂料施工-恶搞开篇",
|
||||
"original_name": "5月16日(5).mp4",
|
||||
"new_filename": "688a3f761f110c7ce320a7a124baf191.mp4",
|
||||
"slug": "wanghong-egao-gxtlsg",
|
||||
"duration": 5.04
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(6).mp4",
|
||||
"parent_folder": "搞笑涂料施工-恶搞开篇",
|
||||
"original_name": "5月16日(6).mp4",
|
||||
"new_filename": "0750b373b8d293020e593c0fb6ca973b.mp4",
|
||||
"slug": "wanghong-egao-gxtlsg",
|
||||
"duration": 4.11
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(9).mp4",
|
||||
"parent_folder": "搞笑涂料施工-恶搞开篇",
|
||||
"original_name": "5月16日(9).mp4",
|
||||
"new_filename": "33a38a924ca3ee44ae651c452b742799.mp4",
|
||||
"slug": "wanghong-egao-gxtlsg",
|
||||
"duration": 5.02
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/5月16日(13).mp4",
|
||||
"parent_folder": "暴力拆除-恶搞开篇",
|
||||
"original_name": "5月16日(13).mp4",
|
||||
"new_filename": "2eaf1185874d48136e3fbc62e908d455.mp4",
|
||||
"slug": "wanghong-egao-blcc",
|
||||
"duration": 4.25
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/5月16日(30).mp4",
|
||||
"parent_folder": "暴力拆除-恶搞开篇",
|
||||
"original_name": "5月16日(30).mp4",
|
||||
"new_filename": "d9fe52d52a13c5fcd15736f342f082fe.mp4",
|
||||
"slug": "wanghong-egao-blcc",
|
||||
"duration": 7.62
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/5月16日(31).mp4",
|
||||
"parent_folder": "暴力拆除-恶搞开篇",
|
||||
"original_name": "5月16日(31).mp4",
|
||||
"new_filename": "c252875cd6948d0f38062cb07538194d.mp4",
|
||||
"slug": "wanghong-egao-blcc",
|
||||
"duration": 6.78
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/5月16日(42).mp4",
|
||||
"parent_folder": "暴力拆除-恶搞开篇",
|
||||
"original_name": "5月16日(42).mp4",
|
||||
"new_filename": "dd1cee83a3366ff11bd00df286193d0b.mp4",
|
||||
"slug": "wanghong-egao-blcc",
|
||||
"duration": 6.34
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/5月16日(15).mp4",
|
||||
"parent_folder": "炫技-恶搞开篇",
|
||||
"original_name": "5月16日(15).mp4",
|
||||
"new_filename": "e36d1bceeebaadf20ccc5f8dfeb1ab97.mp4",
|
||||
"slug": "wanghong-egao-xj",
|
||||
"duration": 3.02
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/5月16日(16).mp4",
|
||||
"parent_folder": "炫技-恶搞开篇",
|
||||
"original_name": "5月16日(16).mp4",
|
||||
"new_filename": "a19a83b9a3b5f32daf154a46b457bb69.mp4",
|
||||
"slug": "wanghong-egao-xj",
|
||||
"duration": 3.55
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/5月16日(17).mp4",
|
||||
"parent_folder": "炫技-恶搞开篇",
|
||||
"original_name": "5月16日(17).mp4",
|
||||
"new_filename": "92baf7b9594e89c5f366fb77168a4879.mp4",
|
||||
"slug": "wanghong-egao-xj",
|
||||
"duration": 4.02
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/5月16日(22).mp4",
|
||||
"parent_folder": "炫技-恶搞开篇",
|
||||
"original_name": "5月16日(22).mp4",
|
||||
"new_filename": "a2c58cb2c6a1f2c1dec111f2fcefecc8.mp4",
|
||||
"slug": "wanghong-egao-xj",
|
||||
"duration": 5.04
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/贴砖恶搞-恶搞开篇/5月16日(2).mp4",
|
||||
"parent_folder": "贴砖恶搞-恶搞开篇",
|
||||
"original_name": "5月16日(2).mp4",
|
||||
"new_filename": "62d4bc30cccf74a3300f40c3952470d3.mp4",
|
||||
"slug": "wanghong-egao-tzeg",
|
||||
"duration": 8.01
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/贴砖恶搞-恶搞开篇/5月16日(29).mp4",
|
||||
"parent_folder": "贴砖恶搞-恶搞开篇",
|
||||
"original_name": "5月16日(29).mp4",
|
||||
"new_filename": "9a134ff2649212d5f33069c850df385f.mp4",
|
||||
"slug": "wanghong-egao-tzeg",
|
||||
"duration": 9.01
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/贴砖恶搞-恶搞开篇/5月16日(32).mp4",
|
||||
"parent_folder": "贴砖恶搞-恶搞开篇",
|
||||
"original_name": "5月16日(32).mp4",
|
||||
"new_filename": "00d6b249ce62c2553a23e3d93e460d91.mp4",
|
||||
"slug": "wanghong-egao-tzeg",
|
||||
"duration": 8.03
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/施工翻车镜/防水翻车漏水-施工翻车镜/5月16日(40).mp4",
|
||||
"parent_folder": "防水翻车漏水-施工翻车镜",
|
||||
"original_name": "5月16日(40).mp4",
|
||||
"new_filename": "73e70b1aacab4e4ddaa06f361ff1c07e.mp4",
|
||||
"slug": "wanghong-fanche-fsfcls",
|
||||
"duration": 8.01
|
||||
},
|
||||
{
|
||||
"original_path": "/Users/0fun/Desktop/网红开篇/施工翻车镜/防水翻车漏水-施工翻车镜/5月16日(41).mp4",
|
||||
"parent_folder": "防水翻车漏水-施工翻车镜",
|
||||
"original_name": "5月16日(41).mp4",
|
||||
"new_filename": "6d770fb02e2bbb6000b8123fe5a9fb55.mp4",
|
||||
"slug": "wanghong-fanche-fsfcls",
|
||||
"duration": 7.5
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,248 @@
|
||||
[
|
||||
{
|
||||
"original": "5月16日(19).mp4",
|
||||
"new": "b3aff6db0536a8d7f51277bd17a449b3.mp4",
|
||||
"folder": "吸睛画面-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/b3aff6db0536a8d7f51277bd17a449b3.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(23).mp4",
|
||||
"new": "845c6856746752c319239869d03d2def.mp4",
|
||||
"folder": "吸睛画面-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/845c6856746752c319239869d03d2def.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(24).mp4",
|
||||
"new": "4819ccec34b556b6a686503c8496d2d2.mp4",
|
||||
"folder": "吸睛画面-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/4819ccec34b556b6a686503c8496d2d2.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(26).mp4",
|
||||
"new": "2073d7ca41856cc162ac3a86881eeee8.mp4",
|
||||
"folder": "吸睛画面-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/2073d7ca41856cc162ac3a86881eeee8.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(27).mp4",
|
||||
"new": "0097dceb9c7218d66f4b31d9ad47aee3.mp4",
|
||||
"folder": "吸睛画面-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/0097dceb9c7218d66f4b31d9ad47aee3.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(33).mp4",
|
||||
"new": "811ad18d3f8e5cf3792460e4aabf1744.mp4",
|
||||
"folder": "吸睛画面-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/811ad18d3f8e5cf3792460e4aabf1744.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(36).mp4",
|
||||
"new": "7f1ec7aeab78ee64171fa6685c4439fc.mp4",
|
||||
"folder": "吸睛画面-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/7f1ec7aeab78ee64171fa6685c4439fc.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(37).mp4",
|
||||
"new": "df3223bb4de53e197ddd944ed5d2e5d5.mp4",
|
||||
"folder": "吸睛画面-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/df3223bb4de53e197ddd944ed5d2e5d5.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(38).mp4",
|
||||
"new": "a2c9adea107f99cdc5f6fb6b02236579.mp4",
|
||||
"folder": "吸睛画面-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/a2c9adea107f99cdc5f6fb6b02236579.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(39).mp4",
|
||||
"new": "c77b5e546cb0393a5e7c3c4cea3bebb2.mp4",
|
||||
"folder": "吸睛画面-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/c77b5e546cb0393a5e7c3c4cea3bebb2.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(4).mp4",
|
||||
"new": "a29f7c2ffa5a39326d6aed18f0c6df8d.mp4",
|
||||
"folder": "吸睛画面-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/a29f7c2ffa5a39326d6aed18f0c6df8d.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(8).mp4",
|
||||
"new": "e7cc059acaca9d9286c547c1f9f3c39f.mp4",
|
||||
"folder": "吸睛画面-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/e7cc059acaca9d9286c547c1f9f3c39f.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(1).mp4",
|
||||
"new": "8c5bbf96530c1a03b9f084d13e06c7c9.mp4",
|
||||
"folder": "工地恶搞-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/8c5bbf96530c1a03b9f084d13e06c7c9.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(12).mp4",
|
||||
"new": "24c662049e2db23c8ad8e39b188d769c.mp4",
|
||||
"folder": "工地恶搞-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/24c662049e2db23c8ad8e39b188d769c.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(14).mp4",
|
||||
"new": "6f9c760668d743102ae4e6e0943a658f.mp4",
|
||||
"folder": "工地恶搞-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/6f9c760668d743102ae4e6e0943a658f.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(25).mp4",
|
||||
"new": "44622ad5abe2e66279550bc7f95dcc6b.mp4",
|
||||
"folder": "工地恶搞-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/44622ad5abe2e66279550bc7f95dcc6b.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(3).mp4",
|
||||
"new": "4f2290dd81773eaada0a3a0cc8adf115.mp4",
|
||||
"folder": "工地恶搞-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/4f2290dd81773eaada0a3a0cc8adf115.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(34).mp4",
|
||||
"new": "8021088c304e09ac93929660530d68ab.mp4",
|
||||
"folder": "工地恶搞-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/8021088c304e09ac93929660530d68ab.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(35).mp4",
|
||||
"new": "b25deff3d658d6b5e1f82715d5b32e6c.mp4",
|
||||
"folder": "工地恶搞-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/b25deff3d658d6b5e1f82715d5b32e6c.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(7).mp4",
|
||||
"new": "93e95bedaf905e63613d5971ecbde77d.mp4",
|
||||
"folder": "工地恶搞-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/93e95bedaf905e63613d5971ecbde77d.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日.mp4",
|
||||
"new": "17705678ad0757af9e70fd1ca4579882.mp4",
|
||||
"folder": "工地恶搞-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/17705678ad0757af9e70fd1ca4579882.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(10).mp4",
|
||||
"new": "6ea04c0905384386643a43ad3d8c62e8.mp4",
|
||||
"folder": "搞笑涂料施工-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/6ea04c0905384386643a43ad3d8c62e8.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(11).mp4",
|
||||
"new": "c1c71478b19779df6d6231c76147c00e.mp4",
|
||||
"folder": "搞笑涂料施工-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/c1c71478b19779df6d6231c76147c00e.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(20).mp4",
|
||||
"new": "fd03a112a4b9e7edc4534648d17b5cff.mp4",
|
||||
"folder": "搞笑涂料施工-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/fd03a112a4b9e7edc4534648d17b5cff.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(28).mp4",
|
||||
"new": "70ea7edb5173568fa8079da9fe7da0bf.mp4",
|
||||
"folder": "搞笑涂料施工-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/70ea7edb5173568fa8079da9fe7da0bf.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(5).mp4",
|
||||
"new": "688a3f761f110c7ce320a7a124baf191.mp4",
|
||||
"folder": "搞笑涂料施工-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/688a3f761f110c7ce320a7a124baf191.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(6).mp4",
|
||||
"new": "0750b373b8d293020e593c0fb6ca973b.mp4",
|
||||
"folder": "搞笑涂料施工-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/0750b373b8d293020e593c0fb6ca973b.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(9).mp4",
|
||||
"new": "33a38a924ca3ee44ae651c452b742799.mp4",
|
||||
"folder": "搞笑涂料施工-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/33a38a924ca3ee44ae651c452b742799.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(13).mp4",
|
||||
"new": "2eaf1185874d48136e3fbc62e908d455.mp4",
|
||||
"folder": "暴力拆除-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/2eaf1185874d48136e3fbc62e908d455.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(30).mp4",
|
||||
"new": "d9fe52d52a13c5fcd15736f342f082fe.mp4",
|
||||
"folder": "暴力拆除-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/d9fe52d52a13c5fcd15736f342f082fe.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(31).mp4",
|
||||
"new": "c252875cd6948d0f38062cb07538194d.mp4",
|
||||
"folder": "暴力拆除-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/c252875cd6948d0f38062cb07538194d.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(42).mp4",
|
||||
"new": "dd1cee83a3366ff11bd00df286193d0b.mp4",
|
||||
"folder": "暴力拆除-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/dd1cee83a3366ff11bd00df286193d0b.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(15).mp4",
|
||||
"new": "e36d1bceeebaadf20ccc5f8dfeb1ab97.mp4",
|
||||
"folder": "炫技-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/e36d1bceeebaadf20ccc5f8dfeb1ab97.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(16).mp4",
|
||||
"new": "a19a83b9a3b5f32daf154a46b457bb69.mp4",
|
||||
"folder": "炫技-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/a19a83b9a3b5f32daf154a46b457bb69.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(17).mp4",
|
||||
"new": "92baf7b9594e89c5f366fb77168a4879.mp4",
|
||||
"folder": "炫技-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/92baf7b9594e89c5f366fb77168a4879.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(22).mp4",
|
||||
"new": "a2c58cb2c6a1f2c1dec111f2fcefecc8.mp4",
|
||||
"folder": "炫技-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/a2c58cb2c6a1f2c1dec111f2fcefecc8.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(2).mp4",
|
||||
"new": "62d4bc30cccf74a3300f40c3952470d3.mp4",
|
||||
"folder": "贴砖恶搞-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/贴砖恶搞-恶搞开篇/62d4bc30cccf74a3300f40c3952470d3.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(29).mp4",
|
||||
"new": "9a134ff2649212d5f33069c850df385f.mp4",
|
||||
"folder": "贴砖恶搞-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/贴砖恶搞-恶搞开篇/9a134ff2649212d5f33069c850df385f.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(32).mp4",
|
||||
"new": "00d6b249ce62c2553a23e3d93e460d91.mp4",
|
||||
"folder": "贴砖恶搞-恶搞开篇",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/恶搞开篇/贴砖恶搞-恶搞开篇/00d6b249ce62c2553a23e3d93e460d91.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(40).mp4",
|
||||
"new": "73e70b1aacab4e4ddaa06f361ff1c07e.mp4",
|
||||
"folder": "防水翻车漏水-施工翻车镜",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/施工翻车镜/防水翻车漏水-施工翻车镜/73e70b1aacab4e4ddaa06f361ff1c07e.mp4"
|
||||
},
|
||||
{
|
||||
"original": "5月16日(41).mp4",
|
||||
"new": "6d770fb02e2bbb6000b8123fe5a9fb55.mp4",
|
||||
"folder": "防水翻车漏水-施工翻车镜",
|
||||
"path": "/Users/0fun/Desktop/网红开篇/施工翻车镜/防水翻车漏水-施工翻车镜/6d770fb02e2bbb6000b8123fe5a9fb55.mp4"
|
||||
}
|
||||
]
|
||||
Executable
+167
@@ -0,0 +1,167 @@
|
||||
#!/bin/bash
|
||||
# 网红开篇素材批量上传脚本
|
||||
|
||||
# 吸睛画面-恶搞开篇/5月16日(19).mp4 (4.02s)
|
||||
# qshell put meijiaka-zy materials/b3aff6db0536a8d7f51277bd17a449b3.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(19).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/b3aff6db0536a8d7f51277bd17a449b3.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(19).mp4'
|
||||
|
||||
# 吸睛画面-恶搞开篇/5月16日(23).mp4 (4.5s)
|
||||
# qshell put meijiaka-zy materials/845c6856746752c319239869d03d2def.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(23).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/845c6856746752c319239869d03d2def.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(23).mp4'
|
||||
|
||||
# 吸睛画面-恶搞开篇/5月16日(24).mp4 (9.17s)
|
||||
# qshell put meijiaka-zy materials/4819ccec34b556b6a686503c8496d2d2.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(24).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/4819ccec34b556b6a686503c8496d2d2.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(24).mp4'
|
||||
|
||||
# 吸睛画面-恶搞开篇/5月16日(26).mp4 (6.32s)
|
||||
# qshell put meijiaka-zy materials/2073d7ca41856cc162ac3a86881eeee8.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(26).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/2073d7ca41856cc162ac3a86881eeee8.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(26).mp4'
|
||||
|
||||
# 吸睛画面-恶搞开篇/5月16日(27).mp4 (5.43s)
|
||||
# qshell put meijiaka-zy materials/0097dceb9c7218d66f4b31d9ad47aee3.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(27).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/0097dceb9c7218d66f4b31d9ad47aee3.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(27).mp4'
|
||||
|
||||
# 吸睛画面-恶搞开篇/5月16日(33).mp4 (5.2s)
|
||||
# qshell put meijiaka-zy materials/811ad18d3f8e5cf3792460e4aabf1744.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(33).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/811ad18d3f8e5cf3792460e4aabf1744.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(33).mp4'
|
||||
|
||||
# 吸睛画面-恶搞开篇/5月16日(36).mp4 (8.01s)
|
||||
# qshell put meijiaka-zy materials/7f1ec7aeab78ee64171fa6685c4439fc.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(36).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/7f1ec7aeab78ee64171fa6685c4439fc.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(36).mp4'
|
||||
|
||||
# 吸睛画面-恶搞开篇/5月16日(37).mp4 (8.8s)
|
||||
# qshell put meijiaka-zy materials/df3223bb4de53e197ddd944ed5d2e5d5.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(37).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/df3223bb4de53e197ddd944ed5d2e5d5.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(37).mp4'
|
||||
|
||||
# 吸睛画面-恶搞开篇/5月16日(38).mp4 (7.11s)
|
||||
# qshell put meijiaka-zy materials/a2c9adea107f99cdc5f6fb6b02236579.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(38).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/a2c9adea107f99cdc5f6fb6b02236579.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(38).mp4'
|
||||
|
||||
# 吸睛画面-恶搞开篇/5月16日(39).mp4 (6.62s)
|
||||
# qshell put meijiaka-zy materials/c77b5e546cb0393a5e7c3c4cea3bebb2.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(39).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/c77b5e546cb0393a5e7c3c4cea3bebb2.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(39).mp4'
|
||||
|
||||
# 吸睛画面-恶搞开篇/5月16日(4).mp4 (5.04s)
|
||||
# qshell put meijiaka-zy materials/a29f7c2ffa5a39326d6aed18f0c6df8d.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(4).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/a29f7c2ffa5a39326d6aed18f0c6df8d.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(4).mp4'
|
||||
|
||||
# 吸睛画面-恶搞开篇/5月16日(8).mp4 (5.02s)
|
||||
# qshell put meijiaka-zy materials/e7cc059acaca9d9286c547c1f9f3c39f.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(8).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/e7cc059acaca9d9286c547c1f9f3c39f.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/吸睛画面-恶搞开篇/5月16日(8).mp4'
|
||||
|
||||
# 工地恶搞-恶搞开篇/5月16日(1).mp4 (7.34s)
|
||||
# qshell put meijiaka-zy materials/8c5bbf96530c1a03b9f084d13e06c7c9.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(1).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/8c5bbf96530c1a03b9f084d13e06c7c9.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(1).mp4'
|
||||
|
||||
# 工地恶搞-恶搞开篇/5月16日(12).mp4 (5.02s)
|
||||
# qshell put meijiaka-zy materials/24c662049e2db23c8ad8e39b188d769c.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(12).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/24c662049e2db23c8ad8e39b188d769c.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(12).mp4'
|
||||
|
||||
# 工地恶搞-恶搞开篇/5月16日(14).mp4 (4.25s)
|
||||
# qshell put meijiaka-zy materials/6f9c760668d743102ae4e6e0943a658f.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(14).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/6f9c760668d743102ae4e6e0943a658f.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(14).mp4'
|
||||
|
||||
# 工地恶搞-恶搞开篇/5月16日(25).mp4 (6.08s)
|
||||
# qshell put meijiaka-zy materials/44622ad5abe2e66279550bc7f95dcc6b.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(25).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/44622ad5abe2e66279550bc7f95dcc6b.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(25).mp4'
|
||||
|
||||
# 工地恶搞-恶搞开篇/5月16日(3).mp4 (5.04s)
|
||||
# qshell put meijiaka-zy materials/4f2290dd81773eaada0a3a0cc8adf115.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(3).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/4f2290dd81773eaada0a3a0cc8adf115.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(3).mp4'
|
||||
|
||||
# 工地恶搞-恶搞开篇/5月16日(34).mp4 (8.01s)
|
||||
# qshell put meijiaka-zy materials/8021088c304e09ac93929660530d68ab.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(34).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/8021088c304e09ac93929660530d68ab.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(34).mp4'
|
||||
|
||||
# 工地恶搞-恶搞开篇/5月16日(35).mp4 (8.01s)
|
||||
# qshell put meijiaka-zy materials/b25deff3d658d6b5e1f82715d5b32e6c.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(35).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/b25deff3d658d6b5e1f82715d5b32e6c.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(35).mp4'
|
||||
|
||||
# 工地恶搞-恶搞开篇/5月16日(7).mp4 (5.02s)
|
||||
# qshell put meijiaka-zy materials/93e95bedaf905e63613d5971ecbde77d.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(7).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/93e95bedaf905e63613d5971ecbde77d.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日(7).mp4'
|
||||
|
||||
# 工地恶搞-恶搞开篇/5月16日.mp4 (8.01s)
|
||||
# qshell put meijiaka-zy materials/17705678ad0757af9e70fd1ca4579882.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日.mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/17705678ad0757af9e70fd1ca4579882.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/工地恶搞-恶搞开篇/5月16日.mp4'
|
||||
|
||||
# 搞笑涂料施工-恶搞开篇/5月16日(10).mp4 (4.02s)
|
||||
# qshell put meijiaka-zy materials/6ea04c0905384386643a43ad3d8c62e8.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(10).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/6ea04c0905384386643a43ad3d8c62e8.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(10).mp4'
|
||||
|
||||
# 搞笑涂料施工-恶搞开篇/5月16日(11).mp4 (4.02s)
|
||||
# qshell put meijiaka-zy materials/c1c71478b19779df6d6231c76147c00e.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(11).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/c1c71478b19779df6d6231c76147c00e.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(11).mp4'
|
||||
|
||||
# 搞笑涂料施工-恶搞开篇/5月16日(20).mp4 (4.02s)
|
||||
# qshell put meijiaka-zy materials/fd03a112a4b9e7edc4534648d17b5cff.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(20).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/fd03a112a4b9e7edc4534648d17b5cff.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(20).mp4'
|
||||
|
||||
# 搞笑涂料施工-恶搞开篇/5月16日(28).mp4 (7.34s)
|
||||
# qshell put meijiaka-zy materials/70ea7edb5173568fa8079da9fe7da0bf.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(28).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/70ea7edb5173568fa8079da9fe7da0bf.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(28).mp4'
|
||||
|
||||
# 搞笑涂料施工-恶搞开篇/5月16日(5).mp4 (5.04s)
|
||||
# qshell put meijiaka-zy materials/688a3f761f110c7ce320a7a124baf191.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(5).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/688a3f761f110c7ce320a7a124baf191.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(5).mp4'
|
||||
|
||||
# 搞笑涂料施工-恶搞开篇/5月16日(6).mp4 (4.11s)
|
||||
# qshell put meijiaka-zy materials/0750b373b8d293020e593c0fb6ca973b.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(6).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/0750b373b8d293020e593c0fb6ca973b.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(6).mp4'
|
||||
|
||||
# 搞笑涂料施工-恶搞开篇/5月16日(9).mp4 (5.02s)
|
||||
# qshell put meijiaka-zy materials/33a38a924ca3ee44ae651c452b742799.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(9).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/33a38a924ca3ee44ae651c452b742799.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/搞笑涂料施工-恶搞开篇/5月16日(9).mp4'
|
||||
|
||||
# 暴力拆除-恶搞开篇/5月16日(13).mp4 (4.25s)
|
||||
# qshell put meijiaka-zy materials/2eaf1185874d48136e3fbc62e908d455.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/5月16日(13).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/2eaf1185874d48136e3fbc62e908d455.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/5月16日(13).mp4'
|
||||
|
||||
# 暴力拆除-恶搞开篇/5月16日(30).mp4 (7.62s)
|
||||
# qshell put meijiaka-zy materials/d9fe52d52a13c5fcd15736f342f082fe.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/5月16日(30).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/d9fe52d52a13c5fcd15736f342f082fe.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/5月16日(30).mp4'
|
||||
|
||||
# 暴力拆除-恶搞开篇/5月16日(31).mp4 (6.78s)
|
||||
# qshell put meijiaka-zy materials/c252875cd6948d0f38062cb07538194d.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/5月16日(31).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/c252875cd6948d0f38062cb07538194d.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/5月16日(31).mp4'
|
||||
|
||||
# 暴力拆除-恶搞开篇/5月16日(42).mp4 (6.34s)
|
||||
# qshell put meijiaka-zy materials/dd1cee83a3366ff11bd00df286193d0b.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/5月16日(42).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/dd1cee83a3366ff11bd00df286193d0b.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/暴力拆除-恶搞开篇/5月16日(42).mp4'
|
||||
|
||||
# 炫技-恶搞开篇/5月16日(15).mp4 (3.02s)
|
||||
# qshell put meijiaka-zy materials/e36d1bceeebaadf20ccc5f8dfeb1ab97.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/5月16日(15).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/e36d1bceeebaadf20ccc5f8dfeb1ab97.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/5月16日(15).mp4'
|
||||
|
||||
# 炫技-恶搞开篇/5月16日(16).mp4 (3.55s)
|
||||
# qshell put meijiaka-zy materials/a19a83b9a3b5f32daf154a46b457bb69.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/5月16日(16).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/a19a83b9a3b5f32daf154a46b457bb69.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/5月16日(16).mp4'
|
||||
|
||||
# 炫技-恶搞开篇/5月16日(17).mp4 (4.02s)
|
||||
# qshell put meijiaka-zy materials/92baf7b9594e89c5f366fb77168a4879.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/5月16日(17).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/92baf7b9594e89c5f366fb77168a4879.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/5月16日(17).mp4'
|
||||
|
||||
# 炫技-恶搞开篇/5月16日(22).mp4 (5.04s)
|
||||
# qshell put meijiaka-zy materials/a2c58cb2c6a1f2c1dec111f2fcefecc8.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/5月16日(22).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/a2c58cb2c6a1f2c1dec111f2fcefecc8.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/炫技-恶搞开篇/5月16日(22).mp4'
|
||||
|
||||
# 贴砖恶搞-恶搞开篇/5月16日(2).mp4 (8.01s)
|
||||
# qshell put meijiaka-zy materials/62d4bc30cccf74a3300f40c3952470d3.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/贴砖恶搞-恶搞开篇/5月16日(2).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/62d4bc30cccf74a3300f40c3952470d3.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/贴砖恶搞-恶搞开篇/5月16日(2).mp4'
|
||||
|
||||
# 贴砖恶搞-恶搞开篇/5月16日(29).mp4 (9.01s)
|
||||
# qshell put meijiaka-zy materials/9a134ff2649212d5f33069c850df385f.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/贴砖恶搞-恶搞开篇/5月16日(29).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/9a134ff2649212d5f33069c850df385f.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/贴砖恶搞-恶搞开篇/5月16日(29).mp4'
|
||||
|
||||
# 贴砖恶搞-恶搞开篇/5月16日(32).mp4 (8.03s)
|
||||
# qshell put meijiaka-zy materials/00d6b249ce62c2553a23e3d93e460d91.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/贴砖恶搞-恶搞开篇/5月16日(32).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/00d6b249ce62c2553a23e3d93e460d91.mp4 '/Users/0fun/Desktop/网红开篇/恶搞开篇/贴砖恶搞-恶搞开篇/5月16日(32).mp4'
|
||||
|
||||
# 防水翻车漏水-施工翻车镜/5月16日(40).mp4 (8.01s)
|
||||
# qshell put meijiaka-zy materials/73e70b1aacab4e4ddaa06f361ff1c07e.mp4 '/Users/0fun/Desktop/网红开篇/施工翻车镜/防水翻车漏水-施工翻车镜/5月16日(40).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/73e70b1aacab4e4ddaa06f361ff1c07e.mp4 '/Users/0fun/Desktop/网红开篇/施工翻车镜/防水翻车漏水-施工翻车镜/5月16日(40).mp4'
|
||||
|
||||
# 防水翻车漏水-施工翻车镜/5月16日(41).mp4 (7.5s)
|
||||
# qshell put meijiaka-zy materials/6d770fb02e2bbb6000b8123fe5a9fb55.mp4 '/Users/0fun/Desktop/网红开篇/施工翻车镜/防水翻车漏水-施工翻车镜/5月16日(41).mp4'
|
||||
# 或: qshell fput meijiaka-zy materials/6d770fb02e2bbb6000b8123fe5a9fb55.mp4 '/Users/0fun/Desktop/网红开篇/施工翻车镜/防水翻车漏水-施工翻车镜/5月16日(41).mp4'
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
# Windows 代码签名配置指南
|
||||
|
||||
> 本文档说明美家卡智影 Windows 版本的签名机制与配置方法。
|
||||
|
||||
---
|
||||
|
||||
## 一、当前状态
|
||||
|
||||
| 签名类型 | 状态 | 说明 |
|
||||
|----------|------|------|
|
||||
| Tauri Updater 自签名 | ✅ 已启用 | 使用 minisign 免费签名,确保自动更新包的完整性 |
|
||||
| Windows 安装包签名 (NSIS/MSI) | ⏳ 待配置 | 暂未购买商业代码签名证书,安装包运行时可能触发 SmartScreen |
|
||||
|
||||
---
|
||||
|
||||
## 二、Tauri Updater 自签名(已启用)
|
||||
|
||||
### 2.1 作用
|
||||
- 对自动更新包(`.nsis.zip` / `.msi.zip`)进行数字签名
|
||||
- 客户端下载更新后,通过 `tauri.conf.json` 中的公钥验证更新包未被篡改
|
||||
- **这是免费的,且与 Windows 操作系统信任无关**
|
||||
|
||||
### 2.2 密钥管理
|
||||
|
||||
**公钥**
|
||||
- 文件: `src-tauri/tauri.key.pub`
|
||||
- 已嵌入 `tauri.conf.json` → `plugins.updater.pubkey`
|
||||
- **已提交到 Git 仓库**(公钥可以公开)
|
||||
|
||||
**私钥**
|
||||
- 文件: `tauri.key`(**已删除,未提交到 Git**)
|
||||
- 必须保存在安全位置(如 GitLab CI/CD Variables、1Password、公司密码管理器)
|
||||
- **切勿泄露或提交到仓库**
|
||||
|
||||
### 2.3 GitLab CI 配置
|
||||
|
||||
在 GitLab 项目设置 → **CI/CD → Variables** 中添加:
|
||||
|
||||
| 变量名 | 类型 | 值 | 保护级别 |
|
||||
|--------|------|-----|----------|
|
||||
| `TAURI_SIGNING_PRIVATE_KEY` | Variable | `dW50cnVzdGVk...`(私钥 base64 字符串)| Masked + Protected |
|
||||
|
||||
> CI 构建时会自动读取该变量,对更新包进行签名。
|
||||
|
||||
### 2.4 私钥丢失后的恢复
|
||||
|
||||
若私钥丢失,必须重新生成密钥对:
|
||||
|
||||
```bash
|
||||
cd tauri-app
|
||||
npm run tauri signer generate -- --write-keys src-tauri/tauri.key
|
||||
```
|
||||
|
||||
然后:
|
||||
1. 将新生成的公钥(`tauri.key.pub` 内容)更新到 `tauri.conf.json`
|
||||
2. 将新生成的私钥保存到 GitLab CI/CD Variables
|
||||
3. **旧版本客户端将无法通过自动更新升级**(公钥不匹配),必须重新下载安装包
|
||||
|
||||
---
|
||||
|
||||
## 三、Windows 安装包签名(待购买证书后启用)
|
||||
|
||||
### 3.1 为什么要商业签名
|
||||
|
||||
没有签名的 `.exe` 安装包在 Windows 上运行时:
|
||||
- Microsoft Defender SmartScreen 会显示 **"此应用可能会威胁你的设备安全"**
|
||||
- 用户必须点击 **"仍要运行"** 才能继续安装
|
||||
- 影响品牌信任度和转化率
|
||||
|
||||
### 3.2 证书类型选择
|
||||
|
||||
| 类型 | 价格(参考) | SmartScreen 效果 | 推荐度 |
|
||||
|------|-------------|------------------|--------|
|
||||
| 标准代码签名证书 (OV) | ¥1,500-3,000/年 | 初次下载仍可能触发,随下载量积累信誉后消除 | ⭐⭐⭐ |
|
||||
| 扩展验证代码签名证书 (EV) | ¥3,000-6,000/年 | 立即消除 SmartScreen | ⭐⭐⭐⭐⭐ |
|
||||
| 自签名证书 | 免费 | 需用户手动信任根证书,不适合分发 | ❌ |
|
||||
|
||||
**推荐**: 预算充足时直接购买 **EV 代码签名证书**(如 DigiCert、Sectigo、GlobalSign)。
|
||||
|
||||
### 3.3 启用商业签名的步骤
|
||||
|
||||
#### 步骤 1: 购买并获取证书
|
||||
从正规 CA 购买 Windows 代码签名证书,获取 `.pfx` 或 `.p12` 文件。
|
||||
|
||||
#### 步骤 2: 配置 GitLab CI Variables
|
||||
|
||||
在 GitLab 项目设置 → **CI/CD → Variables** 中添加:
|
||||
|
||||
| 变量名 | 类型 | 值 | 说明 |
|
||||
|--------|------|-----|------|
|
||||
| `WINDOWS_CERTIFICATE` | Variable | 证书文件的 **base64 编码内容** | `certutil -encode certificate.pfx cert.b64` 生成 |
|
||||
| `WINDOWS_CERTIFICATE_PASSWORD` | Variable | 证书密码 | Masked |
|
||||
|
||||
> 注意:Tauri CLI 会自动读取这两个环境变量并对 NSIS/MSI 安装包进行签名。
|
||||
|
||||
#### 步骤 3: 验证签名
|
||||
|
||||
构建完成后,在 Windows 上右键安装包 → **属性 → 数字签名**,应能看到签名者信息。
|
||||
|
||||
---
|
||||
|
||||
## 四、常见问题
|
||||
|
||||
### Q1: 现在没有商业证书,用户能用吗?
|
||||
**可以。** 安装包功能完全正常,只是首次运行时会遇到 SmartScreen 提示。可在官网/下载页添加说明,指导用户点击"更多信息"→"仍要运行"。
|
||||
|
||||
### Q2: Updater 自签名和 Windows 商业签名有什么区别?
|
||||
| | Updater 自签名 | Windows 商业签名 |
|
||||
|--|----------------|------------------|
|
||||
| 成本 | 免费 | 付费 |
|
||||
| 作用 | 验证更新包完整性 | 验证软件发布者身份 |
|
||||
| 影响范围 | Tauri 自动更新流程 | Windows 系统级信任 / SmartScreen |
|
||||
| 是否必须 | 是(否则更新无法验证) | 否(但强烈推荐) |
|
||||
|
||||
### Q3: 可以先用自签名证书绕过 SmartScreen 吗?
|
||||
**不建议。** 自签名证书需要每个用户手动在系统信任存储中安装根证书,操作复杂且极不专业,仅适用于内部测试。
|
||||
|
||||
---
|
||||
|
||||
## 五、相关文件
|
||||
|
||||
- `src-tauri/tauri.conf.json` — updater 公钥配置
|
||||
- `src-tauri/tauri.key.pub` — minisign 公钥(已提交)
|
||||
- `.gitlab-ci.yml` — CI 构建流程与签名环境变量
|
||||
@@ -0,0 +1 @@
|
||||
dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEZCMUQyRjU1MzY3ODZDREIKUldUYmJIZzJWUzhkK3l4VTl0RGE3OFRhN2JXdjBjZnR5UC9aMmwxTUY5K2ZoeDVNOStjZlFwQWYK
|
||||
Reference in New Issue
Block a user