Как добавить кучу WAV-файлов, сохранив (не добавляя ноль) числовой порядок?
У меня есть много (7500) WAV-файлов (названных по их номерам), которые я хотел бы объединить в один. Я думаю, что это должно быть сделано с помощью цикла bash, потому что при использовании глобирования некоторые файлы были бы в неправильном порядке (например, 1111 до 2).
Какой лучший способ сделать это под Linux?
2 ответа
Если все файлы имеют одинаковые параметры, такие как частота дискретизации и количество каналов, вы все равно не можете просто их объединить. Вы должны удалить заголовок WAV.
Это может быть проще всего использовать утилиту манипулирования звуковыми файлами, как sox
, который содержит метод для объединения файлов. На самом деле, он делает это по умолчанию. Например, чтобы объединить три WAV-файла в один длинный:
$ sox short1.wav short2.wav short3.wav long.wav
Цикл не будет располагать файлы в нужном вам порядке. Вам нужно отсортировать имена, но обработать их численно. sort -n
сделаю это.
Таким образом:
$ sox $(ls *.wav | sort -n) out.wav
Если sox
не можем обработать столько файлов, мы можем разбить работу следующим образом:
$ ls *.wav | sort -n > script
Тогда у нас есть файл сценария, который выглядит так:
1.wav
2.wav
...
3999.wav
4000.wav
...
file7500.wav
Мы редактируем это, чтобы сделать несколько командных строк:
# catenate about half the files to temp1.wav
sox \
1.wav \
2.wav \
... \
3999.wav \
temp1.wav
# catenate the remainder to temp2.wav
sox \
4000.wav \
... \
7500.wav \
temp2.wav
# catenate the two halves
sox temp1.wav temp2.wav out.wav ; rm temp1.wav temp2.wav
В качестве первого шага редактирования в списке файлов вы можете использовать vi
команда :%s/.*/& \\/
добавить обратную косую черту после каждой строки.
Это беспокоило меня сегодня, так как мне нужно было объединить гораздо больше файлов, чем мог загрузить sox. В итоге я использовал этот сценарий оболочки внутри папки с wav-файлами (пожалуйста, убедитесь, что вам не нужны in.wav и out.wav, поскольку они будут перезаписаны):
rm in.wav out.wav
ls *.wav | sort -n | while read l;
do
if [ ! -f in.wav ]
then
cp $l in.wav
else
sox in.wav $l out.wav
cp out.wav in.wav
fi
echo "$l"
done
``