ファイル名からタイムスタンプを抽出してmp3を分割する

ファイル名からタイムスタンプを抽出してmp3を分割する

私のフォルダにmp3ファイルがたくさんあります。カセットテープで録音され、個々のトラックを取り外す必要がありました。これはファイル名の1つです。

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の1つに基づいています。スクリプトは次のとおりです。

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

おすすめ記事