Skip to content

Instantly share code, notes, and snippets.

@killerbees19
Created March 28, 2025 19:01
Show Gist options
  • Save killerbees19/6f24d2cfb1e7b2e159cc662ad20dd7a3 to your computer and use it in GitHub Desktop.
Save killerbees19/6f24d2cfb1e7b2e159cc662ad20dd7a3 to your computer and use it in GitHub Desktop.
Cut files with ffmpeg lossless
#!/bin/bash
###
# [email protected] (2025-03-19)
# https://gist.github.com/90f21ebb14024c40ba46c16a0325a10d
###
set -euf -o pipefail
function errexit
{
printf '%s: %s\n' "$(basename "$0")" "$*"
exit 1
}
if [[ $# -lt 1 ]]
then
printf 'Usage: %s FILENAME START END\n' "$(basename "$0")" >&2
exit 1
fi
filename=$1
start=$2
end=$3
[[ -f "$filename" && -r "$filename" ]] || errexit "File not found or not readable!"
[[ "$start" =~ ^(([0-9]+:)?[0-9]+:)?[0-9]+$ ]] || errexit "Invalid start time format!"
[[ "$end" =~ ^(([0-9]+:)?[0-9]+:)?[0-9]+$ ]] || errexit "Invalid end time format!"
IFS=':' read -r -a astart <<< "$start"
starth=0; [[ ${#astart[@]} -gt 2 ]] && starth=$((10#${astart[-3]}))
startm=0; [[ ${#astart[@]} -gt 1 ]] && startm=$((10#${astart[-2]}))
starts=$((10#${astart[-1]}))
unset astart
IFS=':' read -r -a aend <<< "$end"
endh=0; [[ ${#aend[@]} -gt 2 ]] && endh=$((10#${aend[-3]}))
endm=0; [[ ${#aend[@]} -gt 1 ]] && endm=$((10#${aend[-2]}))
ends=$((10#${aend[-1]}))
unset aend
rend=$((endh * 3600 + endm * 60 + ends))
rstart=$((starth * 3600 + startm * 60 + starts))
[[ "$rend" -gt "$rstart" ]] || errexit "END <= START"
duration=$((rend - rstart))
dirname=$(dirname "$filename")
basename=$(basename "$filename")
if [[ "$filename" =~ [^0-9]*[0-9]{8}_[0-9]{6}\.[^.]+$ ]]
then
IFS='_' read -r -a afile <<< "$basename"
ftime=${afile[-1]}
fdate=${afile[-2]}
unset afile
fdy=${fdate:0:4}
fdm=${fdate:4:2}
fdd=${fdate:6:2}
unset fdate
fth=${ftime:0:2}
ftm=${ftime:2:2}
fts=${ftime:4:2}
unset ftime
suffix=$(printf '.cut_%ds' "$duration")
ext=$(sed -r 's/^.+\.([^.]+)$/\1/' <<< "$filename")
prefix=$(sed -r 's/(.*)[0-9]{8}_[0-9]{6}\.[^.]+$/\1/' <<< "$basename")
date=$(date -ud "$fdy-$fdm-$fdd $fth:$ftm:$fts UTC + $rstart seconds" +'%Y%m%d_%H%M%S')
output=$(printf '%s/%s%s%s.%s' "$dirname" "$prefix" "$date" "$suffix" "$ext")
else
suffix=$(printf '.cut_%d-%d' "$rstart" "$rend")
output=$(sed -r 's/(\.[^.]+)$/'"$suffix"'\1/' <<< "$filename")
fi
[[ -e "$output" ]] && errexit "Output file already exists! ($(basename "$output"))"
ffmpeg -ss "${rstart}s" -to "${rend}s" -i "$filename" -c copy "$output"
exit $?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment