pipo. docs

audio-to-video

A watch input picks up every .mp3 dropped in ./inbox. A transform: exec node runs ffmpeg to loop ./cover.jpg over the track and write ./out/<name>.mp4. The output appends one JSON line per video (exit code, time taken, the file) to ./out/videos.jsonl.

Needs ffmpeg on the machine (brew install ffmpeg, apt install ffmpeg). Without it, the pipeline refuses to start and says so.

bun pipo check examples/audio-to-video
bun pipo run examples/audio-to-video/audio-to-video.pipo
cp song.mp3 examples/audio-to-video/inbox/
tail -f examples/audio-to-video/out/videos.jsonl

Swap cover.jpg for your own image. inbox/ and out/ are git-ignored.

audio-to-video.pipo#

pipo: 1
name: audio-to-video
description: Turns every mp3 dropped in ./inbox into an mp4 that shows ./cover.jpg for the whole track.

# Needs ffmpeg on this machine (brew install ffmpeg). Runs no shell: each arg goes to ffmpeg as it is.
input:
  via: watch
  with:
    path: ./inbox/*.mp3
    events: [create]
    read: path

nodes:
  render:
    from: input
    transform: exec
    with:
      command: ffmpeg
      args:
        - -y
        - -loglevel
        - error
        - -loop
        - "1"
        - -i
        - ./cover.jpg
        - -i
        - ${data.path}
        - -c:v
        - libx264
        - -tune
        - stillimage
        - -c:a
        - aac
        - -b:a
        - 192k
        - -pix_fmt
        - yuv420p
        - -shortest
        - ./out/${data.name}.mp4
      outputs: ["./out/${data.name}.mp4"]
      timeout: 10m

output:
  from: render
  to: file
  with:
    path: ./out/videos.jsonl
    format: jsonl

Source: examples/audio-to-video.