【问题标题】:check duration of audio files on the command-line在命令行上检查音频文件的持续时间
【发布时间】:2012-02-14 12:36:18
【问题描述】:

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

> duration *

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

【问题讨论】:

    标签: unix audio sox


    【解决方案1】:
    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 }'
    

    【讨论】:

    • 所以把它包装在一个 for 循环中,你就准备好了,for file in *.mp3 ; do mp3info -p "%m:%s\n" $file ; done。祝大家好运。
    • mp3info -p " %f %m:%s\n" *.mp3 也可以 - 将打印文件名和持续时间
    • 仅适用于 mp3 文件,不适用于 e.g. wav 或 ogg 容器。
    【解决方案2】:
    soxi -D filename
    soxi -D *
    

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

    【讨论】:

    • soxi 也是我用的,可惜它缺乏 m4a 支持
    • 只有我,还是连mp3都不支持?我收到soxi FAIL formats: no handler for file extension 'mp3'编辑:原来我必须sudo apt-get install libsox-fmt-mp3
    • 还有soxi -d表示小时、分钟和秒
    • 为了给 sox 添加 mp3 支持,安装 libsox-fmt-mp3
    【解决方案3】:

    mediainfo 将返回音频文件的毫秒数。假设当前目录只有音频文件,如下

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

    要计算本地目录中所有音频的持续时间,this gist 会有所帮助:

    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
    

    【讨论】:

    • 这个工具很棒,也适用于 ogg 文件,并且在 debian 存储库中可用
    • 我认为与其他答案相比,这个答案需要的机器运行它的资源最少。
    • 只为我打印一个空行。
    【解决方案4】:

    在 OSX 上

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

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

    包含文件路径:

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

    【讨论】:

      【解决方案5】:

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

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

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

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

      结果会输出到list.txt。

      【讨论】:

        【解决方案6】:

        除cdosborn的answer外,递归计算当前目录子文件夹中所有.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
        $
        

        【讨论】:

          【解决方案7】:

          另一个基于 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
          

          【讨论】:

            【解决方案8】:
            sox --info -D file             --> duration in seconds
            sox --info -d file             --> duration in HH:mm:ss.ss
            sox --info file                --> metadata 
            

            【讨论】:

              【解决方案9】:
              ffmpeg -i <audiofile> 2>&1 | grep Duration
              

              【讨论】:

              • 您也可以use ffprobe 附带ffmpeg 并为此而设计。
              • 哇,说到媒体文件,ffmpeg 永远不会让你失望。
              【解决方案10】:

              基于commandlinefu by syssyphus 的 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

              【讨论】:

                【解决方案11】:

                (当您没有 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
                

                【讨论】:

                  【解决方案12】:

                  ffprobe

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

                  输出如下:

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

                  【讨论】:

                  • 带 xargs find *.mp3 | xargs -I {} ffprobe -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "{}" 2&gt;/dev/null | awk 'BEGIN { s = 0 }; { s = s + $1 }; END { print s }'
                  【解决方案13】:

                  使用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
                  

                  【讨论】:

                    【解决方案14】:

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

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

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

                    【讨论】:

                      【解决方案15】:

                      我在此处扩展了 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
                      

                      【讨论】:

                        【解决方案16】:

                        可能有点晚了,但这是我的版本。

                        # 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 就可以得到总数

                        【讨论】:

                        • 完整的脚本请看我的github
                        【解决方案17】:

                        对于 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
                        

                        【讨论】:

                          猜你喜欢
                          • 2016-02-10
                          • 1970-01-01
                          • 2015-07-25
                          • 1970-01-01
                          • 2015-10-13
                          • 2013-03-01
                          • 1970-01-01
                          • 2016-04-23
                          • 1970-01-01
                          相关资源
                          最近更新 更多