搜索 mp3 集合中具有特定歌曲长度的歌曲

搜索 mp3 集合中具有特定歌曲长度的歌曲

我如何在 mp3 文件目录中搜索特定长度之间的歌曲。前任:

findmp3 -min=03:00 -max=03:15 /music/mp3/ebm/

将返回emb/目录中歌曲长度在 3:00 到 3:15 分钟之间的所有 mp3 文件。

我使用 Linux Mint、Ubuntu 以及 CentOS。

答案1

首先安装mp3info,它应该在你的发行版的存储库中(你没有说,所以我假设你正在使用某种Linux)。如果您有基于 Debian 的发行版,您可以使用

sudo apt-get install mp3info

mp3info安装后,您可以使用music以下命令在目录中搜索特定长度的歌曲:

find music/ -name "*mp3" | 
  while IFS= read -r f; do 
   length=$(mp3info -p "%S" "$f"); 
   if [[ "$length" -ge "180" && "$length" -le "195" ]]; then 
     echo "$f"; 
   fi;  
done

上面的命令将搜索music/mp3 文件,如果长度大于或等于 180 秒 (3:00) 且小于或等于 195 秒 (3:15),则打印其名称和长度。man mp3info有关其输出格式的更多详细信息,请参阅 参考资料。

如果您希望能够以 MM:SS 格式输入时间,则情况会变得更加复杂:

#!/usr/bin/env bash

## Convert MM:SS to seconds.
## The date is random, you can use your birthday if you want.
## The important part is not specifying a time so that 00:00:00
## is returned.
d=$(date -d "1/1/2013" +%s);

## Now add the number of minutes and seconds
## you give as the first argument
min=$(date -d "1/1/2013 00:$1" +%s);
## The same for the second arument
max=$(date -d "1/1/2013 00:$2" +%s);

## Search the target directory for files
## of the correct length.
find "$3" -name "*mp3" | 
  while IFS= read -r file; do 
   length=$(mp3info -p "%m:%s" "$file"); 
   ## Convert the actual length of the song (mm:ss format)
   ## to seconds so it can be compared.
   lengthsec=$(date -d "1/1/2013 00:$length" +%s);

   ## Compare the length to the $min and $max
   if [[ ($lengthsec -ge $min ) && ($lengthsec -le $max ) ]]; then 
       echo "$file"; 
   fi; 
done

将上面的脚本保存为findmp3并像这样运行:

findmp3 3:00 3:15 music/

答案2

我怀疑是否有现有的findmp3工具。遵循 Unix 哲学,它可以通过find查找.mp3文件、报告找到的每个文件的长度的另一个工具find以及一些 shell/文本处理粘合来构建。

索克斯是一个常用的处理声音文件的实用程序(sox 之于声音,就像 sed 或 awk 之于文本文件)。命令soxi显示有关声音文件的信息。特别是,soxi -D打印持续时间(以秒为单位)。

对于每个.mp3文件,下面的代码片段调用soxi并解析其输出。如果持续时间在所需范围内,则sh调用将返回成功状态,因此-print执行操作以打印文件名。

find /music/mp3/ebm -type f -name .mp3 -exec sh -c '
    d=$(soxi -D "$0")
    d=${d%.*} # truncate to an integer number of seconds
    [ $((d >= 3*60 && d < 3*60+15)) -eq 1 ]
' {} \; -print

在 bash、ksh93 或 zsh 中,您可以使用递归通配代替find.在ksh中,set -o globstar先运行。在 bash 中,shopt -s globstar首先运行。请注意,在 bash 中(但不在 ksh 或 zsh 中),**/通过目录的符号链接进行递归。

for f in /music/mp3/ebm/**/*.mp3; do
  d=$(soxi -D "$0")
  d=${d%.*} # truncate to an integer number of seconds (needed in bash only, ksh93 and zsh understand floating point numbers)
  if ((d >= 3*60 && d < 3*60+15)); then
    echo "$f"
  fi
done

答案3

使用ffmpeg

find . -name \*.mp3|while IFS= read -r l;do ffprobe -v 0 -i "$l" -show_streams|awk -F= '$1=="duration"&&$2>=180&&$2<=195'|read&&echo "$l";done

mp3info单行:

find . -name \*.mp3 -exec mp3info -p '%S %f\n' {} +|awk '$1>=180&&$1<=195'|cut -d' ' -f2-

或者在 OS X 中:

mdfind 'kMDItemDurationSeconds>=180&&kMDItemDurationSeconds<=195&&kMDItemContentType=public.mp3' -onlyin .

答案4

ffmpeg -i  yourmp3.mp3  2>&1 | grep Duration | sed 's/Duration: \(.*\), start/\1/g'  |awk {'print $1'}

使用上面的命令,您可以获得持续时间,因此您可以编写脚本来指定持续时间的域。您还可以使用:

find yourPath -iname "*mp3" -exec ffmpeg -i  {}   2>&1 | grep Duration | sed 's/Duration: \(.*\), start/\1/g'  |awk {'print $1'}

将 yourPath 替换为 mp3 存储库的根目录。

相关内容