¿Cómo paso de .flac a .mp3 usando LAME y FLAC usando solo la Terminal?

27

Durante mucho tiempo he estado usando una técnica torpe relativa que involucra a Audacity con un complemento LAME. Supongo que esto está bien, pero el atractivo del enfoque de Terminal Server es que puedo ser un poco más detallado con mi [options] y tal vez usar binarios más actualizados.

Además, mi MacBook está envejeciendo un poco ahora y si puedo deshacerme de una GUI innecesaria, mucho mejor.

Gracias de antemano.

    
pregunta boehj 24.02.2011 - 06:43

4 respuestas

38

Convertir un solo archivo sin conservar las etiquetas

brew install lame
flac --decode --stdout test.flac | lame --preset extreme - test.mp3

Un script de shell que conserva algunas etiquetas 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

Para usar el script, simplemente guárdalo en algún lugar como ~/bin/flac2mp3 y hazlo ejecutable con chmod +x ~/bin/flac2mp3 .

Esto convertiría todos los archivos flac en tu carpeta de Música:

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

O un poco más rápido, ya que solo llama a flac2mp3 una vez:

find ~/Music/ -name '*.flac' -print0 | xargs -0 ~/bin/flac2mp3
    
respondido por el boehj 24.02.2011 - 10:51
10

ffmpeg conservaría las etiquetas (pero no cubrirá el arte) de forma predeterminada.

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

-aq 1 corresponde a -V 1 en lame. -acodec libfaac convertiría los archivos a AAC:

for f in *.flac; do ffmpeg -i "$f" -acodec libfaac -aq 200 "${f%flac}m4a"; done
    
respondido por el user495470 28.01.2013 - 11:57
3

Tomé lo que tenían, pero luego lo hice correr más rápido usando xargs para paralelizar los trabajos.

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

Entonces este es el script de arriba     / 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

y aquí tiene algunas estadísticas para la aceleración del rendimiento mediante el paralelismo.

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

puede ver que también utilizó mis CPU de manera más efectiva, tengo un intel i7, por lo que 8 es probablemente el número correcto de procesos.

    
respondido por el Jake Plimack 29.07.2017 - 21:10
2

Encontré este hilo al intentar realizar una codificación directa de archivos MP3 desde archivos fuente de FLAC. La respuesta de Boehj proporciona una opción de script decente, pero personalmente prefiero usar FFmpeg, así que este es el script de Bash que vine con para manejar esta tarea. Probado y funciona muy bien en macOS Sierra (10.12.2).

Requisitos: Debes tener ffmpeg y lame ya instalados en tu Mac. La forma más fácil de hacerlo es a través de Homebrew. Primero asegúrese de tener Homebrew instalado de esta manera:

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

Luego ejecuta este comando para instalar ffmpeg y lame :

brew install ffmpeg lame

Una vez hecho esto, ya está listo para ejecutar este script. Este script buscará los archivos FLAC en el directorio path/to/FLAC/files , pero se puede cambiar para que simplemente sea . si los archivos FLAC están en el mismo directorio en el que está ejecutando este script. Cuando se ejecute, se creará un mp3/ subdirectorio donde se colocarán todos los archivos MP3.

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

Algunas notas sobre cosas que aprendí "The Hard Way ™" para que otros puedan beneficiarse de lo que hice de manera diferente en este script en comparación con otras en Internet.

  • Los comandos grep para el análisis de etiquetas (usando FFprobe que se instala con FFmpeg) no distinguen entre mayúsculas y minúsculas al utilizar -i Opción para hacer que sea grep -i .
  • El siguiente comando cut ahora está limitado a dividir la salida solo en base al primer = en un nombre de etiqueta con la opción -f 2- que hace el comando cut -d '=' -f 2- . Por ejemplo, Pavement tiene una canción titulada "5-4 = Unidad" y si solo es la segunda parte se seleccionaron por corte y ese título se habría truncado a "5-4".
  • Para los números de pista y total de pistas, agregué una canalización adicional a sed que elimina los ceros iniciales: sed 's/^0*//' .
  • En scripts similares en Internet, la salida de FFmpeg es algo así como -f wav y eso en realidad comprimiría la salida de FFmpeg, lo cual no tiene sentido en una configuración de tubería donde LAME lo va a recodificar. En su lugar, la salida aquí se establece en -f s16le -acodec pcm_s16le , que es básicamente una salida RAW; perfecto para canalizar audio a otro proceso como este.
  • Para lidiar con la salida RAW en el lado LAME de la tubería, tuve que agregar la opción -r .
  • También tenga en cuenta las opciones de etiqueta --tt , --ta , --tl , --tn y --tg ID3v2 para LAME. Cuando el audio se transmite / canaliza desde un proceso a LAME, los metadatos del archivo fuente se pierden. Una opción sugerida es hacer que FFmpeg guarde los metadatos en un archivo de texto configurando la opción con -f ffmetadata "[metadata filename here]" y luego ejecutando FFmpeg nuevamente con algo como esto: -i "[metadata filename here]" -map_metadata 1 -c:a copy [destination mp3 file] id3v2_version 3 -write_id3v1 1 . Eso funciona, pero tenga en cuenta el requisito de un archivo de destino. Parece que FFmpeg solo importa metadatos cuando puede copiar el archivo, lo que parece un proceso muy inútil. Usar FFprobe para obtener valores y luego establecerlos en LAME con las opciones --tt , --ta , --tl , --tn y --tg funciona mejor; todos los metadatos están escritos en su lugar, por lo que se debe generar un archivo duplicado.
respondido por el JakeGould 02.01.2017 - 04:33

Lea otras preguntas en las etiquetas