2010-07-03 21 views
12

Tengo la necesidad de grabar en un código de tiempo un video y me pregunto si esto es algo que ffmpeg es capaz de hacer.¿Puedo ffmpeg grabar en el código de tiempo?

+0

Así que supongo que quieres grabar en la "hora actual del video" en el video mismo? ¿O quieres usar libav * para agregar texto a un video con tu propio código de tiempo aquí? – rogerdpack

Respuesta

3

Respuesta corta, no.

Respuesta larga, sí, pero no sin usar una biblioteca separada para crear los marcos con el código de tiempo representado, con transparencia llenando el resto del cuadro y luego usando FFmpeg para superponer los marcos en el video existente. De repente, no sé cómo hacer esto, pero estoy seguro de que si eres creativo puedes resolverlo.

Editar: He estado trabajando en este problema porque es una pregunta/proyecto interesante para mí. He avanzado un poco más en la solución escribiendo a Perl script que generará un archivo .srt con el código de tiempo incrustado en él para cualquier archivo de video dado desde el que FFmpeg esté configurado para poder leer los metadatos. Utiliza la biblioteca Video::FFmpeg para leer la duración y guarda un archivo de subtítulos como ${video}.srt. Esto hará que sea lo que hará que automáticamente en Mplayer si inserta las siguientes líneas en su ~/.mplayer/config:

# select subtitle files automatically in the current directory, all files 
# matching the basename of the current playing file 
sub-fuzziness=1 

Seguimos trabajando en cómo posicionar y superponer los subtítulos prestados en un vídeo y volver a codificar en el mismo formato . Actualizaré esta publicación porque sé más.

+0

Ese es un enfoque interesante. ¿Alguna pista sobre las bibliotecas que podría hacer esto? Si no, puedo mirar alrededor. – spinon

+0

Una cosa que debería agregar ya que obviamente está haciendo un gran trabajo aquí. Es lo que estoy buscando hacer es crear un nuevo video con los códigos de tiempo presentes en él. Así que no solo juegue con ellos en un reproductor, sino cree un video nuevo para que pueda reproducirse en cualquier reproductor. Agregaré una recompensa a la pregunta ya que le has dado tanto esfuerzo. – spinon

+1

Evidentemente, ahora es posible con filtros de video. Consulte https://gist.github.com/reidransom/2630650 –

-1

FFMPEG podrá hacer gran parte del trabajo, pero no estará todo empaquetado. Usando FFMPEG, puede hacer que descodifique todos los fotogramas en secuencia, y le otorgue la "Marca de tiempo de presentación" (los metadatos adicionales relacionados con el tiempo pueden estar disponibles en algunos formatos, pero PTS es lo que desea buscar para comenzar .) Entonces, usted está solo para dibujar el texto en el marco decodificado usted mismo. Utilizo Qt para cosas similares, al usar QPainter en una QImage con los datos de marco, pero puede haber alguna otra API para dibujar en una imagen que le parezca más obvia. Luego, use la API FFMPEG para hacer un video comprimido que tenga sus marcos recién dibujados en él. Será un poco más complicado si también quieres audio. Mi propio trabajo realmente no se preocupa por el audio, así que no me he molestado en aprender los aspectos de audio de la API. Básicamente, a medida que haces tu ciclo de lectura sacando paquetes del archivo, algunos de ellos serán de audio. En lugar de descartarlos como yo, tendrá que guardarlos y escribirlos en el archivo de salida como los obtuvo.

Solo he usado la API C, en lugar de C#, por lo que no sé si hay algún problema especial que preocupe.

2

En compilaciones más recientes, puede usar el filtro drawtext (la "t" en sus ejemplos es, creo, la marca de tiempo del marco) para insertar texto. También funciona para srtftime en el tiempo "actual" del sistema también.

+0

