complete beginner here, so sorry if this is painfully obvious. I'm trying to write a shell script to ffmpeg concat protocol a bunch of split video files together by looping over the files and dynamically adding the correct parts to be joined together. For example, turning this:
titlea-00001234-01.ts
titlea-00001234-02.ts
titlea-00001234-03.ts
titleb-00001234-01.ts
titleb-00004321-02.ts
titleb-00004321-03.ts
into this:
titlea-00001234.mp4
titleb-00004321.mp4
by doing this
ffmpeg -i "concat:titlea-00001234-01.ts|titlea-00001234-02.ts|titlea-00001234-03.ts" -c copy titlea-00001234.mp4
ffmpeg -i "concat:titleb-00001234-01.ts|titleb-00001234-03.ts|titleb-00001234-03.ts" -c copy titleb-00001234.mp4
But what I'm having trouble with is using find to add the correct parts after "concat:"
.
Here's my best attempt:
#!/bin/bash
for i in /path/to/files/*.ts
do
if [[ "$i" =~ (-01) ]]
then
j="${i##*/}"
k="${j%-0*}"
ffmpeg -i `concat:( find /path/to/files/ -type f -name "{$k}*" -exec printf "%s\0" {} + )` -c copy /path/to/output/"{$k%.ts}.mp4"
else
echo "no files to process"
exit 0
fi
done
But this gives an error of "No such file or directory".
Edit This solution worked perfectly for my needs https://stackoverflow.com/a/75807616/21403800 Thanks @pjh and everyone else for taking the time to help
Try this Shellcheck-clean code:
#! /bin/bash -p
shopt -s nullglob
cd path_to_files || exit 1
prev_base=
for tsfile in *-[[:digit:]][[:digit:]].ts ''; do
base=${tsfile%-*}
if [[ $base == "$prev_base" ]]; then
iarg+="|$tsfile"
else
[[ -n $prev_base ]] && echo ffmpeg -i "$iarg" -c copy "${prev_base}.mp4"
iarg="concat:$tsfile"
prev_base=$base
fi
done
shopt -s nullglob
makes globs expand to nothing when nothing matches (otherwise they expand to the glob pattern itself, which is almost never useful in programs).''
before the semicolon in for tsfile in *-[[:digit:]][[:digit:]].ts ''; do
is an empty string sentinel to cause the last batch of files matched by the *-[[:digit:]][[:digit:]].ts
pattern to be processed by the code in the loop body.${tsfile%-*}
.ffmpeg
commands to be executed. Remove the echo
to have it actually run the ffmpeg
commands.