낙서 음악 릴 (Doodle Music Reel)
형식: 격자 무늬 용지 위를 검은 선이 가로지릅니다. 누군가 파도를 그리고, 선이 그 파도를 연주합니다. 언덕을 하나 더 추가하면 두 번째 악기가 들어옵니다. 줄기가 자라나고, 그 소리가 올라가는 것을 듣게 됩니다. 마지막에는 완성된 그림과 완성된 노래가 있고, 둘 다 같은 획에서 비롯되었습니다. 아무도 말하지 않고 읽을 것도 없습니다. 참고 릴은 1250만 뷰를 기록했습니다.
효과가 좋은 이유: '이게 무엇이 될까?'와 '이게 어떤 소리가 날까?'라는 두 가지 질문이 동시에 제기됩니다. 새로운 획이 추가될 때마다 두 질문에 대한 답이 조금씩 드러나므로, 사람들은 그림이 완성될 때까지 화면을 넘기지 않으며, 마지막 10초가 가장 큰 만족감을 줍니다.
template/ 디렉토리에는 엔진과 5개의 완성된 그림이 있습니다. 이를 복사하여 새로운 그림을 작성하고, 하나의 명령어를 실행하면 됩니다.
형식 작동 방식
참고 릴에서 프레임 단위로 측정했습니다. 엔진은 다음 수치를 따릅니다.
| 부분 | 작동 방식 |
|---|---|
| 재생 막대(Playhead) | 왼쪽에서 오른쪽으로 휩쓸고, 다시 점프하여 돌아옵니다. 한 번 휩쓰는 것은 2마디: 100bpm에서 4.8초 |
| 선의 높이 | 음높이(Pitch). 아래에서 위로 3옥타브, 5음 음계(pentatonic scale), 15개 음 |
| 스냅(Snapping) | 선이 가장 가까운 음으로 스냅되며 약 60ms 내에 미끄러져 이동하고, 새로운 어택(attack)은 없음 |
| 각 교차점 | 하나의 성부(voice), 검은 점으로 표시됨. 재생 막대가 교차하는 원은 한 번에 2개의 음 |
| 획이 소리를 내기 시작하는 시점 | 펜이 재생 막대를 지난 후에만 가능. 그림만으로는 소리가 나지 않음 |
| 색상 | 각 색상은 하나의 악기. 모두 부드러운 톤으로, 순수 사인파에 가까움 |
| 레벨 | 성부가 쌓여도 일정하게 유지되며, 약 -16dB |
| 순서 | 페이지를 가로지르는 파도, 그다음 큰 모양, 그다음 세부 요소. 각 레이어 사이에 1~2번의 휩쓰는 동안 듣는 시간, 마지막에는 새로운 요소 없이 약 2번 휩쓰는 시간 |
단계
- 주제 정하기. 사용자가 무엇을 그릴지 정하지 않았다면,
drawings.md에서 3가지를 제안하되, 자라나는 것을 먼저 제시하세요. 모서리에 핸들(handle)을 넣는 것은 선택 사항이며 대부분의 릴에는 없으므로, 사용자가 요청할 때만 추가하세요. - 템플릿 복사하기:
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분 소요). - 최종본 접촉 시트(Contact sheet) 생성 후 전달:
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', // 모든 조(key): 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.
5음 음계의 높이. 다음은 D조에 대한 15단계이며, 각각 88단위 간격입니다. 다른 조는 이름이 바뀌고 높이는 유지됩니다.
| 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 음계는 15단계 대신 21단계이므로, 음표 테이블에서 해당 높이를 읽으세요.
좋은 결과를 위한 규칙
첫 번째 획은 페이지 전체를 가로지르며, 두 음 사이의 선 위에 있어야 합니다. 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개 이상의 음을 가져야 합니다. 하나의 음만 있는 긴 선은 드론(drone)입니다. 더 높이를 주거나, 음선을 교차하도록 이동하세요.
- "휩쓰는 주기의 무음 부분"은 0이거나 거의 0이어야 합니다.
- 마지막 획은 비디오가 끝나기 약 2회 휩쓰는 주기 전에 종료되어야 합니다.
문제 해결
- 그림이 이상해 보일 경우: 점들을 변경하고
--stills를 다시 실행하세요. 몇 초 만에 완료되므로 여러 번 반복하세요. - 특정 부분 소리가 얇을 경우: 점선 레이어를 추가하거나, 새로운 색상으로 페이지를 가로지르는 낮은 선을 추가하세요.
- Puppeteer가 없을 경우:
make.cjs가 있는 폴더에서npm i puppeteer를 실행하세요. - ffmpeg가 없을 경우: 설치하세요 (Mac의 경우
brew install ffmpeg).--check및--sound는 ffmpeg 없이도 작동하지만, 비디오에는 필요합니다.
당신의 것으로 유지하세요
형식을 복사하여 자신만의 그림을 만드세요. 다른 제작자의 핸들, 그림 또는 앱 화면을 사용하지 말고, 아직 얻지 못한 조회수를 비디오에 표시하지 마세요.