Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Mix, trim, and concatenate video clips with ffmpeg without audio/video desync. Use when stitching generated clips into an original video, inserting scenes at timestamps, or any ffmpeg filter_complex work involving trim/concat with a continuous audio track.
.claude/skills/varghq-ffmpeg-mixing/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | -10% | 0% |
| case-02 | ✗→✓ | ▲ Improved | -14% | 0% |
| case-03 | ✗→✓ | ▲ Improved | -35% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 4% | 0% |
| case-06 | ✗→✓ | ▲ Improved | -18% | 0% |
Lessons for mixing video clips with ffmpeg while keeping audio and video in sync.
using -ss X -t Y to pre-trim input, then applying relative trim filters caused timing drift:
bash# BAD: relative timestamps after pre-trim ffmpeg -ss 64 -t 36 -i original.mp4 ... -filter_complex " [0:v]split=5[orig1][orig2]...; [orig1]trim=0:4,setpts=PTS-STARTPTS[o1]; [orig2]trim=4:11,setpts=PTS-STARTPTS[o2]; ..."
this produced wrong duration (38s instead of 36s) with audio desync.
trim directly from full original using absolute timestamps:
bash# GOOD: absolute timestamps from full file ffmpeg -i original.mp4 -i scene1.mp4 -i scene2.mp4 ... -filter_complex " [0:v]trim=64:68,setpts=PTS-STARTPTS[o1]; [1:v]scale=1280:720,trim=4:6,setpts=PTS-STARTPTS[s1]; [0:v]trim=70:75,setpts=PTS-STARTPTS[o2]; ... [o1][s1][o2]...concat=n=N:v=1:a=0[outv]; [0:a]atrim=64:100,asetpts=PTS-STARTPTS[outa] " -map "[outv]" -map "[outa]"
atrim on audio stream independentlysetpts=PTS-STARTPTS after trim to reset timestampsto insert generated clips at specific timestamps while keeping continuous audio:
bashffmpeg -y \ -i original.mp4 \ -i generated-scene.mp4 \ -filter_complex " [0:v]trim=START1:END1,setpts=PTS-STARTPTS[o1]; [1:v]scale=1280:720,trim=0:DURATION,setpts=PTS-STARTPTS[s1]; [0:v]trim=START2:END2,setpts=PTS-STARTPTS[o2]; [o1][s1][o2]concat=n=3:v=1:a=0[outv]; [0:a]atrim=AUDIO_START:AUDIO_END,asetpts=PTS-STARTPTS[outa] " \ -map "[outv]" -map "[outa]" \ -c:v libx264 -preset fast -crf 18 \ -c:a aac -b:a 192k \ output.mp4
timestamps must add up: (END1-START1) + DURATION + (END2-START2) = AUDIO_END - AUDIO_START
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 16,901 | 9,270 | -45% | 1 | 1 | 0% | 3,205 | 2,869 | -10% | 0 | 0 | — |
case-02 | fail→pass | 19,084 | 11,382 | -40% | 1 | 1 | 0% | 3,550 | 3,057 | -14% | 0 | 0 | — |
case-03 | fail→pass | 22,269 | 9,138 | -59% | 1 | 1 | 0% | 4,046 | 2,610 | -35% | 0 | 0 | — |
case-04 | pass→pass | 6,004 | 3,665 | -39% | 1 | 1 | 0% | 1,086 | 1,491 | +37% | 0 | 0 | — |
case-05 | fail→pass | 10,176 | 5,981 | -41% | 1 | 1 | 0% | 1,791 | 1,866 | +4% | 0 | 0 | — |
case-06 | fail→pass | 14,313 | 7,980 | -44% | 1 | 1 | 0% | 2,677 | 2,208 | -18% | 0 | 0 | — |
case-07 | pass→pass | 15,720 | 8,000 | -49% | 1 | 1 | 0% | 3,058 | 2,282 | -25% | 0 | 0 | — |
case-08 | pass→pass | 12,053 | 7,583 | -37% | 1 | 1 | 0% | 2,365 | 2,360 | -0% | 0 | 0 | — |
case-09 | fail→pass | 12,853 | 11,288 | -12% | 1 | 1 | 0% | 2,512 | 2,750 | +9% | 0 | 0 | — |
case-10 | pass→pass | 5,144 | 3,318 | -35% | 1 | 1 | 0% | 854 | 1,397 | +64% | 0 | 0 | — |
case-11 | fail→pass | 10,095 | 7,221 | -28% | 1 | 1 | 0% | 2,056 | 2,344 | +14% | 0 | 0 | — |
case-12 | pass→pass | 10,696 | 6,758 | -37% | 1 | 1 | 0% | 1,920 | 2,046 | +7% | 0 | 0 | — |
case-13 | pass→pass | 3,680 | 2,470 | -33% | 1 | 1 | 0% | 506 | 1,205 | +138% | 0 | 0 | — |
case-14 | pass→pass | 5,936 | 3,884 | -35% | 1 | 1 | 0% | 1,105 | 1,538 | +39% | 0 | 0 | — |
case-15 | pass→pass | 7,413 | 3,370 | -55% | 1 | 1 | 0% | 1,466 | 1,446 | -1% | 0 | 0 | — |
case-16 | pass→pass | 13,327 | 6,306 | -53% | 1 | 1 | 0% | 2,204 | 1,925 | -13% | 0 | 0 | — |
case-17 | pass→pass | 17,094 | 15,073 | -12% | 1 | 1 | 0% | 2,748 | 3,234 | +18% | 0 | 0 | — |
case-18 | pass→pass | 6,863 | 4,069 | -41% | 1 | 1 | 0% | 1,313 | 1,608 | +22% | 0 | 0 | — |
case-19 | pass→pass | 13,900 | 9,624 | -31% | 1 | 1 | 0% | 2,540 | 2,499 | -2% | 0 | 0 | — |
case-20 | pass→pass | 5,910 | 4,068 | -31% | 1 | 1 | 0% | 1,059 | 1,458 | +38% | 0 | 0 | — |
case-21 | pass→pass | 12,865 | 12,692 | -1% | 1 | 1 | 0% | 2,211 | 3,279 | +48% | 0 | 0 | — |
case-22 | pass→pass | 9,469 | 6,477 | -32% | 1 | 1 | 0% | 1,702 | 2,017 | +19% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +32 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.