install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data-ai/smart-short-video" ~/.claude/skills/diegosouzapw-awesome-omni-skill-smart-short-video && rm -rf "$T"
manifest:
skills/data-ai/smart-short-video/SKILL.mdsource content
Smart Short Video - 智能短影片生成器
混合 AI 圖片與原始影片片段,生成 TikTok/Reels/Shorts 短影片
使用者輸入
| 參數 | 說明 |
|---|---|
| 輸入影片路徑 |
| 輸出時長 (30/60/90/120 秒) |
| 圖庫圖片比例 (0/25/50/75%) |
| AI 生圖比例 (0/25/50/75%) |
| 原始影片比例 (自動計算 = 100% - 圖庫 - AI) |
| 轉錄方式 (local/openai/existing) |
| OpenAI API 金鑰 (用於 DALL-E 或 Whisper API) |
| GLM (智譜 AI) API 金鑰 (用於 glm-image 模型) |
| AI 生圖服務 (pollinations/glm/dalle) |
| Whisper 模型選擇 (large-v3-turbo/medium/small/base) |
🎙️ Whisper 本地模型選擇
模型比較
| 模型 | 大小 | 速度 | 準確度 | 推薦用途 |
|---|---|---|---|---|
| large-v3-turbo | ~3GB | ⚡ 快 | ⭐⭐⭐⭐⭐ | 推薦 最佳平衡 |
| large-v3 | ~3GB | 🐢 慢 | ⭐⭐⭐⭐⭐ | 最高準確度 |
| medium | ~1.5GB | ⚡ 快 | ⭐⭐⭐ | 一般用途 |
| small | ~500MB | ⚡⚡ 很快 | ⭐⭐ | 快速處理 |
| base | ~150MB | ⚡⚡⚡ 極快 | ⭐ | 草稿級 |
安裝 Whisper
# 安裝 OpenAI Whisper pip3 install openai-whisper # 驗證安裝 python3 -m whisper --help
使用方式
# 推薦:large-v3-turbo (速度與準確度最佳平衡) python3 -m whisper video.mp4 --model large-v3-turbo --output_format json --language Zh # 最高準確度:large-v3 python3 -m whisper video.mp4 --model large-v3 --output_format json --language Zh # 快速處理:medium python3 -m whisper video.mp4 --model medium --output_format json --language Zh
⚠️ 執行前必讀
在開始執行任何步驟之前,必須先使用
工具分三批詢問使用者以下參數:AskUserQuestion
📦 第一批詢問 (4個問題)
- target_duration - 目標時長 (30/60/90/120 秒)
- library_ratio - 圖庫圖片比例 (0/25/50/75%)
- ai_ratio - AI 生圖比例 (0/25/50/75%)
- ai_image_service - AI 生圖服務 (Pollinations/GLM/DALL-E)
📦 第二批詢問 (1個問題)
- api_key - API Key (根據 ai_image_service 選擇要求輸入)
- Pollinations.ai → 可跳過(免費)
- GLM → 必須輸入 GLM_API_KEY
- DALL-E → 必須輸入 OPENAI_API_KEY
📦 第三批詢問 (1個問題)
- transcription_method - 轉錄方式 (local/openai/existing)
重要: 不要跳過詢問直接執行步驟!依序執行三批詢問。
已修正問題
✅ 問題 1:AI 生圖沒有真正執行
已修正: 使用
assemble-scenes-with-ai.js,調用 Pollinations.ai 免費 API 真正生成 AI 圖片
✅ 問題 2:場景順序混亂
已修正: 使用 Fisher-Yates 隨機演算法,確保場景類型分布符合設定比例
執行步驟 (按順序執行)
# ═══════════════════════════════════════════════════════════ # 步驟 0: 創建專屬工作資料夾 # ═══════════════════════════════════════════════════════════ WORK_DIR="output/$(date +%Y%m%d-%H%M%S)" mkdir -p "$WORK_DIR"/{segments,transcripts,video-segments,ai-generated} echo "✅ 步驟 0 完成:創建專屬資料夾 $WORK_DIR" echo "🔄 執行步驟 1:影片切片..." # ═══════════════════════════════════════════════════════════ # 步驟 1: 影片切片 (每 3 秒一段) # ═══════════════════════════════════════════════════════════ cd "$WORK_DIR/segments" ffmpeg -i "{{video_source}}" -c copy -map 0 -f segment -segment_time 3 -reset_timestamps 1 "segment_%03d.mp4" echo "✅ 步驟 1 完成:影片切片" echo "🔄 執行步驟 2:Whisper 轉錄..." # ═══════════════════════════════════════════════════════════ # 步驟 2: Whisper 轉錄 (使用 Python 直接調用) # ═══════════════════════════════════════════════════════════ python3 -m whisper "{{video_source}}" --model large-v3-turbo --output_format json --output_dir "$WORK_DIR/transcripts" --task transcribe --language Zh echo "✅ 步驟 2 完成:Whisper 轉錄" echo "🔄 執行步驟 3:生成文字分組與關鍵字..." # ═══════════════════════════════════════════════════════════ # 步驟 3: 生成 grouped.json 和 keywords.json # ═══════════════════════════════════════════════════════════ # 從轉錄結果按 3 秒分組,生成對應的關鍵字 node -e " const fs = require('fs'); const path = require('path'); const transcriptPath = '$WORK_DIR/transcripts/*.json'; const transcriptFiles = require('fs').readdirSync('$WORK_DIR/transcripts').filter(f => f.endsWith('.json')); const transcript = JSON.parse(fs.readFileSync(path.join('$WORK_DIR/transcripts', transcriptFiles[0]), 'utf8')); const SEGMENT_DURATION = 3; const totalDuration = transcript.segments[transcript.segments.length - 1].end; const numSegments = Math.ceil(totalDuration / SEGMENT_DURATION); const groupedTexts = []; const keywordsList = []; for (let i = 0; i < numSegments; i++) { const startTime = i * SEGMENT_DURATION; const endTime = (i + 1) * SEGMENT_DURATION; const relevantSegments = transcript.segments.filter(s => s.start < endTime && s.end > startTime); const text = relevantSegments.map(s => s.text.trim()).filter(t => t).join(' '); groupedTexts.push(text); const keywords = text.replace(/[?!。,、;:「」『』\\s]/g, ' ').split(' ').filter(w => w.length >= 2).slice(0, 5); keywordsList.push(keywords); } fs.writeFileSync('$WORK_DIR/transcripts/grouped.json', JSON.stringify(groupedTexts, null, 2)); fs.writeFileSync('$WORK_DIR/transcripts/keywords.json', JSON.stringify(keywordsList, null, 2)); console.log('✓ 生成 grouped.json 和 keywords.json'); " echo "✅ 步驟 3 完成:文字分組與關鍵字" echo "🔄 執行步驟 4:片段重要性分析..." # ═══════════════════════════════════════════════════════════ # 步驟 4: 片段重要性分析與選擇 # ═══════════════════════════════════════════════════════════ WORK_DIR="$WORK_DIR" node scripts/analyze-segments.js echo "✅ 步驟 4 完成:片段重要性分析" echo "🔄 執行步驟 5:AI 文案重寫..." # ═══════════════════════════════════════════════════════════ # 步驟 5: AI 文案重寫 (使用 Claude) # ═══════════════════════════════════════════════════════════ # ⚠️ 重要:此步驟必須由 Claude (AI) 完成,不使用腳本 # # 執行方式: # 1. 讀取 $WORK_DIR/selected-segments.json # 2. 根據目標時長計算場景數量:target_duration / 3 # 3. 使用 Claude 重寫每個片段的文案: # - 每個場景 3 秒,文案必須在 12-15 字以內(正常語速 4-5字/秒) # - 簡潔有力,去除冗餘和重複內容 # - 保持核心信息 # - 適合短影片快節奏 # 4. 輸出格式到 $WORK_DIR/rewritten-text.json: # [{ index: 0, originalText: "...", rewrittenText: "...", keywords: [...] }] # echo "✅ 步驟 5 完成:AI 文案重寫" echo "🔄 執行步驟 6:影片片段重新編碼..." # ═══════════════════════════════════════════════════════════ # 步驟 6: 影片片段重新編碼 (瀏覽器相容格式) # ═══════════════════════════════════════════════════════════ node -e " const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); const workDir = '$WORK_DIR'; const selected = JSON.parse(fs.readFileSync(path.join(workDir, 'selected-segments.json'), 'utf8')); console.log('🎬 重新編碼選取的影片片段...'); selected.selectedSegments.forEach((seg, i) => { const src = path.join(workDir, \`segments/segment_\${String(seg.index).padStart(3, '0')}.mp4\`); const dst = path.join('public/video-segments', \`segment_\${String(i).padStart(3, '0')}.mp4\`); if (fs.existsSync(src)) { execSync(\`ffmpeg -y -i \"\${src}\" -c:v libx264 -profile:v baseline -level 3.0 -pix_fmt yuv420p -c:a aac -b:a 128k -movflags +faststart \"\${dst}\"\`, { stdio: 'inherit' }); console.log(\`✓ [\${i}] segment_\${String(seg.index).padStart(3, '0')} -> segment_\${String(i).padStart(3, '0')}\`); } }); " echo "✅ 步驟 6 完成:影片片段重新編碼" echo "🔄 執行步驟 7:場景組裝與 AI 生圖..." # ═══════════════════════════════════════════════════════════ # 步驟 7: 場景組裝 # ═══════════════════════════════════════════════════════════ # ⚠️ 場景數量 = target_duration / 3(例如 60秒 = 20個場景) # ⚠️ 不要固定 30 個場景! # # 根據用戶選擇的 AI 服務執行生圖: # - pollinations → 使用 Pollinations.ai 免費 API # - glm → 使用 GLM API (需要 GLM_API_KEY) # - dalle → 使用 DALL-E API (需要 OPENAI_API_KEY) echo "✅ 步驟 7 完成:場景組裝" echo "🔄 執行步驟 8:渲染最終影片..." # ═══════════════════════════════════════════════════════════ # 步驟 8: 複製場景配置並渲染 # ═══════════════════════════════════════════════════════════ cp "$WORK_DIR/scenes.json" output/scenes.json npx remotion render AIShortVideo "$WORK_DIR/final-output.mp4" --overwrite --timeout=120000 --concurrency=1 echo "✅ 步驟 8 完成:渲染最終影片" echo "🔄 執行步驟 9:UI/UX 視覺檢查..." # ═══════════════════════════════════════════════════════════ # 步驟 9: UI/UX 視覺檢查 # ═══════════════════════════════════════════════════════════ echo "" echo "🎨 執行 UI/UX 視覺檢查..." # 檢查場景配置的視覺多樣性和吸引力 node -e " const fs = require('fs'); const data = JSON.parse(fs.readFileSync('output/scenes.json', 'utf8')); const scenes = data.scenes; const videoCount = scenes.filter(s => s.useVideo).length; const imageCount = scenes.filter(s => !s.useVideo).length; const aiImageCount = scenes.filter(s => s.imageConfig?.primary?.url?.includes('/ai-generated/')).length; const libraryImageCount = imageCount - aiImageCount; console.log('\\n📊 場景分析:'); console.log(\` 🎬 影片場景: \${videoCount} (\${Math.round(videoCount/scenes.length*100)}%)\`); console.log(\` ✨ AI 圖片: \${aiImageCount} (\${Math.round(aiImageCount/scenes.length*100)}%)\`); console.log(\` 📚 圖庫圖片: \${libraryImageCount} (\${Math.round(libraryImageCount/scenes.length*100)}%)\`); // 分析視覺多樣性 const sceneTypes = scenes.map(s => s.useVideo ? 'video' : s.imageConfig?.primary?.url?.includes('/ai-generated/') ? 'ai' : 'library'); let transitions = 0; for (let i = 1; i < sceneTypes.length; i++) { if (sceneTypes[i] !== sceneTypes[i-1]) transitions++; } const diversityScore = Math.round((transitions / (scenes.length - 1)) * 100); console.log('\\n🎨 視覺多樣性:'); console.log(\` 場景切換次數: \${transitions}/\${scenes.length - 1}\`); console.log(\` 多樣性評分: \${diversityScore}%\`); if (diversityScore >= 60) { console.log(' ✅ 視覺節奏良好,場景變化豐富'); } else if (diversityScore >= 40) { console.log(' ⚠️ 視覺節奏一般,可增加場景變化'); } else { console.log(' ❌ 視覺節奏單調,建議增加場景類型變化'); } // 場景順序視覺化 console.log('\\n📲 場景順序:'); console.log(' ' + sceneTypes.map(t => t === 'video' ? '🎬' : t === 'ai' ? '✨' : '📚').join(' ')); " echo "" echo "✅ 步驟 9 完成:UI/UX 視覺檢查" echo "" echo "🎉 所有步驟完成!輸出影片: $WORK_DIR/final-output.mp4"
關鍵修正:場景順序使用隨機模式
✅ 隨機模式做法
// 建立類型池 const sceneTypes = []; for (let i = 0; i < videoScenes; i++) sceneTypes.push('video'); for (let i = 0; i < libraryScenes; i++) sceneTypes.push('library'); for (let i = 0; i < aiScenes; i++) sceneTypes.push('ai'); // Fisher-Yates 隨機打亂 for (let i = sceneTypes.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [sceneTypes[i], sceneTypes[j]] = [sceneTypes[j], sceneTypes[i]]; }
UI/UX 視覺多樣性檢查
渲染後會自動分析場景配置,評估視覺多樣性:
- 📊 場景類型統計
- 🎨 場景切換頻率
- ✅/⚠️/❌ 視覺節奏評分
AI 生圖必須真正執行
❌ 錯誤做法
function simulateAIImage(text, sceneIndex) { // 只是隨機選圖庫圖片! const allImages = Object.keys(irasutoyaDB.images); const randomImage = allImages[Math.floor(Math.random() * allImages.length)]; return `/ai-images/${randomImage}`; }
✅ 正確做法
async function generateAIImage(text, sceneIndex) { // 檢查是否有 API Key if (process.env.OPENAI_API_KEY) { // 真正調用 DALL-E API const prompt = createImagePrompt(text); const imageUrl = await generateWithDalle(prompt, sceneIndex); if (imageUrl) return imageUrl; } // 才使用 fallback return getRandomLibraryImage(text); }
場景組裝腳本:assemble-scenes-with-ai.js
這個腳本:
- AI 生圖真正執行 - 使用 Pollinations.ai 免費 API 生成圖片
- 隨機場景順序 - Fisher-Yates 洗牌演算法
- 內容匹配圖片 - 根據文案生成對應的 AI 圖片
GLM (智譜 AI) 配置
✅ 正確模型名稱
使用
glm-image 模型進行 AI 圖像生成。
API 請求格式
{ "model": "glm-image", "prompt": "futuristic, cyberpunk, digital art, neon, high quality", "size": "1024x1024" }
API 端點
POST https://open.bigmodel.cn/api/paas/v4/images/generations Authorization: Bearer YOUR_GLM_API_KEY
場景數據結構
圖片場景 (AI 生圖)
{ "id": "scene-0", "index": 0, "startTime": 0, "endTime": 3, "duration": 3, "transcription": "2026年最強個人AI員工來了!", "keywords": ["AI", "員工", "2026"], "style": "tech", "useVideo": false, "videoSegmentPath": null, "imageConfig": { "primary": { "url": "/ai-generated/ai_0.png" } } }
圖片場景 (圖庫圖片)
{ "id": "scene-1", "index": 1, "startTime": 3, "endTime": 6, "duration": 3, "transcription": "Cloudbot徹底改變我的工作方式", "keywords": ["Cloudbot", "工作"], "style": "tech", "useVideo": false, "videoSegmentPath": null, "imageConfig": { "primary": { "url": "/ai-images/VR_1.png" } } }
影片場景
{ "id": "scene-1", "index": 1, "startTime": 3, "endTime": 6, "duration": 3, "transcription": "現代最強咒術師,迎來最強大的外星敵人", "keywords": ["咒術", "最強"], "style": "tech", "useVideo": true, "videoSegmentPath": "video-segments/segment_000.mp4", "imageConfig": { "primary": { "url": null } } }
關鍵檔案位置
| 用途 | 路徑 |
|---|---|
| 輸入影片 | 使用者指定路徑 |
| 專屬資料夾 | (如 ) |
| 影片片段 | |
| 轉錄結果 | |
| 選取片段 | |
| 重寫文案 | |
| 場景數據 | |
| 瀏覽器影片 | (共用) |
| 圖片資源 | (共用) |
| AI 生圖 | |
| 最終輸出 | |