ffmpeg: conserva el código de tiempo al convertir mp4 a mov

Tengo .mp4archivos creados por una cámara Sony A7s. Están usando el códec XAVC S. Los estoy convirtiendo para .movusar el siguiente comando. Los archivos originales tienen un código de tiempo, pero no está presente en el archivo de salida. Los archivos de salida tienen sus códigos de tiempo establecidos en cero. ¿Hay alguna forma de conservar el código de tiempo?

ffmpeg -i [filenmae] -vcodec copy -acodec copy [outputDirectory]

Respuestas (4)

Respuesta corta específica para este problema:

Utilice esta opción:

-map_metadata 0:s:2

Explicación:

El código de tiempo a menudo viene en un formato específico para el formato de archivo, por lo que no se puede esperar que ffmpeg simplemente lo "copie" sin obtener instrucciones explícitas.

En el archivo mp4 de material de archivo Sony a7siii 4k 10bit, hay un flujo de 'datos' separado al que se agrega como metadatos. Por lo general, se indexa como flujo 2 (el tercer flujo), pero puede usar este comando para determinarlo usted mismo:

ffmpeg -i inputfile.mp4

Esto mostrará información sobre todos los flujos de entrada, incluidos los metadatos.

Salida de ejemplo (extractos):

ffmpeg version...
...
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'inputfile.mp4':
  Metadata:
...
  Stream #0:0(und): Video: h264...
...
  Stream #0:2(und): Data: none (rtmd / 0x646D7472), 2252 kb/s (default)
    Metadata:
      creation_time   : 2021-06-19T16:39:17.000000Z
      handler_name    : Timed Metadata Media Handler
      timecode        : 07:15:07:17

Ahora, tenga en cuenta que el código de tiempo se adjunta como metadatos a un flujo de 'datos' separado, que debe estar presente en la salida para -map_metadata 0que funcione de manera sencilla. Como no se puede copiar, debemos asignar esos metadatos a los metadatos globales del propio archivo.

Anote el número de transmisión que contiene el código de tiempo, en este ejemplo, la transmisión 2 de la entrada 0, y asígnelo a metadatos globales usando -map_metadata 0:s:2.

ffmpeg -i inputfile.mp4 -map_metadata 0:s:2 -c copy outputfile.mov

Esto debería asignar los metadatos del flujo indexado 2 (s:2) desde la primera entrada (0:) a los metadatos globales (predeterminados) del archivo de salida, y copiar los flujos de audio y video tal como están.

Tenga en cuenta que la numeración y el significado de 's' es diferente de cómo es en otras opciones más comunes. Consulte más información en la parte de opciones avanzadas de la documentación de ffmpeg .

Luego, ffmpeg lee todo lo que comprende de los metadatos de esa secuencia (que incluye el código de tiempo), lo convierte al formato de metadatos ideal del formato de archivo de destino y lo incluye en la salida.

El archivo resultante tendrá un código de tiempo reconocible en software de edición como DaVinci Resolve y Premiere Pro.

Probé otras opciones como -write_tmcdy varias formas de -map 0con y sin -copy_unknownpero no funcionaron, probablemente porque ffmpeg actualmente necesita entender lo que está copiando.

Tenga en cuenta que esto no copia todo el flujo de datos, solo sus metadatos. Para nuestro requisito actual, esto está bien.

Además, dado que me estaba convirtiendo a prores422hq, mi comando exacto (que funcionó) fue este:

ffmpeg -i inputfile.mp4 -map_metadata 0:s:2 -c:v prores_ks -profile hq -c:a pcm_s16le outputfile.mov
¡Bienvenidos! ¡Gracias por una primera respuesta increíble y detallada!

En caso de que alguien más busque esto, el código de tiempo en los archivos mp4 y mov suele ser una pista de "datos", y ffmpeg generalmente elimina las pistas de datos. Para mantener todas las pistas, generalmente uso estos interruptores para mapear las pistas desde el origen hasta las pistas en el destino.

-map 0:v (video switches)
-map 0:a (audio switches)
-map 0:d (this keeps the data track)

Lo que también tiene la ventaja de mantener todas las pistas de audio de origen, en lugar del valor predeterminado de solo la primera. Entonces su comando podría verse como

ffmpeg -i [filename] -map 0:v -codec:v copy -map 0:a -codec:a copy -map 0:d [outputDirectory]

EDITAR: en ffmpeg moderno, también puede agregar un signo de interrogación (como -0: a?) Lo que significa que ffmpeg continuará si no encuentra una pista como la que le pidió que copiara

Solo use copiar para todas las transmisiones, es decir

ffmpeg -i [filename] -c copy -map 0 [outputDirectory]

Editar : cambiemos el orden de bytes

ffmpeg -i [filename] -c copy -c:a pcm_s16le -map 0 [outputDirectory]
Gracias por la sugerencia. Lo probé y copió el código de tiempo, pero no copió el audio. Lo probé así "-acodec copy -c copy -map 0" pero aún no hay audio. También dio este mensaje tanto en su versión como en la que modifiqué: [NULL @ 0000000005795f00] Unknown hldr_type for rtmd / 0x646D7472, writing dummy
Pegue la salida completa de la consola del comando que encontró en la pregunta.
Según esa lectura, el audio se copió correctamente. ¿Qué ffprobe C0371.movdice?
Tienes razón, copió el audio. El problema que tengo es que el programa que estoy usando, Davinci Resolve, lee el audio creado usando el comando original, "-vcodec copy -acodec copy", pero no lee el audio creado usando la versión modificada. Eso es un problema, porque la única razón por la que hago la conversión es para que Davinci Resolve lea el audio. Esta es la salida de ffprobe para ambos archivos pastebin.com/Wbkn3nat
Pruebe el nuevo comando en respuesta.
La primera vez que probé la nueva versión, me dijo que no podía encontrar un formato de salida compatible, así que cambié el archivo de salida para que tuviera la extensión .mov. Creó el archivo de salida pero no tiene audio ni código de tiempo. Este es el resultado: pastebin.com/vfcYd1uT Este es el archivo de prueba que estoy usando: goo.gl/xilYd9
Esto parece ser un problema de DaVinci en lugar de ffmpeg. Usé su archivo fuente con mis comandos y el resultado se reproduce con audio en Sony Vegas y Premiere Pro CC pero no en Resolve 11 (la versión que tengo). No uso Resolve para editar, así que si puedes encontrar una guía de lo que Resolve necesita en un MP4/MOV, puedo ajustar mi comando.

El código de tiempo y muchas otras informaciones no pertenecen a transmisiones de video o audio, son atributos de metadatos.

FFmpeg tiene muchos comandos para manipular los atributos de los metadatos, para la pregunta específica puede echar un vistazo a mi pregunta anterior y la respuesta relativa: ffmpeg Cortar un medio conservando todos los flujos pero también todos los metadatos, códigos de tiempo y todo lo demás

Tenga en cuenta que los metadatos tienden a cambiar de formato a formato, por lo que probablemente deba encontrar el campo de metadatos correcto en el Sony .mp4 original, analizarlo correctamente y escribirlo cambiado o renombrado en el nuevo archivo .mov, siguiendo el QuickTime .mov especificaciones para la definición de código de tiempo.