Night Market Skill — ported from claude-night-market/scry. For the full experience with agents, hooks, and commands, install the Claude Code plugin.
Combine multiple media assets (GIFs, videos, images) into composite outputs for detailed tutorials and documentation.
This skill orchestrates the combination of separately generated media assets into unified outputs. It reads manifest files that define components and their composition rules, validates all inputs exist, and executes FFmpeg commands to produce the final composite media.
text
- Parse composition manifest file
- Validate all component outputs exist
- Determine composition layout and parameters
- Execute FFmpeg composition command
- Verify combined output file created
- Report composition metrics (file size, dimensions)
Verification: Run the command with --help flag to verify availability.
Manifests define the components to combine and how to arrange them:
yaml
# Example manifest: tutorials/mcp.manifest.yaml
name: mcp
title: "MCP Server Integration"
components:
- type: tape
source: mcp.tape
output: assets/gifs/mcp-terminal.gif
- type: playwright
source: browser/mcp-browser.spec.ts
output: assets/gifs/mcp-browser.gif
requires:
- "skrills serve"
combine:
output: assets/gifs/mcp-combined.gif
layout: vertical
options:
padding: 10
background: "#1a1a2e"
Verification: Run the command with --help flag to verify availability.
FieldTypeRequiredDescriptionnamestringYesIdentifier for the compositiontitlestringNoHuman-readable titlecomponentsarrayYesList of media components to combinecomponents[].typestringYesSource type: tape, playwright, static``components[].sourcestringYesPath to source filecomponents[].outputstringYesPath to generated outputcomponents[].requiresarrayNoCommands to run before generationcombine.outputstringYesPath for combined outputcombine.layoutstringYesLayout mode (see table below)combine.optionsobjectNoLayout-specific options
bash
# Read and validate manifest structure
yq eval '.' manifest.yaml
# Extract component outputs
yq eval '.components[].output' manifest.yaml
Verification: Run the command with --help flag to verify availability.
bash
# Check all required files exist
for output in $(yq eval '.components[].output' manifest.yaml); do
if [[ ! -f "$output" ]]; then
echo "ERROR: Missing component: $output"
exit 1
fi
done
Verification: Run the command with --help flag to verify availability.
Based on the layout specified in the manifest, execute the appropriate FFmpeg command.
bash
# Verify output exists and has content
if [[ -f "$output" && -s "$output" ]]; then
echo "Composition successful: $output"
ls -lh "$output"
else
echo "ERROR: Composition failed"
exit 1
fi
Verification: Run the command with --help flag to verify availability.
Stack GIFs/videos top to bottom:
bash
ffmpeg -i top.gif -i bottom.gif \
-filter_complex "[0:v][1:v]vstack=inputs=2" \
-y output.gif
Verification: Run the command with --help flag to verify availability.
With padding between:
bash
ffmpeg -i top.gif -i bottom.gif \
-filter_complex "[0:v]pad=iw:ih+10:0:0:color=black[top];[top][1:v]vstack=inputs=2" \
-y output.gif
Verification: Run the command with --help flag to verify availability.
Stack GIFs/videos side by side:
bash
ffmpeg -i left.gif -i right.gif \
-filter_complex "[0:v][1:v]hstack=inputs=2" \
-y output.gif
Verification: Run the command with --help flag to verify availability.
Play GIFs/videos one after another:
bash
# Create concat list file
cat > concat_list.txt << EOF
file 'first.gif'
file 'second.gif'
file 'third.gif'
EOF
# Concatenate
ffmpeg -f concat -safe 0 -i concat_list.txt \
-y output.gif
Verification: Run the command with --help flag to verify availability.
bash
ffmpeg -i tl.gif -i tr.gif -i bl.gif -i br.gif \
-filter_complex "[0:v][1:v]hstack=inputs=2[top];[2:v][3:v]hstack=inputs=2[bottom];[top][bottom]vstack=inputs=2" \
-y output.gif
Verification: Run the command with --help flag to verify availability.
bash
ffmpeg -i top.gif -i bottom.gif \
-filter_complex "color=c=#1a1a2e:s=800x600[bg];[bg][0:v]overlay=0:0[tmp];[tmp][1:v]overlay=0:300" \
-y output.gif
Verification: Run the command with --help flag to verify availability.
LayoutDescriptionOptionsverticalStack top to bottompadding, background, align``horizontalStack left to rightpadding, background, align``sequentialPlay in ordertransition, duration``gridN x M grid arrangementrows, cols, padding``overlayLayer on top of each otherposition, opacity``pipPicture-in-picturecorner, scale, margin
OptionTypeDefaultDescriptionpaddingint0Pixels between componentsbackgroundstring"black"Background color (hex or name)alignstring"center"Alignment: left, center, righttransitionstring"none"Transition type: fade, wipe, nonescalefloat0.25Scale factor for PiPcornerstring"br"PiP corner: tl, tr, bl, br
yaml
name: plugin-demo
components:
- type: tape
source: demo.tape
output: terminal.gif
- type: playwright
source: browser.spec.ts
output: browser.gif
combine:
output: demo-combined.gif
layout: vertical
options:
padding: 5
background: "#0d1117"
Verification: Run the command with --help flag to verify availability.
yaml
name: before-after
components:
- type: static
source: before.gif
output: before.gif
- type: static
source: after.gif
output: after.gif
combine:
output: comparison.gif
layout: horizontal
options:
padding: 10
Verification: Run the command with --help flag to verify availability.
yaml
name: pip-demo
components:
- type: tape
source: main.tape
output: main.gif
- type: playwright
source: overlay.spec.ts
output: overlay.gif
combine:
output: pip-demo.gif
layout: pip
options:
corner: br
scale: 0.3
margin: 20
Verification: Run the command with --help flag to verify availability.