Como posso canalizar dados sem perda de e para o FFmpeg?

7

Eu canalizei um fluxo de uma instância do FFmpeg para outro, mas como a compressão foi usada no fluxo intermediário, o resultado final foi feio. Eu preciso de um pipe sem perdas para evitar isso, e quero que ele contenha áudio e vídeo.

Eu suspeito que há mais de uma resposta para esse problema, então os pontos de bônus vão para qualquer pessoa que forneça uma lista exaustiva de soluções (contêineres compatíveis e codecs que podem ser canalizados). Os pontos de bônus também são direcionados para qualquer pessoa responsável por outros dados, como legendas.

EDIT: Estou procurando combinações de codec / contêiner adequadas. Eu não sei porque as pessoas estavam tendo dificuldade em descobrir isso, já que eu disse que já usei um tubo e agora eu preciso que ele seja sem perdas.

Eu não sei como explicar isso sem soar vaidoso, mas este é um site de FAQ. Fazer perguntas que exigem respostas extremamente específicas não ajudará os milhões de usuários que acessam esse site inserindo seus próprios problemas nos mecanismos de pesquisa. Minha pergunta foi projetada para ajudar qualquer outra pessoa que precise pipetar dados sem perda entre instâncias do FFmpeg sem distrair todo mundo com uma parede de narrativa e código explicando o que eu estava fazendo, por que não funcionou e por que essa é a única opção. p>     

por Wutaz 06.12.2013 / 22:01

3 respostas

6

A maneira como aprendi a fazer isso (de partes de respostas anteriores) é usar o codec rawvideo do vídeo, o codec de áudio pcm_s16le e o wrapper nut do FFmpeg para codificar o fluxo. O nut não é suportado pelos principais programas fora do FFmpeg, mas é o único contêiner que conheço atualmente que pode suportar os formatos descompactados necessários para distribuir dados com eficiência entre os processos.

Os argumentos para essa codificação podem ser assim:

... -c:v rawvideo -c:a pcm_16le -f nut - ...

Algum áudio é armazenado com amostras de 24 bits ou maiores e, para essas, você deve usar pcm_24le ou um formato diferente. A lista completa de formatos de áudio não compactados será listada executando ffmpeg -codecs (você terá que pesquisar a lista por eles). Se você não sabe qual é o tamanho de amostra do seu áudio, usar pcm_16le não deve causar perda perceptível de qualidade.

Na extremidade de recebimento do pipe, defina a entrada como entrada padrão e o ffmpeg detectará o formato e decodificará o fluxo.

... ffmpeg -i - ...

As elipses (...) nesta resposta não fazem parte do código. Aqui é onde o seu código vai. Os hífens solitários (-) dizem ao FFmpeg para usar a entrada padrão ou saída padrão, dependendo de onde eles aparecem.

ATUALIZAÇÃO:

Eu tentei um experimento simples para melhorar isso, e parece que um container melhor é o AVI, porque outros programas irão entendê-lo (pelo menos o VLC irá).

... -c:v rawvideo -c:a pcm_16le -f avi - ...

Isso funcionará exatamente como a versão antiga, com a vantagem adicional de compatibilidade.

Em retrospecto, me arrependi de postar uma pergunta que não foi útil em muitas situações, apesar da minha afirmação de que as perguntas deveriam ser úteis para todos. Isso torna a resposta mais útil.

    
por 08.12.2013 / 19:26
11

Como canalizar vídeo e áudio sem perda de ffmpeg para ffmpeg

Requisitos do autor da pergunta:

  • pipe sem perdas de uma instância de ffmpeg para outra
  • não importa se vai e de /dev/null

Exemplo:

ffmpeg -s 1280x720 -f rawvideo -i /dev/zero -ar 48000 -ac 2 -f s16le -i \
/dev/zero -c copy -f nut pipe:1 | ffmpeg -y -i pipe:0 -c copy -f nut /dev/null

Não vejo motivos para que alguém faça isso. Além disso, há muito poucos motivos para canalizar de ffmpeg para ffmpeg quando é mais provável que você use apenas um processo ffmpeg para faça o que quiser.

O que as opções fazem:

  • -s 1280x720 -f rawvideo - Opções para descrever a entrada, pois /dev/zero não é um típico formato de entrada e, portanto, essas opções adicionais são necessárias.

  • -i /dev/zero - A entrada de vídeo. Está sendo usado neste exemplo para gerar um fluxo de vídeo de "nada". Isso foi usado no exemplo porque o autor da pergunta se recusou a fornecer qualquer informação sobre as entradas que estão sendo usadas.

  • -ar 48000 -ac 2 -f s16le - Opções para descrever a entrada, pois /dev/zero não é um típico formato de áudio.

  • -i /dev/zero - A entrada de áudio. Está sendo usado neste exemplo para gerar um fluxo de áudio de "nada".

  • -c copy - Copie a cópia ou re-mux, as entradas para a saída. Nenhuma recodificação está sendo executada, portanto, o processo é sem perdas. Não se sabe se a cópia em fluxo é aceitável para o autor da pergunta ou não. Talvez a recodificação seja desejada?

  • -f nut - Você precisa informar ffmpeg qual formato usar para o pipe. A porca é um formato de contêiner. Veja ffmpeg -formats para uma lista completa. Outro formato flexível é -f matroska , mas é impossível sugerir um formato de contêiner de saída apropriado ou específico para usar sem mais informações do questionador da questão.

  • pipe:1 - Use o pipe protocol para enviar para o stdout. Alternativamente, o número pode ser omitido (apenas pipe: ) e, por padrão, o descritor de arquivo stdout será usado para escrita e o stdin será usado para leitura.

por 06.12.2013 / 22:42
-1

O único problema com a outra resposta é que é pcm_s16le, não s16le. Além disso, inclui muitos parâmetros redundantes.

Eu usaria pcm em vez de flac no pipe, porque leva muito menos tempo para processar (PCM é áudio bruto, FLAC leva muito tempo para codificar).

De qualquer forma, eis como eu faria isso.

ffmpeg -i <input video file/stream> -vcodec rawvideo -acodec pcm_s16le pipe:1 | ffmpeg -f rawvideo -i - -vcodec <video output codec> -acodec <audio output codec> -vb <video bitrate if applicable> -ab <audio bitrate if applicable> <final-output-filename>

Isso funcionou para mim quando eu tentei pela última vez, mas meu objetivo era canalizar o ffmpeg para o ffplay, que é um processo ligeiramente diferente.

exemplo:

Isso canaliza um vídeo do ffmpeg para outra instância como saída de vídeo bruta e PCM little-endian de 16 bits (ambos sem perda, a menos que você tenha PCM de 24 bits e substitua pcm_s24le ). segunda instância, com a biblioteca Aun fraunhoefer do projeto Android ( libfaac é mais comumente incluída nas construções do ffmpeg. Você pode substituí-la por isso.)

ffmpeg -i montypythonsflyingcircus-s1e1.avi -vcodec rawvideo -acodec pcm_s16le pipe:1 | ffmpeg -i - -vcodec libx264 -acodec libfdk_aac -vb 1200k -ab 96k mpfc-s1e01-output.mkv

Se isso não canalizar as legendas, você sempre pode copiá-las para os SRTs e depois atualizá-las novamente ou adicioná-las aos canais acima facilmente.

    
por 06.12.2013 / 23:48