Jak przejść z .flac do .mp3 przy użyciu LAME i FLAC przy użyciu samego terminala?


31

Od dłuższego czasu stosuję względnie niezdarną technikę, która obejmuje Audacity z wtyczką LAME. Myślę, że to w porządku, ale atrakcyjność podejścia terminalowego polega na tym, że mogę być trochę bardziej precyzyjny [options]i być może używać bardziej aktualnych plików binarnych.

Co więcej, mój MacBook trochę się starzeje i jeśli mogę pozbyć się niepotrzebnego GUI, tym lepiej.

Z góry dziękuję.


1
dostaniesz za to punkty;)
Mortimer

Haha ... Odpowiedziałem na pytanie, ale mówi, że nie mogę potwierdzić mojej odpowiedzi przez dwa dni. Przepraszam. Nadal zastanawiam się, jak tu się wszystko dzieje. Świetna strona. : D
boehj

Odpowiedzi:


41

Konwertowanie pojedynczego pliku bez zachowania znaczników

brew install lame
flac --decode --stdout test.flac | lame --preset extreme - test.mp3
  • --decode --stdout = -dc
  • lame - $outfile = dane wejściowe z STDIN
  • --preset extreme= ~ 245 kbit / s VBR

Skrypt powłoki, który zachowuje niektóre tagi ID3

#!/bin/bash

for f in "$@"; do
    [[ "$f" != *.flac ]] && continue
    album="$(metaflac --show-tag=album "$f" | sed 's/[^=]*=//')"
    artist="$(metaflac --show-tag=artist "$f" | sed 's/[^=]*=//')"
    date="$(metaflac --show-tag=date "$f" | sed 's/[^=]*=//')"
    title="$(metaflac --show-tag=title "$f" | sed 's/[^=]*=//')"
    year="$(metaflac --show-tag=date "$f" | sed 's/[^=]*=//')"
    genre="$(metaflac --show-tag=genre "$f" | sed 's/[^=]*=//')"
    tracknumber="$(metaflac --show-tag=tracknumber "$f" | sed 's/[^=]*=//')"

    flac --decode --stdout "$f" | lame --preset extreme --add-id3v2 --tt "$title" --ta "$artist" --tl "$album" --ty "$year" --tn "$tracknumber" --tg "$genre" - "${f%.flac}.mp3"
done

Aby użyć skryptu, po prostu zapisz go gdzieś tak, ~/bin/flac2mp3aby był wykonywalny chmod +x ~/bin/flac2mp3.

Spowodowałoby to konwersję wszystkich plików flac w folderze Muzyka:

find ~/Music/ -name '*.flac' -exec ~/bin/flac2mp3 {} \;

Lub nieco szybciej, ponieważ wywołuje flac2mp3 tylko raz:

find ~/Music/ -name '*.flac' -print0 | xargs -0 ~/bin/flac2mp3

2
Powinieneś opublikować odpowiedź tutaj, a nie odniesienie do tekstu w pytaniu. IMHO, powinieneś edytować zarówno pytanie, jak i odpowiedź i przenieść tutaj wniosek.
lpacheco

Ok zrobi sie. Przepraszam.
boehj

