#!/usr/bin/env bash set -euo pipefail command -v ffmpeg >/dev/null || { echo "ffmpeg is required" >&2; exit 127; } command -v ffprobe >/dev/null || { echo "ffprobe is required" >&2; exit 127; } test_dir="$(mktemp -d)" trap 'rm -rf "$test_dir"' EXIT make_sample() { local output="$1" local duration="$2" ffmpeg -hide_banner -loglevel error \ -f lavfi -i "testsrc2=size=320x180:rate=25" \ -f lavfi -i "sine=frequency=1000:sample_rate=48000" \ -t "$duration" -c:v libx264 -preset ultrafast -pix_fmt yuv420p \ -c:a aac -b:a 96k -movflags +faststart -y "$output" } make_sample "$test_dir/short-a.mp4" 1.2 make_sample "$test_dir/short-b.mp4" 2.1 make_sample "$test_dir/normal.mp4" 6.4 run_case() { local name="$1" local minimum_duration="$2" shift 2 local list="$test_dir/$name.txt" local output="$test_dir/$name.mp4" : > "$list" for source in "$@"; do printf "file '%s'\n" "$source" >> "$list" done ffmpeg -hide_banner -loglevel error -f concat -safe 0 -i "$list" \ -map 0 -c copy -movflags +faststart -y "$output" local duration duration="$(ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 "$output")" local video_streams video_streams="$(ffprobe -v error -select_streams v:0 -show_entries stream=index -of csv=p=0 "$output" | wc -l)" awk -v actual="$duration" -v minimum="$minimum_duration" 'BEGIN { exit !(actual >= minimum) }' test "$video_streams" -ge 1 echo "$name ok: duration=${duration}s" } run_case short_then_normal 7.0 "$test_dir/short-a.mp4" "$test_dir/normal.mp4" run_case normal_then_short 7.0 "$test_dir/normal.mp4" "$test_dir/short-a.mp4" run_case consecutive_shorts 9.0 "$test_dir/short-a.mp4" "$test_dir/short-b.mp4" "$test_dir/normal.mp4"