La documentación contiene un error, no hay una opción 't'. Se [se denomina 'basetime'] (http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavfilter/vf_drawtext.c;h=dde3b0a3202d45b82326f1f523673d52eff6236b;hb=HEAD#l190). De todos modos, no pude hacer que esto funcione correctamente. – Lekensteyn

+0

sí, aparentemente fue desaprobado y eliminado. Algunas otras cosas que pueden ser útiles: puede usar cualquier soporte "eval", y tener "frame_num" y "localtime" disponibles para las cosas de strftime ... – rogerdpack

+0

Ver [mi respuesta a esta pregunta] (http: // stackoverflow .com/a/20313722/427545), ayer descubrí algunos otros métodos para obtener el tiempo. La 't' parece ser un error de documentación, debe ser 'basetime' (que se aplica a' expansion = strftime' solamente). – Lekensteyn

21

filtro DrawText de FFMPEG funciona para mí, se especifica el código de tiempo de inicio y su formato de esta manera:

-vf drawtext="fontsize=15:fontfile=/Library/Fonts/DroidSansMono.ttf:\ 
timecode='00\:00\:00\:00':rate=25:text='TCR\:':fontsize=72:fontcolor='white':\ 
boxcolor=0x000000AA:box=1:x=860-text_w/2:y=960" 

tiene que especificar el formato de código de tiempo en el formato hh: mm: ss [:;,] y ss. Tenga en cuenta que debe escapar de los dos puntos en la cadena de formato de código de tiempo, y debe especificar una tasa de código de tiempo (aquí 25 fps).También puede especificar texto adicional - aquí es "TCR:"

Puede obtener la velocidad de fotogramas con ffprobe y un poco de cáscara de fu:

frame_rate=$(ffprobe -i "movie.mov" -show_streams 2>&1|grep fps|sed "s/.*, \([0-9.]*\) fps,.*/\1/") 

por lo que podría fácilmente conectar todo junto en un lote - escritura de procesamiento, por ejemplo

for i in *.mov 
frame_rate=$(ffprobe -i "$i" -show_streams 2>&1|grep fps|sed "s/.*, \([0-9.]*\) fps,.*/\1/") 
clipname=${(basename "$i")/\.*/} 
ffmpeg -i "$i" -vcodec whatever -acodec whatever \ 
-vf drawtext="fontsize=15:fontfile=/Library/Fonts/DroidSansMono.ttf:\ 
timecode='00\:00\:00\:00':rate=$frame_rate:text='$clipname' TCR:':\ 
fontsize=72:fontcolor='white':boxcolor=0x000000AA:\ 
box=1:x=860-text_w/2:y=960" "${i/.mov/_tc.mov}" 
done 

que añadiría el nombre del clip y código de tiempo rodando en una caja semi-opaco en el centro inferior de un marco 1920x1080

Editar Desde que he venido al lado oscuro ahora hago esto en un entorno de Windows PowerShell, y esto es lo que yo uso:

ls -R -File -filter *.M*|%{ 
ffmpeg -n -i $_.fullname -vf drawtext="fontsize=72:x=12:y=12:` 
timecode='00\:00\:00\:00':rate=25:fontcolor='white':` 
boxcolor=0x000000AA:box=1" ` 
("c:\path\to\destination\{0}" -F ($_.name -replace 'M[OPT][V4S]', 'mp4'))} 

Esto crea mp4s dado una carpeta que contiene MOV, MP4 y Archivos .MTS (usando el comando -filter busca archivos con * .M * en el nombre, que debería cambiar si está haciendo archivos .AVI), y es un poco más mínimo, solo usa libx264 con configuraciones predeterminadas como códec de salida y no especifica fuente, etc. El código de tiempo en este caso se quema en la esquina superior izquierda del marco.

+1

Buena idea, desafortunadamente no funciona con fracciones como '12.34 fps'. – Lekensteyn

+0

hmm Considero que es un error que no se puede usar el código de tiempo para mostrar fracciones ... – rogerdpack

+0

De hecho, parece que solo funciona para frame_rate estándar, como 25, tuvo que transcodificar, e incluso entonces, los tiempos eran mal por alguna razón para mí. – ntg

12

El filtro drawtext mencionado en @stib es la clave para insertar la hora. Sin embargo, la opción timecode no coincide con la hora del reloj de pared. Si obtiene el parámetro r (timecode_rate) incorrecto, entonces su tiempo no coincidirá con el tiempo de reproducción.

Existen otras opciones, por ejemplo, la opción text='%{prt}' le permite visualizar el tiempo transcurrido con una precisión de microsegundos. Comando:

ffmpeg -i video.mp4 -vf "drawtext=text='%{prt}'" output.mp4 

Para obtener un reloj en lugar, tenía que utilizar la opción obsoleta strftime. Tiene una opción no documentada basetime que se puede usar para establecer la hora de inicio en microsegundos. Un ejemplo en el que la hora de inicio a 24:00 el 1 de diciembre de 2013 (la parte $(...) es de concha de expansión realizado por la cáscara) y han mostrado sólo el tiempo (ver el strftime manual for possible formats):

ffmpeg -i video.mp4 -vf "drawtext=expansion=strftime: \ 
    basetime=$(date +%s -d'2013-12-01 12:00:00')000000: \ 
    text='%H\\:%S\\:%S'" output.mp4 

\\: se usa para escapar del : que de otro modo obtendría el significado de un separador de opciones.

Otro ejemplo: un comando para insertar la fecha + hora dentro de un recuadro negro, algunos píxeles de la esquina superior izquierda y "algo de relleno" (en realidad, dos espacios y saltos de línea en los bordes):

newline=$'\r' 
ffmpeg -i video.mp4 -vf "drawtext=x=8:y=8:box=1:fontcolor=white:boxcolor=black: \ 
    expansion=strftime:basetime=$(date +%s -d'2013-12-01 12:00:00')000000: \ 
    text='$newline %Y-%m-%d %H\\:%M\\:%S $newline'" output.mp4 

Otro ejemplo para conseguir la microsegundos debajo del reloj:

newline=$'\r' 
ffmpeg -i video.mp4 -vf "drawtext=expansion=strftime: \ 
    basetime=$(date +%s -d'2013-12-01 12:00:00')000000: \ 
    text='$newline %H\\:%M\\:%S $newline':fontcolor=white:box=1:boxcolor=black, \ 
    drawtext=text='$newline %{pts} $newline': \ 
    y=2*th/3:box=1:fontcolor=white:boxcolor=black:" output.mp4 

Este utiliza el hecho de que el texto es en realidad tres líneas de largo y que tanto texto tener una nueva línea (retorno de carro, ^M) antepuesto y anexa.(Sin esta nueva línea, el espacio se despojó)

Otros consejos:

  • -vf y -filter:v son iguales.
  • No puede especificar filtros varias veces, p. -vf drawtext=text=1 -vf drawtext=text=2 solo dibujará el segundo texto. Puedes combinar filtros con una coma como mostré arriba. !
+0

¿la opción "hora local" ayuda aquí? http://ffmpeg.org/pipermail/ffmpeg-user/2014-July/022355.html – rogerdpack

+0

localtime no ayuda, basa la hora local en lugar de un momento fijo. El comando que probé: 'ffplay -i video.mp4 -vf drawtext = 'expansión = normal: texto =% {tiempo local \\:% a% b% d% Y}' ' – Lekensteyn

+0

éste trabajó newline = $' \ r ' ffmpeg -i video.mp4 -vf "drawtext = expansion = strftime: \ basetime = $ (date +% s -d'2013-12-01 12:00:00') 000000: \ text = '$ newline% H \\:% M \\:% S $ newline ': fontcolor = blanco: box = 1: boxcolor = negro, \ drawtext = text =' $ newline% {pts} $ newline ': \ y = 2 * th/3: box = 1: fontcolor = white: boxcolor = black: "output.mp4 – Rick2047

1

La solución más sencilla que encontré para mostrar el reloj cuando el archivo ha sido capturada, no su duración y que funcione/basado en este post, gracias/es

D:\Temp\2>ffmpeg.exe -i test.avi -vf "drawtext=fontfile=C\\:/Windows/Fonts/arial.ttf:timecode='00\:20\:10\:00':rate=25:text='TCR\:':fontsize=46:fontcolor=white:x=500:y=50: box=1: [email protected]" -f mp4 textts.mp4 

tan simple en código de tiempo - ponga su hora de inicio, ¡entonces el conteo va bien! El ejemplo es para Windows

+0

También funciona en OS X dando la ruta correcta a una fuente – kmundnic

1

Aquí está mi solución, y creo que es la correcta, porque evita tener que configurar manualmente la velocidad y le permite formatear la salida.

ffmpeg -i test.mp4 -vf \ 
    "drawtext=fontfile=arialbd.ttf:text='%{pts\:gmtime\:0\:%H\\\:%M\\\:%S}'" test.avi 

Esto produce un sello en el formato HH: MM: SS; puede cambiarlo a lo que desee, usando strftime.

Puede parecer que va a poner una marca de tiempo con gmtime, pero eso no es lo que sucede. En realidad, alimenta el tiempo actual del video, en segundos, a gmtime, produciendo una fecha que es 1/1/1970, y un tiempo que sin embargo es muchos segundos después de la medianoche. Así que solo descarta la porción de fecha y usa la porción de tiempo.

Tome nota del triples escapes dos puntos dentro de la función pts, que tendrá que hacer si lo ingresa como lo hice anteriormente. También puedes ver que copié el archivo de mi fuente para Arial Bold y lo dejé caer directamente en el directorio de trabajo por simplicidad.

Cuestiones relacionadas