53

我需要检查一组音频文件的持续时间。有没有一种简单的方法可以在 unix 命令行上执行此操作?

> duration *

我有一个很棒的 SoX 应用程序,它有一个名为 stats 的选项,可以生成一组音频信息,包括持续时间。我正在寻找一种只获得持续时间的方法。我对输出格式很灵活,可以是任何样本长度、hh:mm:ss 或秒。后者将是我的偏好。

4

18 回答 18

52
soxi -D filename
soxi -D *

Soxi 查询音频文件的元数据;D 是持续时间选项。它支持通配符。Soxi 的老大哥sox做命令行音频处理。

于 2012-01-21T16:41:54.963 回答
37
mp3info -p "%m:%02s\n" filename

以格式为您提供指定文件的长度mm:ss(mm 可以大于 59)。对于文件中的总秒数,您将使用:

mp3info -p "%S\n" filename

要在几秒钟内获得所有 mp3 文件的总长度,AWK 可以提供帮助:

mp3info -p "%S\n" *.mp3 | awk 'BEGIN { s = 0 }; { s = s + $1 }; END { print s }'
于 2012-01-19T20:59:49.877 回答
18
ffmpeg -i <audiofile> 2>&1 | grep Duration
于 2018-02-06T02:48:14.700 回答
16

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
于 2015-10-19T18:17:32.200 回答
12

在 OSX 上

打印当前目录中每个音频文件的长度:

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

包括文件路径:

afinfo * | awk '/File:/ { song=$2 } /estimated duration/ { print song, $3 }'
于 2016-02-27T00:39:41.667 回答
9

除了 cdosborn 的答案,递归计算当前目录子文件夹中所有文件的长度,.mp3并以格式显示总和结果days:hours:minutes:seconds

在 zsh 中:

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))}'

在 bash 或 sh 中:

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
$
于 2017-01-21T00:36:04.350 回答
8

ffprobe

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

输出如下所示:

时长:00:44:33.50,开始:0.011995,比特率:128 kb/

于 2019-05-19T17:24:24.277 回答
8

使用 ffmpeg 可以高精度地获得以秒为单位的原始持续时间ffprobe,如下所示:

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
于 2019-12-02T14:10:04.177 回答
8

如果您有兴趣使用soxi和 python在目录中查找 wav 文件的总持续时间,您可以使用以下命令:

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

input_dir根据您的输入目录进行更改。如果您想查找所有 wav 文件之间的最大/最小持续时间,请随时更改summaxmin

于 2019-12-02T14:57:53.227 回答
7
sox --info -D file             --> duration in seconds
sox --info -d file             --> duration in HH:mm:ss.ss
sox --info file                --> metadata 
于 2017-09-29T17:05:56.967 回答
4

syssyphus的基于 commandlinefu的mplayer 的解决方案 ,适用于音频和视频文件:

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

于 2018-02-08T05:23:21.173 回答
3

我在这里扩展了 Navid Naderi 的答案,并创建了一个 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
于 2021-03-03T16:49:21.150 回答
2

另一个基于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
于 2017-05-02T19:17:25.347 回答
1

mediainfo 可以做到这一点,但 mediainfo 是那些有用的工具之一,它的文档记录如此糟糕,以至于您几乎需要知道如何使用它才能学习如何使用它(在 linux 世界中经常发生)。

经过数小时的试验和高低阅读,我终于让它生成一个以逗号分隔的递归文件名列表及其持续时间(以毫秒为单位)。

cd 到起始目录并发出以下命令:

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

结果将输出到 list.txt。

于 2017-01-08T01:28:32.430 回答
0

(当您没有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
于 2019-05-11T22:14:43.647 回答
0

也许有点晚了,但这是我的版本。

# by dnetto

[[ "$#" -lt 1 ]] && echo -e "imput error\n\$>$0 *.mp3" && exit
echo "geting time of all songs\n"

declare td=0
declare th=0
declare tm=0
declare ts=0
function updateTotal
{
        [[ "$ts" -gt 60 ]] && tm=`echo $tm + $ts / 60 | bc` ; ts=`echo $ts % 60 | bc`
        [[ "$tm" -gt 60 ]] && th=`echo $th + $tm / 60 | bc` ; tm=`echo $tm % 60 | bc`
        [[ "$th" -gt 24 ]] && td=`echo $td + $th / 24 | bc`
}

for i in "$@"; do
        m=`mp3info -p %m $i`
        s=`mp3info -p %s $i`
        t=`mp3info -p %S $i`
        [[ "$color" = "" ]] && color="\033[38;5;199m" || color=""
        printf "$color%.2d:%.2d  -=- %s\033[0m\n" $m $s $i
        ts=`echo $ts + $t | bc`
        updateTotal
done
echo -e "\n=======================================================\n\ttotal time:"
printf "%d days %.2d hours %.2d minutes %.2d seconds" $td $th $tm $ts
echo -e "\n======================================================="                                                                            

如果您不想冗长,只需在里面评论 printf 即可获得总数

于 2021-12-21T11:06:39.897 回答
0

MP3 有很多选择。

说到 OGG,TinyTag是我迄今为止发现的最好的。

贝壳

$ python -m tinytag --format csv /some/music.mp3
> {"filename": "/some/music.mp3", "filesize": 30212227, "album": "Album", "albumartist": "Artist", "artist": "Artist", "audio_offset": null, "bitrate": 256, "channels": 2, "comment": null, "composer": null, "disc": "1", "disc_total": null, "duration": 10, "genre": null, "samplerate": 44100, "title": "Title", "track": "5", "track_total": null, "year": "2012"}

或 Python

from tinytag import TinyTag
tag = TinyTag.get('/some/music.mp3')
print('This track is by %s.' % tag.artist)
print('It is %f seconds long.' % tag.duration)

读取支持格式的音频文件的标签、长度和封面图像

MP3 (ID3 v1, v1.1, v2.2, v2.3+)
Wave/RIFF
OGG
OPUS
FLAC
WMA
MP4/M4A/M4B
AIFF/AIFF-C
于 2021-12-27T10:20:41.297 回答
0

在 Debian/Ubuntu 上用于 FLAC 的非常简单的单行代码,对几乎所有音频容器文件和 SoX 都很有用:

for i in *.flac ; do echo -ne "${i} - " ; soxi -d "${i}" ;  done

soxi -V

可以改为使用,但是您将需要sedorawkgrep以紧凑形式转换输出。

于 2022-02-07T17:05:40.643 回答