¿Cómo puedo canalizar datos sin pérdidas hacia y desde FFmpeg?

¿Cómo puedo canalizar datos sin pérdidas hacia y desde FFmpeg?

Canalicé una secuencia de una instancia de FFmpeg a otra, pero debido a que se usó compresión en la secuencia intermedia, el resultado final fue feo. Necesito una tubería sin pérdidas para evitar esto y quiero que contenga audio y video.

Sospecho que hay más de una respuesta a este problema, por lo que los puntos de bonificación son para cualquiera que proporcione una lista exhaustiva de soluciones (contenedores y códecs compatibles que se puedan canalizar). Los puntos de bonificación también se otorgan a cualquiera que tenga en cuenta otros datos, como los subtítulos.

EDITAR: estoy buscando combinaciones adecuadas de códec/contenedor. No sé por qué la gente tenía dificultades para darse cuenta de eso, ya que dije que ya usé una tubería y ahora necesito que no tenga pérdidas.

No sé cómo explicar esto sin parecer engreído, pero este es un sitio de preguntas frecuentes. Hacer preguntas que requieren respuestas extremadamente específicas no ayudará a los millones de usuarios que llegan a este sitio ingresando sus propios problemas en los motores de búsqueda. Mi pregunta fue diseñada para ayudar a cualquiera que necesite canalizar datos sin pérdidas entre instancias de FFmpeg sin distraer a todos con un muro de narrativa y código que explica lo que estaba haciendo, por qué no funcionó y por qué esta es la única opción.

Respuesta1

Cómo canalizar vídeo y audio sin pérdidas desde ffmpegaffmpeg

Requisitos del autor de la pregunta:

  • canalizar sin pérdidas de una instancia ffmpega otra
  • no importa si va y viene/dev/null

Ejemplo:

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

No veo ninguna razón por la que alguien haría esto.Además, hay muy pocas razones para pasar de un proceso a ffmpegotro ffmpegcuando lo más probable es que puedas usar un ffmpegproceso para hacer lo que quieras.

Qué hacen las opciones:

  • -s 1280x720 -f rawvideo– Opciones para describir la entrada desde/dev/zerono es un formato de entrada típico y, por lo tanto, se requieren estas opciones adicionales.

  • -i /dev/zero– La entrada de vídeo. En este ejemplo se utiliza para generar una transmisión de vídeo a partir de "nada". Esto se utilizó en el ejemplo porque el autor de la pregunta se negó a proporcionar información sobre los datos utilizados.

  • -ar 48000 -ac 2 -f s16le– Opciones para describir la entrada desde/dev/zerono es un formato de audio típico.

  • -i /dev/zero– La entrada de audio. Se utiliza en este ejemplo para generar una secuencia de audio a partir de "nada".

  • -c copyCopia de secuencia, o re-mux, las entradas a la salida. No se realiza ninguna recodificación, por lo que el proceso no produce pérdidas. Se desconoce si la copia de secuencias es aceptable para el autor de la pregunta o no. ¿Quizás se desee volver a codificar?

  • -f nut– Debes indicar ffmpegqué formato usar para la tubería. Nut es un formato contenedor. Consulte ffmpeg -formatspara obtener una lista completa. Otro formato flexible es -f matroska, pero es imposible sugerir un formato de contenedor de salida apropiado o específico para usar sin más información del autor de la pregunta.

  • pipe:1- Utilizar elpipeprotocolopara enviar a la salida estándar. Alternativamente, se puede omitir el número (solo pipe:) y, de forma predeterminada, se usará el descriptor de archivo stdout para escribir y stdin para leer.

Respuesta2

La forma en que aprendí a hacer esto (de partes de respuestas anteriores) es usar el rawvideocódec para el video, el pcm_s16lecódec de audio y nutel contenedor de FFmpeg para codificar la transmisión. nutno es compatible con los principales programas fuera de FFmpeg, pero es el único contenedor que conozco actualmente que puede admitir los formatos sin comprimir necesarios para canalizar datos de manera eficiente entre procesos.

Los argumentos para esta codificación podrían verse así:

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

Parte del audio se almacena con muestras de 24 bits o más y, para estos, debería utilizar pcm_24leun formato diferente. La lista completa de formatos de audio sin comprimir aparecerá al ejecutar ffmpeg -codecs(tendrás que buscarlos en la lista). Si no sabe cuál es el tamaño de muestra de su audio, su uso pcm_16leno debería causar una pérdida notable de calidad.

En el extremo receptor de la tubería, configure la entrada en entrada estándar y ffmpeg detectará el formato y decodificará la transmisión.

... ffmpeg -i - ...

Los puntos suspensivos (...) en esta respuesta no son parte del código. Aquí es donde va su código. Los guiones solitarios (-) le indican a FFmpeg que use entrada estándar o salida estándar, dependiendo de dónde aparezcan.

ACTUALIZAR:

Intenté un experimento simple para mejorar esto, y parece que un mejor contenedor es AVI, porque otros programas lo entenderán (al menos VLC).

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

Esto funcionará exactamente igual que la versión anterior, con la ventaja adicional de la compatibilidad.

En retrospectiva, lamenté haber publicado una pregunta que no fue útil en muchas situaciones, a pesar de mi afirmación de que las preguntas deberían ser útiles para todos. Esto hace que la respuesta sea más útil.

Respuesta3

El único problema con la otra respuesta es que es pcm_s16le, no s16le. Además, incluye muchos parámetros redundantes.

Usaría pcm en lugar de flac en la tubería, porque lleva mucho menos tiempo procesarlo (PCM es audio sin formato, FLAC tarda mucho tiempo en codificarse).

De todos modos, así es como lo haría.

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>

Esto funcionó para mí la última vez que lo intenté, pero mi objetivo era canalizar ffmpeg a ffplay, que es un proceso ligeramente diferente.

ejemplo:

Esto canaliza un video desde ffmpeg a otra instancia como salida de video sin formato y PCM little-endian de 16 bits (ambos sin pérdidas a menos que tenga PCM de 24 bits, luego sustituya pcm_s24le). Luego los convierte a h.264 en la segunda instancia, con el fraunhoefer Biblioteca AAC del proyecto de Android ( libfaacse incluye más comúnmente en compilaciones de ffmpeg. En su lugar, puede reemplazarla con esta).

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

Si esto no canaliza los subtítulos, siempre puedes copiarlos a SRT y luego volver a mezclarlos más tarde, o agregarlos a las canalizaciones de arriba fácilmente.

información relacionada