Проблема, с которой вы сталкиваетесь, заключается в том, что concat
демпфер ffmpeg требует входной файл, содержащий директивы, а не простой список файлов.
Ваш вызов find
создает файл, подобный:
output_vocal/output_000/vocal.wav
output_vocal/output_001/vocal.wav
output_vocal/output_002/vocal.wav
, в то время как ffmpeg concat
demuxer действительно требует такой файл, как:
file output_vocal/output_000/vocal.wav
file output_vocal/output_001/vocal.wav
file output_vocal/output_002/vocal.wav
Также обратите внимание, что find
не обязательно возвращает файлы в алфавитном порядке c, тогда как большинство скорее всего, вы захотите объединить файлы в таком порядке.
Наконец, при объединении WAV-файлов вы не можете использовать copy
код c для создания файла MP3 (поскольку код WAV / RIFF * 1022) * это не MP3). но вам все равно не нужен промежуточный MP3-файл
Вот обновленный скрипт, который - использует временный каталог для всех промежуточных файлов - перебирает все mp4-файлы, представленные на cmdline (вместо жесткого ввода каталог) - создает файл «XXX_vo c .mp4» для каждого входного файла «XXX.mp4» (перезаписывая любые существующие файлы)
#!/bin/bash
for infile in "$@"
do
outfile=${infile%.mp4}_voc.mp4
# create a temp-directory to put our stuff to
TMPDIR=$(mktemp -d)
# create audio from video
ffmpeg -i "${infile}" "${TMPDIR}/output.mp3"
# Split the audio into pieces
ffmpeg -i "${TMPDIR}/output.mp3" -f segment -segment_time 120 -c copy "${TMPDIR}/output_%03d.mp3"
# Execute Spleeter upon each sample
find "${TMPDIR}" -maxdepth 1 -type f -name "output_*.mp3" \
-exec spleeter separate -i {} -o "${TMPDIR}/output_vocal" ";"
# find all 'vocal.wav' files generated by spleeter, sort them,
# prefix them with 'file ', and put them into output.txt
find "${TMPDIR}/output_vocal" -type f -name "vocal.wav" -print0 \
| sort -z \
| xargs -0 -I{} echo "file '{}'" \
> "${TMPDIR}/output.txt"
# concatenate the files and create an MP3 file
ffmpeg -f concat -safe 0 -i "${TMPDIR}/output.txt" -c copy "${TMPDIR}/vocal.wav"
# merge the audio back to video
ffmpeg -y -i "${infile}" -i "${TMPDIR}/vocal.wav" \
-c:v copy -c:a aac -strict experimental \
-map 0:v:0 -map 1:a:0 "${outfile}"
rm -rf "${TMPDIR}"
done