Conversão em lote H.265 mkv em H.264 com ffmpeg para tornar os arquivos compatíveis para recodificação

31

Eu tenho arquivos codificados em H.265 que consomem muitos recursos e não são bem executados, e meu software de conversão (mencoder) atualmente não suporta o formato H.265. Posso convertê-los para H.264 em um arquivo em lotes de linha de comando para converter rapidamente os arquivos para nova compactação usando o Devede / OGMrip? Ao pesquisar neste site, não o encontrei discutido, por isso postarei o que considero uma pergunta útil e responda a ela.

TheMegolith
fonte

Respostas:

37

Sim, usando ffmpeg.

Abra um terminal e direcione-o para o diretório que contém os arquivos codificados H.265, supondo que você tenha ffmpegas bibliotecas apropriadas instaladas e supondo que estejam no formato MKV, copie e cole o seguinte na janela do terminal.

INPUT="$1"
for i in *.mkv ; do
    ffmpeg -i "$i" -bsf:v h264_mp4toannexb -sn -map 0:0 -map 0:1 -vcodec libx264 "$i.ts"
    mv "$i.ts" "$i.mpg"
    sleep 3
done

Lá está você. Isso será convertido para h.264 em um contêiner MPG no mesmo diretório.

Explicação das opções de comando:

  • for i in *.mkv ; do ... done

    Isso configura todos os arquivos .mkv em um diretório para serem incluídos no processo em lote. Isso pode ser alterado para acomodar a extensão do contêiner dos arquivos que você deseja processar.

  • ffmpeg -i "$i" Executa o programa ffmpeg e solicita que os arquivos sejam processados.

    • -bsf:v ativa o filtro de fluxo de bits de vídeo a ser usado.

    • h264_mp4toannexb - É o filtro de fluxo de bits que está ativado.

      Converta um fluxo de bits H.264 do modo prefixado de comprimento para iniciar o modo prefixado de código (conforme definido no Anexo B da especificação ITU-T H.264).

      Isso é exigido por alguns formatos de streaming, normalmente o formato de fluxo de transporte MPEG-2 ( mpegts) que processa o MKV h.264 (atualmente) exige isso; se não estiver incluído, você receberá um erro na janela do terminal instruindo-o a usá-lo.

    • -sn interrompe a transmissão de fluxos de legendas (para aqueles que não desejam legendas em seus vídeos) Isso é opcional e pode ser removido.

    • -map 0:0 -map 0:1Diz ao ffmpeg para processar apenas os dois primeiros fluxos do arquivo ( 0:0é o fluxo de vídeo, 0:1é o primeiro fluxo de áudio do arquivo). Isso faz duas coisas: retira o excesso de fluxos de áudio, geralmente o primeiro fluxo de áudio é em inglês, mas nem sempre. Outros fluxos, como legendas incorporadas, são removidos, reduzindo o tamanho do arquivo. Essa também é uma sequência opcional. Você pode usar ffprobepara visualizar os fluxos disponíveis no arquivo. -mapé opcional e pode ser descartado do comando

    • -vcodec libx264 Isso diz ao ffmpeg para codificar a saída para H.264

    • "$i.ts" Salva a saída no formato .ts, isso é útil para não sobrescrever os arquivos de origem.

  • mv "$i.ts" "$i.mpg"Converte a extensão do arquivo em MPG no mesmo diretório. Isso pode ser configurado para enviá-lo para qualquer diretório que você desejar.

  • sleep 3 - permite que o processo pare, dando tempo ao ffmpeg para enfileirar o próximo arquivo

