Quero copiar / arquivar toda a minha coleção de música em um formato de arquivo sem perdas, mas compactado, ou seja, os arquivos devem ser perfeitos , representações sem perdas dos dados originais, mas devem consumir menos espaço do que WAV (E) não compactado.

WAV (E) é proibido, uma vez que é não-gratuito (material proprietário da Microsoft), a compactação de plataforma cruzada é complicada ou impossível e o tamanho do arquivo está limitado a 4 GB. Portanto, escolhi FLAC (Free Lossless Audio Codec).

Como digitalizar uma coleção inteira é uma tarefa gigantesca e o FLAC oferece 9 níveis de compactação (0 a 8), aí vem a pergunta de ouro :

Qual nível de compressão devo escolher sabiamente?

Comentários

  • esta pergunta não ‘ não aborda o design de som, mas aborda uma escolha que alguns designers de som enfrentam, que é, como lidar da melhor forma com nossas bibliotecas cada vez maiores de gravações. Pessoalmente, eu ‘ estou mudando o FLAC para WAVE simplesmente por causa do problema de armazenamento, mas ‘ receio não ‘ não ter nenhuma idéia do nível de compressão.
  • Curiosamente, postei isso em Música primeiro, mas as pessoas recomendaram movê-lo para Sound Design.

Resposta

Os níveis de compressão FLAC são (apenas) uma troca entre tempo de codificação e tamanho do arquivo . O tempo de decodificação é praticamente independente da taxa de compressão. A seguir, vou me referir aos níveis de compressão 0, …, 8 como FLAC-0, …, FLAC-8.

Resumindo : Eu recomendo FLAC-4 !


As soluções fáceis

Obviamente:

  • Se eu não me importar com a codificação de tempo e como espaço é dinheiro, utilizo o nível de compactação mais alto FLAC-8 .

  • Se eu não me importo com espaço, mas quero resolver isso o mais rápido possível, uso o nível de compressão mais baixo FLAC-0 .


A solução difícil

Onde está o meio certo entre o tamanho do arquivo e o tempo de codificação? Me deparei com o artigo de Nathan Zachary sobre esta questão, mas ele compara apenas dois arquivos, codifica-os apenas uma vez (o tempo de codificação varia enormemente de acordo com a carga secundária do computador ) e as tabelas são difíceis de ler em comparação com os gráficos.

Então, inspirado nisso, refiz suas medidas com cinco álbuns completos cada um em um gênero diferente e codificou cada arquivo / faixa 10 vezes .

Procedimento:

  • Copiar álbum com abcde e configurações adequadas cdparanoia configurações para WAV não compactado.
  • Converta cada arquivo 10 vezes para cada nível de compactação (FLAC-0 para FLAC-8) e obtenha o tempo médio de codificação em relação a FLAC-0 e o tamanho do arquivo em relação a F LAC-0 .
    • Para isso, desativei a conexão com a Internet, todos os trabalhos periódicos (cronjobs) e quase tudo o mais, de modo que, na maioria das vezes, a compressão é executada e o menos possível interfere. li>

Esta medida deve ser bastante independente do hardware usado. Usei flac versão 1.3.2 no Arch Linux usando flac <infile> --compression-level-X -f -o flacX.flac.

Eficiência

Se você multiplicar tamanho relativo com o tempo relativo de codificação / compressão , você obtém um valor pela maldade . Mas como essa maldade é governada principalmente pelo tempo relativo, os gráficos se sobrepõem amplamente. Então, para esclarecer o gráfico, apenas espelhei a maldade em uma bondade , chamo de eficiência aqui.

Descobertas

De FLAC-4 em diante, o tempo de compressão explode, MAS há duas surpresas:

  1. Há uma redução significativa no tamanho do arquivo entre FLAC-3 e FLAC-4 dependendo do gênero musical: A música clássica tem uma compressão bem menor usando FLAC-4. Presumo que seja porque o FLAC usa um modelo de previsão linear para compressão que não funciona bem com músicas mais complexas (menos lineares).

  2. Para música não clássica, FLAC-3 é ainda significativamente pior do que FLAC-2 em termos de tamanho de arquivo.

