$npx -y skills add topo-ai/ai-video-skills --skill sound-fx-for-video用于视频制作中的音效方案:搜索下载免费音效、Web Audio API 合成音效、以及在 HyperFrames/Remotion/HTML5 视频中的音频集成。触发词包括:音效、SFX、配乐、BGM、whoosh、click、transition、impact、typing 等。
| 1 | # 视频音效制作 Skill |
| 2 | |
| 3 | 视频需要声音。这份 Skill 覆盖两条主路径: |
| 4 | 1. **搜索并下载** 免费音效素材 |
| 5 | 2. **合成生成** 自定义音效(Web Audio API,无需外部文件) |
| 6 | |
| 7 | 按需求选择路径,实际项目通常会混合使用。 |
| 8 | |
| 9 | --- |
| 10 | |
| 11 | ## 路径一:搜索并下载免费音效 |
| 12 | |
| 13 | ### 推荐来源 |
| 14 | |
| 15 | | Source | URL | License | API | Best For | |
| 16 | |--------|-----|---------|-----|----------| |
| 17 | | Freesound | freesound.org | CC licenses (check per-file) | REST API (key required) | Huge library, specific sounds | |
| 18 | | Mixkit | mixkit.co/free-sound-effects | Free, no attribution | No | Quick grabs, curated quality | |
| 19 | | Pixabay | pixabay.com/sound-effects | Free, no attribution | No | Clean UI, good variety | |
| 20 | | BBC SFX | bbcsfx.acropolis.org.uk | Free for personal/educational | No | Premium BBC quality | |
| 21 | | ZapSplat | zapsplat.com | Free with attribution | No | Game/comedy/cartoon sounds | |
| 22 | | SoundBible | soundbible.com | Mixed (check per-file) | No | Quick one-off downloads | |
| 23 | |
| 24 | ### 搜索策略 |
| 25 | |
| 26 | 1. **关键词要具体。** |
| 27 | 差:`click sound` |
| 28 | 好:`mouse click sharp UI feedback` |
| 29 | 差:`whoosh` |
| 30 | 好:`fast whoosh air sweep transition` |
| 31 | |
| 32 | 2. **组合关键词搜索:** |
| 33 | - Object + action: "glass shatter", "paper crumple" |
| 34 | - Mood + type: "cinematic impact bass", "playful pop notification" |
| 35 | - Context: "UI button click feedback", "slide transition whoosh" |
| 36 | |
| 37 | 3. **常见音效分类与搜索词:** |
| 38 | |
| 39 | | Category | Search Terms | |
| 40 | |----------|-------------| |
| 41 | | Transitions | whoosh, sweep, swoosh, riser, dive | |
| 42 | | UI feedback | click, tap, pop, blip, notification, ding | |
| 43 | | Impacts | boom, hit, slam, thud, punch, bass drop | |
| 44 | | Typing | keyboard, typing, keystroke, mechanical | |
| 45 | | Reveals | shimmer, sparkle, magic, chime, glow | |
| 46 | | Movement | slide, swoop, flutter, bounce, elastic | |
| 47 | | Atmosphere | ambient, drone, hum, tension, pulse | |
| 48 | |
| 49 | ### 程序化下载 |
| 50 | |
| 51 | **Freesound API** (best for automation): |
| 52 | |
| 53 | ```bash |
| 54 | # 1. Get API key from https://freesound.org/apiv2/apply/ |
| 55 | # 2. Search |
| 56 | curl "https://freesound.org/apiv2/search/text/?query=whoosh+transition&fields=id,name,previews,duration,license&token=YOUR_API_KEY" |
| 57 | |
| 58 | # 3. Download preview (mp3, no auth needed) |
| 59 | curl -o whoosh.mp3 "https://freesound.org/data/previews/ID_ID_preview.mp3" |
| 60 | |
| 61 | # 4. Download full quality (OAuth2 needed) |
| 62 | ``` |
| 63 | |
| 64 | **Simple curl download** (sources with direct links): |
| 65 | |
| 66 | ```bash |
| 67 | # Pixabay (find the download URL from browser network tab) |
| 68 | curl -L -o click.mp3 "https://cdn.pixabay.com/audio/..." |
| 69 | |
| 70 | # Mixkit |
| 71 | curl -L -o transition.wav "https://assets.mixkit.co/active_storage/sfx/..." |
| 72 | ``` |
| 73 | |
| 74 | **Python helper** (for batch downloads): |
| 75 | |
| 76 | ```python |
| 77 | import urllib.request |
| 78 | import json |
| 79 | |
| 80 | FREESOUND_TOKEN = "YOUR_TOKEN" |
| 81 | |
| 82 | def search_sfx(query, max_results=5): |
| 83 | url = f"https://freesound.org/apiv2/search/text/?query={query}&fields=id,name,previews,duration,license&token={FREESOUND_TOKEN}" |
| 84 | with urllib.request.urlopen(url) as r: |
| 85 | return json.loads(r.read())["results"][:max_results] |
| 86 | |
| 87 | def download_preview(sound_id, filename): |
| 88 | url = f"https://freesound.org/data/previews/{sound_id//1000}/{sound_id}_{sound_id}_preview.mp3" |
| 89 | urllib.request.urlretrieve(url, filename) |
| 90 | ``` |
| 91 | |
| 92 | ### 版权检查 |
| 93 | |
| 94 | 发布前必须检查授权协议: |
| 95 | - **CC0**: Use freely, no attribution |
| 96 | - **CC-BY**: Use with attribution (add to video description) |
| 97 | - **CC-BY-NC**: Non-commercial only — do NOT use for monetized videos |
| 98 | - **CC-BY-SA**: Derivatives must share same license |
| 99 | |
| 100 | --- |
| 101 | |
| 102 | ## 路径二:使用 Web Audio API 合成音效 |
| 103 | |
| 104 | 无需音频文件,直接在浏览器中实时合成,适合代码驱动视频流程(HyperFrames、Remotion、HTML5)。 |
| 105 | |
| 106 | ### 快速参考:常见视频音效模式 |
| 107 | |
| 108 | #### UI Click / Tap |
| 109 | ```javascript |
| 110 | function playClick(audioCtx) { |
| 111 | const osc = audioCtx.createOscillator(); |
| 112 | const gain = audioCtx.createGain(); |
| 113 | osc.connect(gain).connect(audioCtx.destination); |
| 114 | osc.frequency.setValueAtTime(1200, audioCtx.currentTime); |
| 115 | osc.frequency.exponentialRampToValueAtTime(600, audioCtx.currentTime + 0.05); |
| 116 | gain.gain.setValueAtTime(0.3, audioCtx.currentTime); |
| 117 | gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.08); |
| 118 | osc.start(); osc.stop(audioCtx.currentTime + 0.08); |
| 119 | } |
| 120 | ``` |
| 121 | |
| 122 | #### Notification Pop / Ding |
| 123 | ```javascript |
| 124 | function playPop(audioCtx) { |
| 125 | const osc = audioCtx.createOscillator(); |
| 126 | const gain = audioCtx.createGain(); |
| 127 | osc.type = 'sine'; |
| 128 | osc.connect(gain).connect(audioCtx.destination); |
| 129 | osc.frequency.setValueAtTime(880, audioCtx.currentTime); |
| 130 | osc.frequency.exponentialRampToValueAtTime(1760, audioCtx.currentTime + 0.05); |
| 131 | gain.gain.setValueAtTime(0.4, audioCtx.currentTime); |
| 132 | gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.2); |
| 133 | osc.start(); osc.stop(audioCtx.currentTime + 0.2); |
| 134 | } |
| 135 | ``` |
| 136 | |
| 137 | #### Whoosh / Transition Sweep |
| 138 | ```javascript |
| 139 | function playWhoosh(audioCtx) { |
| 140 | const bufferSize = audioCtx.sampleRate * 0.4; |
| 141 | const buffer = audioCtx.createBuffer(1, bufferSize, audioCtx.sampleRate); |
| 142 | const data = buffer.getChannelData(0); |
| 143 | for (let i = 0; i < bufferSize; i++) { |
| 144 | data[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / bufferSize, 2); |
| 145 | } |
| 146 | const source = audioCtx.createBufferSource(); |