涂鸦音乐短片
格式:一张网格纸和一条黑线扫过画面。有人画了一条波浪,线条便演奏出来。他们添上一座小山,第二件乐器便加入。一根茎生长,你能听到它向上攀升。到最后,一幅完整的画和一首完整的歌同时诞生,两者源自同一笔触。无人言语,也无文字可读。参考短片获得了1250万播放量。
为何有效:两个问题同时悬在观众心头——“它会长成什么?”和“它会听起来像什么?”。每一笔都同时回答了两个问题的一部分,所以无人会划走,直到画面完成,而最后10秒便是高潮。
template/ 文件夹包含了引擎和5个完成画作。复制它,编写一个新画作,运行一条命令。
格式运作方式
逐帧测量自参考短片。引擎遵循以下数字。
| 部分 | 行为 |
|---|---|
| 播放头 | 从左向右扫动,然后跳回。一次扫动为2小节:BPM 100下持续4.8秒 |
| 线条高度 | 音高。底部到顶部跨3个八度,采用五声音阶,共15个音符 |
| 吸附 | 线条吸附到最近的音符,并在约60毫秒内滑至该位置,无新的起奏 |
| 每次交叉 | 一个声部,带一个黑色圆点。被播放头穿过的圆圈同时发出两个音符 |
| 笔触何时开始发声 | 仅当笔尖已超过播放头位置。单独作画不产生声音 |
| 颜色 | 每种颜色代表一种乐器。均为柔和音色,接近纯正弦波 |
| 音量 | 声部叠加时保持平稳,约-16 dB |
| 顺序 | 先横跨页面的波浪,再是主体形状,然后是细节;图层之间留1-2次扫动用于聆听,末尾约留2次扫动无新内容 |
步骤
- 获取主题。 如果用户没有指定要画什么,从
drawings.md中提供3个选项,从会生长的东西开始。角落里的手柄是可选的,大多数短片没有,所以仅在用户要求时才添加。 - 复制模板:
cp -r ~/.claude/skills/doodle-music-reel/template ~/doodle-reel && cd ~/doodle-reel && npm i puppeteer - 编写画作 到
drawings/<name>.js。先阅读drawings/sunflower.js,它是范例。规则如下。 - 读取歌曲:
node make.cjs drawings/<name>.js --check。你无法听到它,所以这个音符表是读取它的方式。修复任何警告。请参阅“读取音符表”。 - 查看它:
node make.cjs drawings/<name>.js --stills 4,12,20,30,40将图片写入out/<name>-stills/。选取视频长度(见音符表第一行)中不同时间点,最后一个时间点应在最后一笔之后。打开每一张。检查画作是否能被认作它本该是的东西,没有任何内容跑出页面,笔触没有意外碰撞。 - 渲染:
node make.cjs drawings/<name>.js写入out/<name>.mp4(约1分钟)。 - 生成最终接触印相并检查后再交给用户:
ffmpeg -i out/<name>.mp4 -vf "fps=1/3,scale=216:-1,tile=7x2" -frames:v 1 out/sheet.jpg - 告诉用户打开声音收听。 你能阅读音符但无法听到混音,所以用户的耳朵拥有最终发言权。
编写画作
DRAW((E) => ({
name: 'snail', // 输出文件名
key: 'D', // 任意调:C, C#, D, Eb, E, F, F#, G, Ab, A, Bb, B
scale: 'pentatonic', // pentatonic(明亮), minor(忧郁), major(7个音符,可能冲突)
bpm: 100, // 一次扫动为8拍
hold: 2, // 末尾无新内容的扫动次数
// handle: '@yourapp',
steps: [
E.stroke('blue', E.wave(0, 1000, 1012, 34, 4), { speed: 430 }),
E.wait(1.2), // 秒,或 E.wait('wrap') 等待下一次扫动
E.stroke('green', [[500, 1000], [490, 800], [510, 600]], { speed: 200, width: 12 }),
],
}))
页面为 宽1000、高1320,y=0 在顶部。x 表示音符播放的时间,y 表示哪个音符。
点与形状。 给一个笔触4-8个点,它就会呈现为平滑的手绘曲线。
E.wave(x0, x1, y, amp, bumps, seed)一条横跨的波浪线E.circle(cx, cy, r, startDeg, seed)和E.oval(cx, cy, rx, ry, startDeg, seed)手绘,结尾会超过起点。startDeg是笔尖落下的角度:-90为顶部,0为右侧。默认值为-100E.leaf(x0, y0, x1, y1, fat)从基部到尖端再返回的环E.line(x0, y0, x1, y1)和E.arc(cx, cy, r, deg0, deg1)E.path(svgPathString, { fit: [x0, y0, x1, y1] })任意SVG轮廓,使用{ sharp: true }绘制- 其他情况为自己编写的点列表。对于云朵,复制
sunflower.js中的10个点并移动它们
笔触选项。 speed 单位为像素/秒(默认520)。gap 为之后的停顿时间(默认0.22)。width 单位像素(默认10)。sharp: true 保留尖角。closed: true 将结尾与起点连接。wobble 为手抖程度(默认2.2,0为笔直)。
颜色(每种颜色代表一种乐器)。 ink, red, orange, yellow, leaf, green, sky, blue, purple, pink, brown。
五声音阶中的高度。 以下为15个阶梯,步长88单位,对应D调。其他调会改变音名但保持高度。
| y | 音符 | y | 音符 | y | 音符 |
|---|---|---|---|---|---|
| 0 | D6 | 440 | D5 | 880 | D4 |
| 88 | B5 | 528 | B4 | 968 | B3 |
| 176 | A5 | 616 | A4 | 1056 | A3 |
| 264 | F#5 | 704 | F#4 | 1144 | F#3 |
| 352 | E5 | 792 | E4 | 1232 | E3 |
| 1320 | D3 |
两个音符之间的线是中间值:1012介于A3和B3之间,1100介于F#3和A3之间。major 音阶有21个阶梯而非15个,因此请从音符表中读取其高度。
让作品优秀的原则
第一笔要横跨整个页面,位于两个音符之间的线上。 E.wave(0, 1000, 1012, 34, 4) 在整个视频中在A3和B3之间波动。它是这首歌的地板。如果它停留在一个音符上就会变成持续低音,如果它中途停止歌曲就会出现空洞。
分层构建,从低到高。 地板,然后是页面中间的主体形状,最后是高处的细节。每一层使用一种新颜色。在一个图层之后等待1-2次扫动,让人们听到它所添加的内容。
画会缓慢生长的东西。 茎或树干的速度设为170-250,让人们看着它攀升。轮廓线速度400-500。短虚线速度250-350。
形状即声音。
- 一条长而平缓的线是一段持续旋律。
- 一条近乎垂直的线是一串快速的音符,即播放头碰到茎时的“呼啸声”。
- 一个圆圈是两个音符的开合。小圆圈是快速的两个音符击打,大圆圈是整个乐句。
- 一条短虚线是一个音符。位于节拍线上的虚线(每125个单位)会产生脉冲。页面底部是低音,顶部是高音。
保持同时发声的声部不超过10个。 检查时会打印声部数量,超过时还会指明是哪些笔触导致的。每当多个笔触位于同一x位置时,声部计数就会增加,因此堆叠形状在同一列或具有深度波动的轮廓(因为每个在x方向折返的波动都会增加声部)会导致计数增加。超过10个就会变得浑浊。将形状横向移动,使波动变浅,或截断某个笔触。
保持时长30-50秒。 低于30秒歌曲无法充分构建,超过50秒观众会在结束前离开。时长会自动计算:最后一笔结束后向上取整到该扫动结束,再加上 hold 次扫动。因此它会随画作变化而变化,并且总是在一次扫动完成时结束。
它必须看起来像儿童画。 简单、可识别、使用少数颜色。如果需要标签,那就画别的。
读取音符表
--check 会按笔触打印一行:颜色、绘制时间、跨越范围、产生声部数以及演奏的音符。注意检查:
- 第1笔 有2个或更多音符,且跨越 x 0-1000。
- 笔触分散 在低、中、高音符区域。如果所有内容都集中在一个八度,将一些形状向页面上下移动。
- 你意图作为旋律的形状有3个或更多音符。 只有一个音符的长线是持续低音。给它更多高度,或移动它使其跨越音符线。
- “扫动中的静默部分”为0 或接近0。
- 最后一笔结束 大约在视频结束前2次扫动时。
修复问题
- 画作看起来不对: 更改点并重新运行
--stills。只需几秒,所以可以多试几次。 - 某段听起来单薄: 添加一层虚线,或在页面底部添加一条新颜色的低音线。
- 缺少Puppeteer: 在包含
make.cjs的文件夹中运行npm i puppeteer。 - 缺少ffmpeg: 安装它(Mac上运行
brew install ffmpeg)。--check和--sound不需要它即可工作,视频渲染需要它。
保持原创
复制这个格式,制作你自己的画作。不要使用其他创作者的用户名、他们的画作或他们的应用界面,也不要在视频上放置它尚未获得的播放量计数。