flac_rank

Recomendações

Eu recomendo usar o nível de compressão FLAC-4 .

Ir mais alto aumenta significativamente o tempo de codificação com uma melhoria marginal na redução do tamanho do arquivo (redução média de FLAC-4 para FLAC-8 neste teste é 1,2% com um 182% aumento no tempo médio de compressão).


Apêndice

Álbuns

Acabei de pegar os primeiros cinco CDs aleatórios (listados abaixo) que pensei representar um campo diferente da música. Os links vão intencionalmente para a Amazon para fornecer uma possibilidade fácil de dar uma olhada na música / ter uma ideia da música, já que faz uma diferença significativa na compressão.

Programa

Para esta tarefa, escrevi um python programa que percorre todas as subpastas (os álbuns) em uma determinada pasta () para testar todos os arquivos .wav e agrupá-los / plotá-los pelo nome da subpasta.

<folder> Album 1 Album 2 ... 

A análise será salva em um arquivo --outfile <file1>. Para plotar, use --infile <file1> e --outfile <file2>.

#!/usr/bin/python3 #encoding=utf8 import os, sys, subprocess, argparse from datetime import datetime, timedelta from os.path import isfile, isdir, join import numpy as np import matplotlib.pyplot as plt import pickle as pkl parser = argparse.ArgumentParser(description="Analyse flac compression and conversion time") group = parser.add_mutually_exclusive_group() group.add_argument("-d", "--directory", help="Input folder", type=str) group.add_argument("-if", "--infile", help="Plot saved stats (pickle file)", type=str) parser.add_argument("-of", "--outfile", help="Output file", type=str, required=True) parser.add_argument("-c", "--cycles", help="Number of cycles for each file", type=int, default=5) parser.add_argument("-C", "--maxcompression", help="Max compression level", type=int, default=8) args = parser.parse_args() args.maxcompression += 1 ############################################################ xlabel = "FLAC Compression Factor" ylabel_size = "Size Relative to FLAC-0" ylabel_time = "Mean Compression Time\nOver {} Cycles Relative to FLAC-0 [s]".format(args.cycles) ylabel_efficiency = r"Efficiency: $(-1)\cdot$ Fraction Time $\cdot$ Fraction Size $+ 2$" ############################################################ # Analyse and write mode if not args.infile: if isdir(args.directory): mypath = args.directory else: raise ValueError("Folder {} does not exist!".format(args.directory)) folders = [f for f in os.listdir(mypath) if isdir(join(mypath, f))] print("Found folders: {}".format(folders)) # Create temporary working folder temp_folder = "temp_{}".format(os.getpid()) if not os.path.exists(temp_folder): os.makedirs(temp_folder) # Every analysis will be storen in stats stats = {} remove = [] for folder in folders: stats[folder] = {} stats[folder]["files"] = [f for f in os.listdir(mypath+folder) if isfile(join(mypath+folder, f)) and f.endswith(".wav")] if len(stats[folder]["files"]) == 0: print("No .wav files found in {}. Skipping.".format(folder)) remove.append(folder) stats.pop(folder, None) else: stats[folder]["stats"] = np.empty([len(stats[folder]["files"]),args.maxcompression], dtype=object) # Remove empty (no .wav) folders from list for folder in remove: folders.remove(folder) totalfiles = [] for folder in folders: totalfiles += stats[folder]["files"] totalfiles = len(totalfiles) if totalfiles == 0: raise RuntimeError("No .wav files found!") totalcycles = totalfiles * args.cycles * args.maxcompression counter_cycles = 0 time_start = datetime.strptime(str(datetime.now()), "%Y-%m-%d %H:%M:%S.%f") for folder in folders: # i: 0..Nfiles # n: 0..8 files = stats[folder]["files"] for i in range(len(files)): infile = "{}/{}".format(mypath+folder,files[i]) for n in range(args.maxcompression): Dtime = [] for j in range(args.cycles): time1 = datetime.strptime(str(datetime.now()), "%Y-%m-%d %H:%M:%S.%f") subprocess.run(["flac", infile, "--compression-level-{}".format(n), "-f", "-o", "{}/flac{}.flac".format(temp_folder,n)]) time2 = datetime.strptime(str(datetime.now()), "%Y-%m-%d %H:%M:%S.%f") Dtime.append((time2-time1).total_seconds()) counter_cycles += 1 # Percentage of totalcycles status = counter_cycles/totalcycles remain_factor = (1 - status)/status time_current = datetime.strptime(str(datetime.now()), "%Y-%m-%d %H:%M:%S.%f") time_elapsed = (time_current - time_start).total_seconds() print("========================================") print("Status: {} %".format(int(100*status))) print("Estimated remaining time: {}".format(str(timedelta(seconds=int(remain_factor * time_elapsed))))) print("========================================") Dtime = np.mean(Dtime) size = os.path.getsize("{}/flac{}.flac".format(temp_folder,n)) # Array if size (regarded as constat) and mean compression time # (file1, FLAC0)(file1, FLAC1)...(file1, FLACmaxcompression) # (file2, FLAC0)(file2, FLAC1)...(file2, FLACmaxcompression) # ... stats[folder]["stats"][i,n] = (size, Dtime) for folder in folders: # Taking columnwise (for each compression level) means of size... stats[folder]["ploty_size"] = [np.mean([e[0] for e in stats[folder]["stats"][:,col]]) for col in range(np.shape(stats[folder]["stats"])[1])] # (relative to FLAC-0) stats[folder]["ploty_size"] = [i/stats[folder]["ploty_size"][0] for i in stats[folder]["ploty_size"]] # ... and mean time. stats[folder]["ploty_time"] = [np.mean([e[1] for e in stats[folder]["stats"][:,col]]) for col in range(np.shape(stats[folder]["stats"])[1])] # (relative to FLAC-0) stats[folder]["ploty_time"] = [i/stats[folder]["ploty_time"][0] for i in stats[folder]["ploty_time"]] # Rough "effectivity" estimation -size*time + 2 # Expl.: Starts at (0,1), therefore flipping with (-1) requires # + 2. Without (-1) would be "badness" stats[folder]["ploty_eff"] = [ 2 + (-1) * stats[folder]["ploty_size"][i] * stats[folder]["ploty_time"][i] for i in range(len(stats[folder]["ploty_size"]))] with open(args.outfile, "wb") as of: data = {} data["stats"] = stats data["folders"] = folders data["cycles"] = args.cycles data["maxcompression"] = args.maxcompression pkl.dump(data, of, protocol=pkl.HIGHEST_PROTOCOL) if os.path.isdir(temp_folder): subprocess.run(["rm", "-r", temp_folder]) else: with open(args.infile, "rb") as f: data = pkl.load(f) stats = data["stats"] folders = data["folders"] args.maxcompression = data["maxcompression"] args.cycles = data["cycles"] fig = plt.figure() plotx = range(args.maxcompression) pos = range(len(plotx)) ax_size = fig.add_subplot(111) ax_size.set_xticks(pos) ax_size.set_xticklabels(plotx) ax_size.set_title("FLAC compression comparison") ax_time = ax_size.twinx() ax_efficiency = ax_size.twinx() colorfracs = [i / (len(folders)-0.9) if i > 0 else 0 for i in range(len(folders))] # Actual plotting lns = [] for cfrac, folder in zip(colorfracs, folders): color = plt.cm.viridis(cfrac) l_size, = ax_size.plot(plotx, stats[folder]["ploty_size"], color=color, linestyle=":", label="Size Ratio: {}".format(folder)) l_time, = ax_time.plot(plotx, stats[folder]["ploty_time"], color=color, linestyle="--", label="Time Ratio: {}".format(folder)) l_eff, = ax_efficiency.plot(plotx, stats[folder]["ploty_eff"], color=color, linestyle="-", label="Efficiency: {}".format(folder)) lns.append(l_size) lns.append(l_time) lns.append(l_eff) ax_efficiency.spines["right"].set_position(("outward", 60)) ax_size.xaxis.grid(color=".85", linestyle="-", linewidth=.5) ax_size.set_xlabel(xlabel) ax_size.set_ylabel(ylabel_size) ax_efficiency.set_ylabel(ylabel_efficiency) ax_time.set_ylabel(ylabel_time) lgd = ax_time.legend(handles=lns, loc="upper center", bbox_to_anchor=(0.5, -.15), facecolor="#FFFFFF", prop={"family": "monospace","size": "small"}) fig.savefig(args.outfile, bbox_inches="tight", dpi=300) 

