From video-editing
Assemble a single video from a folder of clips — concat in a chosen order, optionally with crossfade transitions, normalized to a target resolution/fps. Use when the user says "stitch this folder into one video", "render-from-library", "concat the clips in folder X", "make a montage from these clips". Lossless concat path when all clips share codec/params; transcoding fallback otherwise.
npx claudepluginhub danielrosehill/claude-code-plugins --plugin video-editingThis skill is limited to using the following tools:
Assemble a single deliverable from a folder of clips.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
Assemble a single deliverable from a folder of clips.
| Field | Default |
|---|---|
| Source folder | required |
| Output | default: <source>/_assembled_<timestamp>.mp4 |
| Order | name (alphabetical) — mtime (modification time) — manual (user supplies an ordered list) |
| Recursive | no |
| Transitions | none (hard cuts) — crossfade:<seconds> (default 0.5s when on) |
| Normalize | auto — re-encode if clips differ; pick most-common resolution/fps as target |
| Render profile | optional — apply a named profile from render-profiles.json for the final encode |
SRC="$(realpath "$INPUT")"
if [ "$RECURSIVE" = "yes" ]; then
mapfile -t CLIPS < <(find "$SRC" -type f \( -iname '*.mp4' -o -iname '*.mov' -o -iname '*.mkv' -o -iname '*.m4v' \))
else
mapfile -t CLIPS < <(find "$SRC" -maxdepth 1 -type f \( -iname '*.mp4' -o -iname '*.mov' -o -iname '*.mkv' -o -iname '*.m4v' \))
fi
case "$ORDER" in
name) IFS=$'\n' CLIPS=($(printf '%s\n' "${CLIPS[@]}" | sort)); unset IFS ;;
mtime) IFS=$'\n' CLIPS=($(printf '%s\n' "${CLIPS[@]}" | xargs -d '\n' stat -c '%Y %n' | sort -n | cut -d' ' -f2-)); unset IFS ;;
manual) ;; # caller supplies the array directly
esac
[ ${#CLIPS[@]} -lt 2 ] && { echo "Need at least 2 clips."; exit 1; }
probe() {
ffprobe -v error -select_streams v:0 \
-show_entries stream=width,height,r_frame_rate,codec_name -of json "$1"
}
Build a table of (codec, w, h, fps) per clip. Record the most-common signature.
printf "file '%s'\n" "${CLIPS[@]}" > /tmp/concat-list.txt
ffmpeg -f concat -safe 0 -i /tmp/concat-list.txt -c copy "$OUT"
xfade for crossfades or concat filter for hard cuts. All clips first re-scaled / fps-converted to the target signature with scale + fps.For hard cuts (no transition):
[0:v]scale=W:H,fps=F,setsar=1[v0];[1:v]scale=W:H,fps=F,setsar=1[v1];...
[v0][0:a][v1][1:a]...concat=n=N:v=1:a=1[v][a]
For crossfades:
Chain xfade between consecutive video streams, offsetting at (cumulative_duration - fade_duration). Audio uses acrossfade. The cumulative offset must be computed from each clip's duration via ffprobe — list them in the preview before running.
If a render profile was supplied, build the output args from it (same shape render-with-profile uses). Otherwise default to -c:v libx264 -crf 20 -preset medium -c:a aac -b:a 192k.
Print:
Ask for confirm before running.
mkdir -p "$(dirname "$OUT")"
ffmpeg ... "$OUT"
ffprobe -v error -show_entries format=duration,size -of default=nw=1 "$OUT"
Print output path, size, duration. Offer follow-ups (audio-analysis, burn-graphics, generate-deliverables).
audio-to-music-video skill (cover-art + audio composite) — this skill is for video clips.library.txt in the source folder, one filename per line.