TheMegolith
fonte
3
Excelente! Agora podemos excluir os comentários abaixo da pergunta. Eu diria que o sleep 3é desnecessário (mas possível útil para terminar o loop) e INPUT=$1não tem sentido, pois você está executando isso diretamente em um shell interativo.
muru
11
Considere o fluxo de cópia do áudio com, em -c:a copyvez de recodificação. Além disso, 0:0nem sempre se refere ao vídeo e 0:1nem sempre se refere ao áudio. É possível usar um especificador de fluxo para evitar possíveis problemas: -map 0:v -map 0:ase você deseja que todos os fluxos de vídeo e áudio da entrada 0 ou -map 0:v:0 -map 0:a:0se deseja apenas os primeiros fluxos de vídeo e áudio da entrada 0. Se você deseja apenas o fluxo de áudio em inglês: -map 0:m:language:eng(supondo que está rotulado).
llogan
1
@LordNeckbeard Vou votar em você para escrever uma resposta completa.
Fran Marzoa
1
@Fran Não percebeu que havia tantos votos positivos sobre esse comentário. Adicionei uma resposta usando métodos mais simples, menos propensos a erros e mais eficientes.
Llogan
1
Eu iria totalmente com simplesmente ffmpeg -i $INPUT -vcodec h264 -acodec copy $OUTPUT. Algo que uso todos os dias e que posso memorizar, em oposição a essa enxurrada de bandeiras sem sentido, pelas quais cada ffmpeg responde é tão infame.
Ben Sinclair
20

Conversão de lote de H.265 em H.264

Estes exemplos foram escritos para recentes ffmpeg. Economize alguns problemas e faça o download de uma versão recente. Em seguida, coloque o ffmpegbinário em ~/binou /usr/local/bin(talvez seja necessário sair do sistema, faça login para que seja notado).

Saída Matroska

mkdir h264vids
for f in *.mp4; do ffmpeg -i "$f" -map 0 -c copy -c:v libx264 -crf 23 -preset medium h264vids/"${f%.*}.mkv"; done
  • Este exemplo será exibido em um diretório chamado h264vids.

  • Este exemplo assume que suas entradas são .mp4. Caso contrário, altere a .mp4instância no exemplo para o tipo de arquivo de entrada ou use apenas o ganancioso *.

  • Ajuste -crfa qualidade e -preseta velocidade / eficiência da codificação. Ou simplesmente remova essas opções e use os padrões que são razoavelmente bons e devem ser suficientes para a maioria (o exemplo está usando os valores padrão para essas opções). Veja FFmpeg Wiki: H.264 para mais informações sobre essas opções.

Saída MP4

Este é um pouco mais complicado. Isso executará a codificação condicional, dependendo se o áudio de entrada é AAC ou não. Se o áudio de entrada for AAC, o áudio será copiado em fluxo contínuo (re-mixado) como está e a recodificação desnecessária será evitada. Se o áudio de entrada não for AAC, será recodificado para AAC.

Aqui está um script simples que demonstra como fazer isso usando ffprobee ffmpeg. Copie e salve-o no diretório que contém seus vídeos a serem convertidos, dê permissão de execução chmod +x yourscriptnamee execute-o com ./yourscriptname.

#!/bin/bash

mkdir h264vids

for f in *.mkv
do
  audioformat=$(ffprobe -loglevel error -select_streams a:0 -show_entries stream=codec_name -of default=nw=1:nk=1 "$f")
  if [ "$audioformat" = "aac" ]; then
    ffmpeg -i "$f" -c:v libx264 -crf 23 -preset medium -c:a copy -movflags +faststart h264vids/"${f%.*}.mp4"
  else
    ffmpeg -i "$f" -c:v libx264 -crf 23 -preset medium -c:a aac -movflags +faststart h264vids/"${f%.*}.mp4"
  fi
done
  • Este exemplo será exibido em um diretório chamado h264vids.

  • Este exemplo assume que suas entradas são .mkv. Caso contrário, altere a .mkvinstância no exemplo para o tipo de arquivo de entrada ou use apenas o ganancioso *.

  • Veja a nota acima sobre -crfe -preset.

  • Você pode pausar a codificação com ctrl+ ze continuar com fg.

llogan
fonte
0

Considerando as respostas anteriores, vim com o seguinte:

for file in *265.mkv; do nice -n19 ffmpeg -i $file -c copy -c:v libx264 ${file/%265.mkv/264.mkv}; done

Isso pressupõe que os arquivos sempre tenham um nome terminado em 265.mkv. Este final será substituído por 264.mkv.

Se a nomeação de arquivos for diferente, você precisará adaptar o comando de acordo.

kerner1000
fonte