Milkdrop
Renders a MilkDrop visualization video from an audio file or link.
MilkDrop Visualizer
Turn audio into a MilkDrop/Butterchurn visualization MP4 and deliver it back to the requester. Triggered when a user sends an audio/video file or a link (YouTube or a direct audio URL) and asks for a visualizer / music video / "milkdrop" / trippy visuals.
Run
Everything runs from one allowlisted wrapper:
{{HOME}}/bin/milkdrop-render.sh --input <url-or-file> [options]
Options:
--inputYouTube/audio URL or a local audio/video file path (required)--outputMP4 path (optional; defaults to~/.openclaw/media/outbound/milkdrop-<timestamp>.mp4)--durationclip length in seconds (default 30)--startstart offset in seconds (default 0)--width/--heightcanvas size--fpsframes per second (default 30)--presetpreset name, index, orrandom(default random)
Aspect shortcuts (pass the matching --width/--height):
- vertical / story / reel —
--width 1080 --height 1920(default) - square —
--width 1080 --height 1080 - landscape —
--width 1920 --height 1080
On success the script prints a single-line JSON summary to stdout, e.g.
{"ok":true,"path":"{{HOME}}/.openclaw/media/outbound/milkdrop-20260612-143012.mp4","preset":"...","duration":30,"width":1080,"height":1920}
Workflow
Resolve the input.
- If the user pasted a URL, pass it directly with
--input <url>. - If the user sent an audio/video file, use the inbound media path
(
~/.openclaw/media/inbound/...) as--input.
- If the user pasted a URL, pass it directly with
Pick options from the request. Honor any requested length (
--duration) and aspect ratio (defaults to vertical). Keep--durationmodest (≤ 60s) unless the user explicitly asks for longer — rendering is real-time plus a transcode pass.Run
{{HOME}}/bin/milkdrop-render.shwith the chosen options.Parse the JSON summary line and read
path.Deliver the MP4 back on the same channel the request came in on:
openclaw message send --channel <channel> --target <chat-id> \ --media "<path>" --force-document \ -m "Here's your MilkDrop visualization 🌀 (preset: <preset>)"Use
--force-documentso the video is not re-compressed by the channel.
Notes
- Remote URLs require
yt-dlp(at/usr/local/bin/yt-dlp); local files only needffmpeg/ffprobe. - Output files accumulate in
~/.openclaw/media/outbound/; old renders are safe to clean up. - On failure the script exits non-zero and writes the error to stderr. Reply with a short, friendly note and the gist of the error.