Comentários

  • Uau … essa é uma análise quantitativa incrível que você fez lá! Eu realmente aprecio que você dedicou tempo para fazer tudo isso. Não poderia ‘ t ter sido rápido, mas resultados realmente excelentes. Obrigado!

Resposta

Flac 0. O armazenamento é tão barato hoje em dia, parece um acéfalo para mim … também Flac 0 tem menos probabilidade de causar problemas em um sistema mais lento, pois a decodificação é menos exigente para decodificar.

Resposta

Seguindo a resposta de Suuuehgi, também gostaria de acrescentar que se você está começando de um CD e copiando-o diretamente para FLAC, o tempo de codificação pode não ter importância porque você deve primeiro copiar a música, o que leva tempo.

Aqui está o que eu tentei:

Usando o dbPowerAmp CD Ripper, eu extraí minha cópia de Mariah Carey “s ” Merry Álbum ” de Natal. Rasguei uma vez no nível 8 de compactação FLAC, uma vez no nível 5 (dbPowerAmps padrão) e uma vez no nível 0.

Aqui está o total vezes para cada extração, desde clicar em iniciar até terminar com todos os arquivos FLAC concluídos:

Nível 0 = 6:19

Nível 5 = 6:18

Nível 8 = 6:23

Como você pode ver, a variação entre todos os 3 é mínima, dentro < 5 segundos um do outro. Enquanto eu assistia a cópia e codificação, o status da codificação era um mero flash na tela, por pouco registrado. E observando o sistema de arquivos enquanto ele estava sendo copiado, parecia estar codificando rapidamente enquanto estava sendo copiado. YMMV em sistemas mais lentos, no entanto.