2
${file%.flac}.mp3jest niesamowite! Wcześniej ${x:: ${#x}-3}m4aużywałem do zmiany nazwy pliku z .wav na .m4a. Wspaniale jest zobaczyć sposób, który wygląda o wiele łatwiej.
Jason Salaz

1
Wygląda na to, że w Opcji 3 występuje błąd. Prawdopodobnie z powodu słabej wersji, ale bieżący kod nie mówi osobie, że powinien używać strumienia wejściowego jako pliku wejściowego, a także pliku wyjściowego nie jest określony, ponieważ używany jest strumień, jest on niezbędny. Dla mnie ostateczny kod to: !/bin/sh file="$1" outfile=${file%.flac}.mp3 eval $(metaflac --export-tags-to - "$file" | sed "s/=\(.*\)/='\1'/") flac -cd "$file" | lame --preset standard \ --add-id3v2 --tt "$TITLE" --ta "$ARTIST" --tl "$ALBUM" \ --ty "$DATE" --tn "$TRACKNUMBER" --tg "$GENRE" \ - "$outfile"
Mehal

Miło jest też stworzyć skrypt, który wykonuje te czynności „znajdowania” ...
Mehal

10

ffmpeg domyślnie zachowuje tagi (ale nie obejmuje grafiki).

for f in *.flac; do ffmpeg -i "$f" -aq 1 "${f%flac}mp3"; done

-aq 1odpowiada -V 1lame. -acodec libfaacprzekonwertuje pliki do AAC:

for f in *.flac; do ffmpeg -i "$f" -acodec libfaac -aq 200 "${f%flac}m4a"; done

Właśnie to zrobiłem i powiedziałem: `` Metadane: komentarz: Koder okładki (z przodu): Lavc57.107.100 png `` Wyszukiwarka macOS pokazuje okładkę. ffmpeg 3.4.2 z naparu.
Habbie

Potem zdałem sobie sprawę, że mój ffmpeg jest bardzo stary. Uaktualniłem go do 4.1.3 z tym samym rezultatem - pliki mp3 tego samego rozmiaru, z działającą okładką.
Habbie

4

wziąłem to, co mieliście, ale potem sprawiłem, że działało to jeszcze szybciej, wykorzystując xargsrównoległe zadania.

find <directory> -name '*.flac' -print0 | xargs -0 -P8 -n1  /usr/local/bin/flac2mp3

To jest skrypt z góry / usr / local / bin / flac2mp3

#!/usr/bin/env bash

for f in "$@"; do
  [[ "$f" != *.flac ]] && continue
  album="$(metaflac --show-tag=album "$f" | sed 's/[^=]*=//')"
  artist="$(metaflac --show-tag=artist "$f" | sed 's/[^=]*=//')"
  date="$(metaflac --show-tag=date "$f" | sed 's/[^=]*=//')"
  title="$(metaflac --show-tag=title "$f" | sed 's/[^=]*=//')"
  year="$(metaflac --show-tag=date "$f" | sed 's/[^=]*=//')"
  genre="$(metaflac --show-tag=genre "$f" | sed 's/[^=]*=//')"
  tracknumber="$(metaflac --show-tag=tracknumber "$f" | sed 's/[^=]*=//')"

  flac --decode --stdout "$f" \ 
         | lame --preset extreme \
                --add-id3v2 \
                 --tt "$title" \
                 --ta "$artist" \
                 --tl "$album" \
                 --ty "$year" \
                 --tn "$tracknumber" \
                 --tg "$genre" \
                 - "${f%.flac}.mp3"
done

i oto niektóre statystyki przyspieszenia wydajności przy użyciu równoległości.

find <dirOfFlac24s> -name '*.flac -print0 | xargs -0 -P8 -n1 /usr/local/bin/flac2mp320  

0.00s user 0.00s system 60% cpu 0.002 total
115.94s user 1.40s system 359% cpu 32.655 total

time /usr/local/bin/flac2mp320 <dirOfFlac24s>/*.flac
96.63s user 1.46s system 109% cpu 1:29.98 total

widać, że bardziej efektywnie wykorzystuje moje procesory, mam Intel i7, więc 8 to prawdopodobnie odpowiednia liczba procesów.


2

Znalazłem ten wątek podczas próby bezpośredniego kodowania plików MP3 z plików źródłowych FLAC. Odpowiedź Boehja zapewnia przyzwoitą opcję skryptową, ale ja osobiście wolę używać FFmpeg, więc jest to skrypt Bash, który wymyśliłem, aby poradzić sobie z tym zadaniem. Testowane i działa świetnie w macOS Sierra (10.12.2).

Wymagania: Powinieneś mieć ffmpegi lamejuż zainstalować na komputerze Mac. Najłatwiej to zrobić za pomocą Homebrew. Najpierw upewnij się, że masz zainstalowany Homebrew w ten sposób:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Następnie uruchom to polecenie, aby zainstalować ffmpegi lame:

brew install ffmpeg lame

Po zakończeniu możesz uruchomić ten skrypt. Ten skrypt będzie szukał plików FLAC w katalogu, path/to/FLAC/filesale można to zmienić tak, aby .pliki FLAC znajdowały się w tym samym katalogu, w którym uruchamiany jest ten skrypt. Po uruchomieniu utworzy mp3/podkatalog, w którym wszystkie pliki MP3 będą umieszczony.

find -E "path/to/FLAC/files" -type f -iregex ".*\.(FLAC)$" |\
  while read full_audio_filepath
  do

    # Break up the full audio filepath stuff into different directory and filename components.
    audio_dirname=$(dirname "${full_audio_filepath}");
    audio_basename=$(basename "${full_audio_filepath}");
    audio_filename="${audio_basename%.*}";
    # audio_extension="${audio_basename##*.}";

    # Set the MP3
    mp3_dirpath="${audio_dirname}/mp3";
    mp3_filepath="${mp3_dirpath}/${audio_filename}.mp3";

    # Create the child MP3 directory.
    mkdir -p "${mp3_dirpath}";

    # Get the track metadata.
    mp3_title=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:TITLE= | cut -d '=' -f 2- );
    mp3_artist=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:ARTIST= | cut -d '=' -f 2- );
    mp3_album=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:ALBUM= | cut -d '=' -f 2- );
    mp3_year=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:YEAR= | cut -d '=' -f 2- );
    mp3_track=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:TRACK= | cut -d '=' -f 2- | sed 's/^0*//' );
    mp3_tracktotal=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:TRACKTOTAL= | cut -d '=' -f 2- | sed 's/^0*//' );
    mp3_genre=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:GENRE= | cut -d '=' -f 2- );

    # Where the magic happens.
    ffmpeg -y -v quiet -nostdin -i "${full_audio_filepath}" -ar 44100 -sample_fmt s16 -ac 2 -f s16le -acodec pcm_s16le - | \
      lame --quiet --add-id3v2 --pad-id3v2 --tt "${mp3_title}" --ta "${mp3_artist}" --tl "${mp3_album}" --tn "${mp3_track}"/"${mp3_tracktotal}" --tg "${mp3_genre}" -r -m s --lowpass 19.7 -V 3 --vbr-new -q 0 -b 96 --scale 0.99 --athaa-sensitivity 1 - "${mp3_filepath}";

  done

