Как мне разделить FLAC с Cue?

Вопрос или проблема

У меня есть полный альбом в формате FLAC и файл CUE для него. Как я могу разделить это на треки в формате FLAC?

Я пользователь KDE, поэтому я предпочёл бы способ с использованием KDE/Qt. Я бы также хотел увидеть ответы с командной строки и другие графические интерфейсы, но они не являются моим предпочтительным методом.

Shnsplit может читать файл CUE напрямую, что также означает, что он может получить доступ к другим данным из файла CUE (не только к контрольным точкам) и генерировать более красивые имена файлов, чем split-*.flac:

shnsplit -f file.cue -t %n-%t -o flac file.flac

Конечно, это усложняет использование cuetag.sh, если оригинальный файл FLAC находится в той же директории.

Flacon — это интуитивный графический интерфейс с открытым исходным кодом, который делает именно это: разделяет FLAC с CUE.

Flacon извлекает отдельные треки из одного большого аудиофайла, содержащего весь альбом, и сохраняет их как отдельные аудиофайлы. Для этого он использует информацию из соответствующего файла CUE.

Он поддерживает, среди прочего:

Поддерживаемые форматы ввода: WAV, FLAC, APE, WavPack, True Audio (TTA).

Поддерживаемые форматы вывода: FLAC, WAV, WavPack, AAC, OGG или MP3.

Автоматическое определение кодировки для файлов CUE.

Чтобы использовать его, вам нужно просто открыть файл *.cue с Flacon. Затем он автоматически обнаружит большой файл *.flac (если нет, вы можете указать это вручную), затем вы должны выбрать формат вывода FLAC (и опционально настроить кодировщик) и начать процесс конвертации.

Flacon v5.4.0

Я знаю только способ через командную строку. Вам понадобятся cuetools и shntool.

cuebreakpoints file.cue | shnsplit -o flac file.flac
cuetag.sh file.cue "split-*".flac

если используются файлы высокого качества, shnsplit с удовольствием выдает ошибку с

shnsplit: error: формат m:ss.ff может быть использован только с файлами
с качеством CD

к счастью, бинарный файл flac поддерживает –skip=mm:ss.ss и –until=mm:ss.ss, так что скрипт может использовать cuebreakpoints следующим образом:

[..]
time[0]="00:00.00"
c=1
for ts in $(cuebreakpoints "${cue_file}"); do
    time[${c}]=${ts}
    c=$((c+1))
