从文件名中提取时间戳以分割 mp3

从文件名中提取时间戳以分割 mp3

我的文件夹中有一堆 mp3 文件。它们是从盒式磁带录制的,并且需要将各个轨道分开。这是文件名之一:

Gobbolino the Witch's Cat, 10:52 The Hare & Tortoise, 14:52 The Shoe Tree, 24:22 The Emperors New Clothes, 34:11 The Red Nightcaps, 37:07 Aldo in Arcadia (1), 40:37 The Forest Troll.mp3

您可以看到它的文件名中有时间戳,指示每个曲目的开始。第一个曲目没有时间戳,因为它始终从 00:00 开始。最后一首曲目应始终位于 mp3 的末尾。不知何故,我想提取这些时间戳以便创建单独的文件。

如果上面的文件被正确分割,输出将是:

Gobbolino the Witch's Cat.mp3
The Hare & Tortoise.mp3
The Shoe Tree.mp3
The Emperors New Clothes.mp3
The Red Nightcaps.mp3
Aldo in Arcadia (1).mp3
The Forest Troll.mp3

我知道如何循环文件,以及如何使用 ffmpeg 剪切文件,但我不知道如何从文件名中提取时间戳和轨道名称。我正在使用 zsh,这是我当前的代码:

for file in *; do
  if [[ -f "$file" ]]; then
    # extract timestamps and loop thru, for each timestamped section
    ffmpeg -ss TIMESTAMP_START -to TIMESTAMP_END -I "$file" -acodec copy TRACK_NAME.mp3
  fi
done

更新

我对这个问题的规范已经改变。文件名如下所示:

Tape 1 - Gobbolino the Witch's Cat, 11-06 The Hare & Tortoise, 14-25 The Shoe Tree, 24-06 The Emperors New Clothes, 34-27 The Red Nightcaps, 37-29 Aldo in Arcadia (1), 40-40 The Forest Troll.mp3

即它的开头有一个专辑名称,时间戳中有连字符而不是冒号(macOS 中文件名不能有冒号)。另外,我想在文件中插入一些 mp3 标签,并将每个专辑的曲目放入其自己的专辑文件夹中。

我的解决方案基于下面的 Gilles 之一。该脚本如下所示:

setopt interactive_comments
for file in *(.); do
    extension=$file:e
    rest=$file:r
    timestamp_start=0:00
    timestamp_duration=$(ffprobe -i "$file"  -show_entries format=duration -v quiet -of csv="p=0" -sexagesimal -sexagesimal)
    timestamp_duration=${timestamp_duration%.*}
    tracknum=1
    while [[ $rest =~ ,\ *([0-9:]+-[0-9][0-9])\ * ]]; do
        track_name="$rest[1,$MBEGIN-1]"
        if [[ "$track_name" == *"Tape "* ]]; then
       albumname="${track_name%% - *}"
           track_name="${track_name#* - }"
           echo "\n\nALBUM NAME $albumname\n"
           mkdir $albumname
        fi
        rest=$rest[$MEND+1,-1]
        timestamp_end=$match[1]
        timestamp_end="${timestamp_end//-/:}"

    # echo "$timestamp_start $timestamp_end $track_name.$extension"
        ffmpeg -ss $timestamp_start -to $timestamp_end -i $file -acodec libmp3lame -ac 2 -ab 256k -ar 44100 -metadata album="$albumname" -metadata title="$track_name" -metadata track="$tracknum" $track_name.$extension
        mv $track_name.$extension $albumname
        timestamp_start=$timestamp_end
        tracknum=$((tracknum+1))
        last_track_name="$rest:r"
    done
    if [[ -n $timestamp_end ]]; then
        # echo "$timestamp_start $timestamp_duration $last_track_name.$extension"
        ffmpeg -ss $timestamp_start -to $timestamp_duration -i $file -acodec libmp3lame -ac 2 -ab 256k -ar 44100 -metadata album="$albumname" -metadata title="$last_track_name" -metadata track="$tracknum" $last_track_name.$extension
        mv $last_track_name.$extension $albumname
    fi
done

答案1

使用正则表达式对文件名进行循环来匹配轨道分隔符=~ 条件表达式运算符。正则表达式,\ *([0-9:]+:[0-9][0-9])\ *匹配一个逗号,后跟一个时间戳,周围有可选空格。

$file:e$file:r通过提取文件扩展名历史修正

不要循环遍历所有文件然后仅匹配常规文件,而是使用全局限定符仅匹配常规文件。

for file in *(.); do
    extension=$file:e
    rest=$file:r
    timestamp_start=0:00
    timestamp_end=
    while [[ $rest =~ ,\ *([0-9:]+:[0-9][0-9])\ * ]]; do
        track_name=$rest[1,$MBEGIN-1]
        rest=$rest[$MEND+1,-1]
        timestamp_end=$match[1]
        ffmpeg -ss $timestamp_start -to $timestamp_end -I $file -acodec copy $track_name.$extension
        timestamp_start=$timestamp_end
    done
    if [[ -n $timestamp_end ]]; then
        ffmpeg -ss $timestamp_end -I $file -acodec copy $rest.$extension
    else
        : # If you want special processing for single-track files, it goes here.
    fi
done

答案2

 awk -F "," '{for(i=1;i<=NF;i++){gsub(/[0-9]{2}:[0-9]{2}/,"",$i);gsub(/^[[:space:]]*/,"",$i);print $i".mp3"}}' file.txt

输出

Gobbolino the Witch's Cat.mp3
The Hare & Tortoise.mp3
The Shoe Tree.mp3
The Emperors New Clothes.mp3
The Red Nightcaps.mp3
Aldo in Arcadia (1).mp3
The Forest Troll.mp3.mp3

相关内容