Quanto aos tamanhos de arquivo, aqui estão os tamanhos de arquivo produzidos:

Nível 0 = 278 MB

Nível 5 = 257 MB

Nível 8 = 256 MB

insira a descrição da imagem aqui

Enquanto o total rip e enc Os tempos ode eram basicamente os mesmos, os tamanhos dos arquivos não eram, NO ENTANTO, há definitivamente retornos decrescentes nos níveis de compressão posteriores (como a resposta de Suuuehgi alude).

Para mim, parece que se você estão começando a partir de CD e têm um PC decente, o tempo que leva para extrair e codificar não mudará muito com base no nível de compressão FLAC. O tamanho do arquivo muda no entanto. Acho que a sugestão do dbPowerAmps de FLAC nível 5 como padrão é boa. Apenas 1 MB de diferença entre FLAC 5 e FLAC 8, onde, como se você fosse FLAC 0, meu exemplo mostra 21 MB de armazenamento em excesso que poderia ser salvo. Isso pode não parecer muito, mas quando você está copiando grandes coleções, aumenta rapidamente (uma única música FLAC pode ter mais ou menos esse tamanho).

Isso foi feito em um desktop com uma unidade de DVD USB 2 , rasgando em média a uma velocidade de 7x. As especificações do meu PC desktop são Intel Core i5-6500 CPU @ 3.2 Ghz, 16 GB de RAM e uma unidade SSD Samsung 860 EVO Sata.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *