проверить продолжительность аудиофайлов в командной строке

Мне нужно проверить продолжительность группы аудиофайлов. Есть ли простой способ сделать это в командной строке unix?

> duration *

У меня есть замечательное приложение SoX, в котором есть опция, называемая stats, которая генерирует набор звуковой информации, включая продолжительность. Я ищу способ получить только продолжительность. У меня гибкий формат вывода, может быть любая длина выборки, чч: мм: сс или секунды. Последнее было бы моим предпочтением.


person ted.strauss    schedule 19.01.2012    source источник


Ответы (14)


mp3info -p "%m:%02s\n" filename

дает вам длину указанного файла в формате mm:ss (мм может быть больше 59). Только для общего количества секунд в файле вы должны использовать:

mp3info -p "%S\n" filename

Чтобы получить общую длину всех mp3-файлов в секундах, AWK может помочь:

mp3info -p "%S\n" *.mp3 | awk 'BEGIN { s = 0 }; { s = s + $1 }; END { print s }'
person 0xbadc0de    schedule 19.01.2012
comment
поэтому заверните это в цикл for, и все готово, for file in *.mp3 ; do mp3info -p "%m:%s\n" $file ; done. Всем удачи. - person shellter; 20.01.2012
comment
mp3info -p %f %m:%s\n *.mp3 тоже работает - напечатает имя файла и продолжительность - person David Rabinowitz; 08.06.2014
comment
Работает только для файлов mp3, а не, например. wav или ogg контейнеры. - person Charles Boling; 15.08.2019

soxi -D filename
soxi -D *

Soxi запрашивает метаданные аудиофайлов; D — параметр продолжительности. Он поддерживает подстановку. Старший брат Soxi sox выполняет обработку звука из командной строки.

person ted.strauss    schedule 21.01.2012
comment
soxi - это то, что я тоже использую, но, к сожалению, ему не хватает поддержки m4a. - person dan3; 11.02.2015
comment
Мне кажется, или он вообще не поддерживает мп3? Я получаю soxi FAIL formats: no handler for file extension 'mp3'. EDIT: оказалось, что мне нужно было sudo apt-get install libsox-fmt-mp3. - person bluenote10; 10.10.2019
comment
Также есть soxi -d для часов, минут и секунд. - person cambunctious; 24.06.2020

mediainfo вернет вам миллисекунды аудиофайла. Предполагая, что в текущем каталоге есть только аудиофайлы, следующее

mediainfo --Inform="Audio;%Duration%" "Miley Cyrus - Wrecking Ball.mp3"

Чтобы рассчитать продолжительность всего аудио в локальном каталоге, эта суть поможет:

shopt -s nullglob
let playlist_duration_ms=0
for song_file in *.{mp3,ogg,m4a,flac,wav}; do
  playlist_duration_ms=$(expr $playlist_duration_ms + $(mediainfo --Inform="Audio;%Duration%" "$song_file"))
done
shopt -u nullglob

let playlist_duration_secs=$(expr $playlist_duration_ms / 1000)
let playlist_duration_mins=$(expr $playlist_duration_ms / 60000)
let playlist_duration_remaining_secs=$(expr $playlist_duration_secs - $(expr $playlist_duration_mins \* 60))

echo $playlist_duration_mins minutes, $playlist_duration_remaining_secs seconds
person DoggoDougal    schedule 19.10.2015
comment
Этот отличный инструмент работает и с файлами ogg и доступен в репозиториях Debian. - person quantumbyte; 15.04.2016
comment
Я думаю, что этот ответ требует наименьших ресурсов от машины, на которой он работает, по сравнению с другими ответами. - person Doron Behar; 15.12.2017
comment
Только печатает пустую строку для меня. - person JellicleCat; 06.02.2018

на OS X

Распечатайте длину каждого аудиофайла в текущем каталоге:

afinfo * | awk '/estimated duration/ { print $3 }'

Включите путь к файлу:

afinfo * | awk '/File:/ { song=$2 } /estimated duration/ { print song, $3 }'
person cdosborn    schedule 27.02.2016

В дополнение к ответу cdosborn, чтобы рекурсивно вычислить длину всех .mp3 файлов в подпапках текущего каталога и показать результат общей суммы в формате days:hours:minutes:seconds:

В зш:

afinfo **/*.mp3 | awk '/estimated duration/ { print $3 }' | paste -sd+ - | bc | awk '{printf("%d:%02d:%02d:%02d\n",($1/60/60/24),($1/60/60%24),($1/60%60),($1%60))}'

В баш или ш:

find . -name "*.mp3" -exec afinfo {} \; | awk '/estimated duration/ { print $3 }' | paste -sd+ - | bc | awk '{printf("%d:%02d:%02d:%02d\n",($1/60/60/24),($1/60/60%24),($1/60%60),($1%60))}'

Результат такой (7 дней, 5 часов, 6 минут, 58 секунд):

$ afinfo **/*.mp3 | awk '/estimated duration/ { print $3 }' | paste -sd+ - | bc | awk '{printf("%d:%02d:%02d:%02d\n",($1/60/60/24),($1/60/60%24),($1/60%60),($1%60))}'
7:05:06:58
$
person Hamid Rohani    schedule 21.01.2017

Если вас интересует общая продолжительность wav-файлов в каталоге с помощью soxi и python, вы можете использовать это:

soxi -D input_dir/*.wav | python -c "import sys;print(sum(float(l) for l in sys.stdin))"

измените input_dir в соответствии с вашим входным каталогом. Если вы хотите найти максимальную/минимальную продолжительность между всеми файлами wav, не стесняйтесь изменить sum на max или min.

person Navid Naderi    schedule 02.12.2019

Необработанная продолжительность в секундах может быть получена с высокой степенью точности с использованием ffprobe ffmpeg следующим образом:

ffprobe -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "filename.mp3" 2>/dev/null

Вывод, который легко использовать в дальнейших сценариях, отформатирован следующим образом:

193.656236

В дополнение к этому, следующее будет измерять общую продолжительность в секундах всех файлов .mp3 в текущем каталоге:

LENGTH=0; for file in *.mp3; do if [ -f "$file" ]; then LENGTH="$LENGTH+$(ffprobe -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)"; fi; done; echo "$LENGTH" | bc

А для измерения общей длины аудиофайлов с несколькими расширениями можно добавить еще один подстановочный знак:

LENGTH=0; for file in *.mp3 *.ogg; do if [ -f "$file" ]; then LENGTH="$LENGTH+$(ffprobe -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)"; fi; done; echo "$LENGTH" | bc
person S. Exchange Considered Harmful    schedule 02.12.2019

Решение на основе mplayer из commandlinefu от syssyphus, который работает как с аудио-, так и с видеофайлами:

sudo apt-get install mplayer
find -type f -name "*.mp3" -print0 | xargs -0 mplayer -vo dummy -ao dummy -identify 2>/dev/null | perl -nle '/ID_LENGTH=([0-9\.]+)/ && ($t +=$1) && printf "%02d:%02d:%02d\n",$t/3600,$t/60%60,$t%60' | tail -n 1

Получить общую длину всего видео/аудио в текущем каталоге (и ниже) в H:m:s

Измените *.mp3 на то, что вы хотите сопоставить (например, *.avi, *.wav), вы можете полностью удалить его, если хотите проверить все файлы.

Пример вывода: 00:00:37

person Franck Dernoncourt    schedule 08.02.2018

с ffprobe

ffprobe your_file.mp3 2>&1 | grep "Duration"

Вывод выглядит следующим образом:

Продолжительность: 00:44:33.50, начало: 0.011995, битрейт: 128 кб/

person Matthias Braun    schedule 19.05.2019
comment
С xargs find *.mp3 | xargs -I {} ffprobe -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "{}" 2>/dev/null | awk 'BEGIN { s = 0 }; { s = s + $1 }; END { print s }' - person Tahlor; 08.07.2021

Я расширил ответ Навида Надери здесь и создал функцию bash, которая даст вам сводку о времени работы каждого файла, а также некоторое общее время в различных форматах (секунды, минуты или общее время работы).

function sox_duration_total
{
  if [[ "$#" -lt 1 ]]; then
    echo "find files!"
    echo "  sox_duration_total *.wav"
    echo ""
    return
  fi
  for i in "$@"; do
    val=`soxi -d "$i"`
    echo "$val | $i"
  done
  soxi -D "$@" | python -c "import sys;print(\"\ntotal sec:    \" +str( sum(float(l) for l in sys.stdin)))"
  soxi -D "$@" | python -c "import sys;print(\"total min:    \" +str( sum(float(l) for l in sys.stdin)/60 ))"
  soxi -D "$@" | python -c "import sys;import datetime;print(\"running time: \" +str( datetime.timedelta(seconds=sum(float(l) for l in sys.stdin)) ))"
}

Вывод будет выглядеть так:

00:01:40.97 | subatomicglue - inertialdecay - 01 - hard.wav
00:00:32.00 | subatomicglue - inertialdecay - 02 - acidbass.wav
00:04:50.80 | subatomicglue - inertialdecay - 03 - cause.of.a.new.dark.age.wav
00:02:08.00 | subatomicglue - inertialdecay - 04 - daybreak.falls.wav
00:05:20.75 | subatomicglue - inertialdecay - 05 - forestfloor.wav
00:03:56.32 | subatomicglue - inertialdecay - 06 - rabbithole.wav
00:03:50.40 | subatomicglue - inertialdecay - 07 - feedme.wav
00:06:03.97 | subatomicglue - inertialdecay - 08 - grand.wav
00:02:09.45 | subatomicglue - inertialdecay - 09 - strawberryflavoreddeath.wav
00:04:43.29 | subatomicglue - inertialdecay - 10 - subfloor.wav
00:03:36.96 | subatomicglue - inertialdecay - 11 - silicone.wav
00:04:28.47 | subatomicglue - inertialdecay - 12 - inertial decay.wav
00:01:23.81 | subatomicglue - inertialdecay - 13 - the.void.wav
00:01:18.86 | subatomicglue - inertialdecay - 14 - weet.wav

total sec:    2764.0637880000004
total min:    46.06772980000001
running time: 0:46:04.063788
person kevin meinert    schedule 03.03.2021

Другой ответ на основе soxi, включающий имена файлов и продолжительность в формате часов, минут и секунд.

$for f in *amr; do printf "$f "; soxi -d $f; done

DGT20161216.amr 00:22:04.62
DGT20170108.amr 00:28:22.80
DGT20170117.amr 00:20:05.18
person alemol    schedule 02.05.2017

mediainfo может это сделать, но mediainfo — один из тех полезных инструментов, который так плохо документирован, что вам почти необходимо знать, как его использовать, чтобы научиться им пользоваться (часто случается в мире Linux).

После нескольких часов испытаний и чтения от и до, я, наконец, смог сгенерировать рекурсивный список имен файлов, разделенных запятыми, и их продолжительность в миллисекундах.

cd в начальный каталог и введите следующую команду:

find "$(pwd)" -type f -print0 | xargs -0 -I {} mediainfo --Inform="General;%CompleteName%,%Duration%" {} > list.txt

Результаты будут выведены в list.txt.

person alex_223    schedule 08.01.2017

(Когда у вас нет afinfo в вашем распоряжении) Я получил его рекурсивно для всех моих файлов

# install mp3info if not yet installed with
sudo apt-get install mp3info

с помощью команды find поместите общее количество секунд в файл csv (сначала перейдите в каталог с вашими, например, файлами mp3)

find . -name "*.mp3" -exec mp3info {} -p "%S\r\n" >> totalSeconds.csv \;

Затем откройте его, например. в LibreOffice и суммируйте его внизу (чтобы получить часы) с помощью

=SUM(A{start}:A{end})/60/60
person Sempfer    schedule 11.05.2019

person    schedule
comment
Вы также можете использовать ffprobe, который поставляется с ffmpeg и предназначен для этого. - person Matthias Braun; 19.05.2019
comment
Ух ты, когда дело доходит до медиафайлов, ffmpeg никогда не подводит. - person Weekend; 18.06.2021