Kilka notatek o rzeczach, których nauczyłem się „The Hard Way ™”, aby inni mogli czerpać korzyści z tego, co zrobiłem inaczej w tym skrypcie w porównaniu do innych w Internecie.

  • Te grepkomendy dla tagu parsowania (używając FFprobe którym jest zainstalowany z FFmpeg) są wrażliwe na wielkość liter przy użyciu -iopcji, aby go grep -i.
  • Następujące cutpolecenie jest teraz ograniczone do dzielenia danych wyjściowych tylko na podstawie pierwszego =w nazwie znacznika z -f 2-opcją, która tworzy polecenie cut -d '=' -f 2-. Na przykład, Pavement ma utwór zatytułowany „5-4 = Unity”, a gdyby tylko drugi fragment został wybrany przez cięcie, tytuł zostałby skrócony do „5-4”.
  • Na torze-torowych i całkowitych numerami dodałem dodatkową rurę sed, która pozbywa zer wiodących: sed 's/^0*//'.
  • W podobnych skryptach w Internecie wyjście FFmpeg jest czymś podobnym -f wavi faktycznie kompresuje wyjście FFmpeg, co nie ma sensu w konfiguracji potoku, w której LAME zamierza go ponownie zakodować. Zamiast tego ustawia się tutaj wyjście, -f s16le -acodec pcm_s16lektóre jest zasadniczo wyjściem RAW; idealny do przesyłania dźwięku do innego procesu takiego jak ten.
  • Aby poradzić sobie z danymi wyjściowymi RAW po stronie LAME rury, musiałem dodać -ropcję.
  • Należy również pamiętać --tt, --ta, --tl, --tni --tgID3v2 opcji znacznik do LAME. Gdy dźwięk jest przesyłany strumieniowo / przesyłany strumieniowo z jednego procesu do LAME, metadane z pliku źródłowego są tracone. Jednym z sugerowanych opcji jest uzyskanie FFmpeg zapisać metadane w pliku tekstowym poprzez ustawienie opcji z -f ffmetadata "[metadata filename here]"czym działa FFmpeg znowu z czymś takim: -i "[metadata filename here]" -map_metadata 1 -c:a copy [destination mp3 file] id3v2_version 3 -write_id3v1 1. To działa, ale zwróć uwagę na wymaganie dotyczące pliku docelowego. Wydaje się, że FFmpeg importuje metadane tylko wtedy, gdy może skopiować plik, co wydaje się bardzo marnotrawstwem. Korzystanie FFprobe uzyskać wartości, a następnie ustawiając je w LAME z --tt, --ta, --tl, --tni --tgopcje działa lepiej; wszystkie metadane są zapisane w miejscu, dlatego należy wygenerować duplikat pliku.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.