done
time[${c}]='-0'
for ((i=0;i<$((${#time[@]}-1));i++)); do
    trackno=$(($i+1))
    TRACKNUMBER="$(printf %02d ${trackno})"
    title="$(cueprint --track-number ${trackno} -t '%t' "${cue_file}")"
    flac --silent --exhaustive-model-search --skip=${time[$i]} --until=${time[$(($i+1))]} --tag=ARTIST="${ARTIST}" --tag=ALBUM="${ALBUM}" --tag=DATE="${DATE}" --tag=TITLE="${title}" --tag=TRACKNUMBER="${TRACKNUMBER}" "${aud_file}" --output-name="${TRACKNUMBER}-${title}.flac"
done

Если у вас установлен к параметрам типа файла k3b, k3b автоматически разделит файл, если вы откроете файл CUE и позволит вам повторно рипнуть.

Вот PHP-скрипт:

<?php
$s_cue = $argv[1];
$a_cue = file($s_cue);
$n_row = -1;
foreach ($a_cue as $s_row) {
   $s_trim = trim($s_row);
   $a_row = str_getcsv($s_trim, ' ');
   if (preg_match('/^FILE\s/', $s_row) == 1) {
      $s_file = $a_row[1];
   }
   if (preg_match('/^\s+TRACK\s/', $s_row) == 1) {
      $n_row++;
      $a_table[$n_row]['track'] = $a_row[1];
   }
   if (preg_match('/^\s+TITLE\s/', $s_row) == 1) {
      $a_table[$n_row]['title'] = $a_row[1];
   }
   if (preg_match('/^\s+PERFORMER\s/', $s_row) == 1) {
      $a_table[$n_row]['artist'] = $a_row[1];
   }
   if (preg_match('/^\s+INDEX\s/', $s_row) == 1) {
      $s_dur = $a_row[2];
      $a_frame = sscanf($s_dur, '%d:%d:%d', $n_min, $n_sec, $n_fra);
      $n_index = $n_min * 60 + $n_sec + $n_fra / 75;
      $a_table[$n_row]['ss'] = $n_index;
      if ($n_row > 0) {
         $a_table[$n_row - 1]['to'] = $n_index;
      }
   }
}
$a_table[$n_row]['to'] = 10 * 60 * 60;
foreach ($a_table as $m_row) {
   $a_cmd = [
      'ffmpeg',
      '-i', $s_file,
      '-ss', $m_row['ss'],
      '-to', $m_row['to'],
      '-metadata', 'artist=" . $m_row["artist"],
      '-metadata', 'title=" . $m_row["title"],
      '-metadata', 'track=' . $m_row['track'],
      $m_row['track'] . ' ' . $m_row['title'] . '.m4a'
   ];
   $a_esc = array_map('escapeshellarg', $a_cmd);
   $s_esc = implode(' ', $a_esc);
   system($s_esc);
}

Существует проект, который работает с несколькими входными файлами: split2flac

Из описания проекта:

split2flac разделяет один большой аудиообраз APE/FLAC/TTA/WV/WAV (или
коллекцию таких файлов, рекурсивно) с CUE-листом на
треки FLAC/M4A/MP3/OGG_VORBIS/WAV с тегированием, переименованием,
конвертацией кодировки CUE-листа, изображениями обложек альбомов. Он также использует
конфигурационный файл, так что нет необходимости передавать много аргументов каждый раз,
только входной файл. Должен работать в любой POSIX-совместимой оболочке.

unflac автоматически разделяет на flac и также правильно выполняет тегирование!

Вам нужно установить go, а затем запустить его, указав cue в качестве входного: ~/go/bin/unflac filename.cue.

Я узнал об этом после того, как файлы, которые я разделил с другими инструментами, не воспроизводились.

Я обнаружил, что mac (что является командой, которую shntool использовал для декодирования APE-файлов) гораздо менее терпим к незначительным ошибкам в исходном файле, чем ffmpeg.

Обычно ffmpeg по-прежнему полностью конвертирует файл, в то время как mac, скорее всего, выдаст ошибку во время обработки.

Поэтому я в конечном итоге написал скрипт для разделения APE-файла, разбирая файл CUE и конвертируя APE в файлов FLAC, отделенных по заголовкам, с использованием ffmpeg:

#!/usr/bin/env python2.7

import subprocess as subp
import sys
import os
from os.path import splitext, basename
import random
import glob

records = []
filename = ""
album=''
alb_artist=""
codec="flac"
ffmpeg_exec="ffmpeg"
encodingList = ('utf-8','euc-kr', 'shift-jis', 'cp936', 'big5')

filecontent = open(sys.argv[1]).read()
for enc in encodingList:
    try:
        lines = filecontent.decode(enc).split('\n')
        encoding = enc
        break
    except UnicodeDecodeError as e:
        if enc == encodingList[-1]:
            raise e
        else:
            pass

for l in lines:
    a = l.split()
    if not a:
        continue
    if a[0] == "FILE":
        filename=" ".join(a[1:-1]).strip('\'"')
    elif a[0]=='TRACK':
        records.append({})
        records[-1]['index'] = a[1]
    elif a[0]=='TITLE':
        if len(records)>0:
            records[-1]['title'] = ' '.join(a[1:]).strip('\'"')
        else:
            album =  ' '.join(a[1:]).strip('\'"')
    elif a[0]=='INDEX' and a[1]=='01':
        timea = a[2].split(':')
        if len(timea) == 3 and int(timea[0]) >= 60:
            timea.insert(0, str(int(timea[0])/60))
            timea[1] = str(int(timea[1])%60)
        times="{0}.{1}".format(':'.join(timea[:-1]), timea[-1])
        records[-1]['start'] = times
    elif a[0]=='PERFORMER':
        if len(records)>1:
            records[-1]['artist'] = ' '.join(a[1:]).strip('\'"')
        else:
            alb_artist=" ".join(a[1:]).strip('\'"')

for i, j in enumerate(records):
    try:
        j['stop'] = records[i+1]['start']
    except IndexError:
        pass

if not os.path.isfile(filename):
    tmpname = splitext(basename(sys.argv[1]))[0]+splitext(filename)[1]
    if os.path.exists(tmpname):
        filename = tmpname
        del tmpname
    else:
        for ext in ('.ape', '.flac', '.wav', '.mp3'):
            tmpname = splitext(filename)[0] + ext
            if os.path.exists(tmpname):
                filename = tmpname
                break

if not os.path.isfile(filename):
    raise IOError("Не удается найти файл: {0}".format(filename))

fstat = os.stat(filename)
atime = fstat.st_atime
mtime = fstat.st_mtime

records[-1]['stop'] = '99:59:59'

if filename.lower().endswith('.flac'):
    tmpfile = filename
else:
    tmpfile = splitext(filename)[0] + str(random.randint(10000,90000)) + '.flac'

try:
    if filename != tmpfile:
        ret = subp.call([ffmpeg_exec, '-hide_banner', '-y', '-i', filename, 
            '-c:a', codec,'-compression_level','12','-f','flac',tmpfile])

        if ret != 0:
            raise SystemExit('Конвертация не удалась.')

    for i in records:
        output = i['index'] +' - '+ i['title']+'.flac'
        commandline = [ffmpeg_exec, '-hide_banner', 
        '-y', '-i', tmpfile,
        '-c', 'copy', 
        '-ss', i['start'], '-to', i['stop'],
        '-metadata', u'title={0}'.format(i['title']), 
        '-metadata', u'artist={0}'.format(i.get('artist', '')),
        '-metadata', u'performer={0}'.format(i.get('artist', '')),
        '-metadata', u'album={0}'.format(album), 
        '-metadata', 'track={0}/{1}'.format(i['index'], len(records)), 
        '-metadata', u'album_artist={0}'.format(alb_artist), 
        '-metadata', u'composer={0}'.format(alb_artist), 
        '-metadata', 'encoder=Meow', 
        '-write_id3v1', '1', 
        output]
        ret = subp.call(commandline)
        if ret == 0:
            os.utime(output, (atime, mtime))
finally:
    if os.path.isfile(tmpfile):
        os.remove(tmpfile)

shntool на Ubuntu 14.04

shntool отсутствует зависимость исполняемого файла mac (Monkey’s Audio Console), и единственный пакет, который я смог найти, находился в PPA flacon:

sudo add-apt-repository -y ppa:flacon
sudo apt-get update
sudo apt-get install -y flacon shntool
shntool split -f *.cue -o flac -t '%n - %p - %t' *.ape

flacon — это графический интерфейс для shntool, но он поставляется со всеми необходимыми ему кодеками… иначе я получал ошибку:

shnsplit: warning: не удалось прочитать данные из входного файла, используя формат: [ape]
shnsplit:          + возможно, у вас нет разрешения на чтение файла: [example.ape]
shnsplit:          + аргументы могут быть неверными для декодера: [mac]
shnsplit:          + проверьте, что декодер установлен и в вашем PATH
shnsplit:          + этот файл может быть неподдерживаемым, усеченным или поврежденным
shnsplit: error: не удается продолжить из-за вышеуказанных ошибок

Foobar2000 доступен в виде snap, так что мы можем добавить его в список решений. Это работает как для разделения существующего flac, так и для разделения другого безпотерянутого файла и сохранения в flac.

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

Ответ или решение

Чтобы разделить файл FLAC на отдельные треки с использованием файла CUE, существует множество методов, включая как графические интерфейсы, так и командные строки. В данном ответе подробно рассмотрим несколько подходов, подходящих для пользователей KDE, а также другие доступные решения.

Использование графических интерфейсов

  1. Flacon:
    Flacon — это простой в использовании графический интерфейс, специальное приложение для извлечения отдельных треков из больших аудиофайлов, таких как FLAC, используя информацию из CUE-файла.

    • Установка: Для установки Flacon в Ubuntu:
      sudo add-apt-repository ppa:flacon
      sudo apt-get update
      sudo apt-get install flacon
    • Использование: Откройте файл CUE с помощью Flacon. Программа автоматически обнаружит связанный файл FLAC. Выберите формат вывода (например, FLAC) и нажмите на кнопку для начала процесса.
  2. K3b:
    Если вы используете K3b, вы можете автоматически разделить файл. Просто откройте CUE-файл в K3b, и программа предложит вам возможность перерипать аудиотрек с разделением на треки.

Использование командной строки

  1. shnsplit и cuetools:
    Эти инструменты позволяют разбивать файлы CUE напрямую:

    shnsplit -f file.cue -t %n-%t -o flac file.flac

    Первый параметр указывает на CUE-файл, а -t %n-%t используется для задания формата именования выходных файлов (номер трека и его название).

    Если высшее качество файлов, возможно, придется обрабатывать их с помощью flac с опциями --skip и --until:

    cuebreakpoints file.cue | shnsplit -o flac file.flac
    cuetag.sh file.cue "split-*".flac
  2. Использование ffmpeg через скрипт:
    Можно также написать Bash или Python-скрипт, использующий ffmpeg для более гибкого разделения:

    #!/bin/bash
    cue_file="yourfile.cue"
    flac_file="yourfile.flac"
    
    time[0]="00:00.00"
    c=1
    for ts in $(cuebreakpoints "${cue_file}"); do
       time[${c}]=${ts}
       c=$((c+1))
    done
    time[${c}]='-0'
    for ((i=0;i<$((${#time[@]}-1));i++)); do
       trackno=$(($i+1))
       title="$(cueprint --track-number ${trackno} -t '%t' "${cue_file}")"
       flac --silent --skip=${time[$i]} --until=${time[$(($i+1))]} --tag=ARTIST="${ARTIST}" --tag=ALBUM="${ALBUM}" --tag=DATE="${DATE}" --tag=TITLE="${title}" --tag=TRACKNUMBER=${trackno} "${flac_file}" --output-name="${trackno}-${title}.flac"
    done
  3. split2flac:
    Еще одно отличное решение для разделения файлов:

    git clone https://github.com/ftrvxmtrx/split2flac.git
    cd split2flac
    ./split2flac.sh yourfile.cue

Использование unflac

Так же существует проект unflac, который позволяет автоматически разделять файлы FLAC, также осуществляя оформление тегов.
Установка:

   go get -u github.com/ftrvxmtrx/unflac

Используйте команду:

   ~/go/bin/unflac filename.cue

Заключение

Выбор метода зависит от ваших предпочтений — используете ли вы графические интерфейсы или предпочитаете командную строку. Как графическое, так и командное решение могут быть эффективными для разделения аудиофайлов с CUE. Flacon и K3b обеспечивают наилучший опыт для пользователей с графическим интерфейсом, в то время как shnsplit, ffmpeg и unflac предоставляют мощные инструменты для технических пользователей.

Если у вас возникнут дополнительные вопросы или вам потребуется помощь, не стесняйтесь обращаться для консультаций!

Оцените материал
Добавить комментарий

Капча загружается...