segmento de ffmpeg por tiempo de video en lugar de tiempo de pared

segmento de ffmpeg por tiempo de video en lugar de tiempo de pared

Tengo un sistema que graba video en el disco y, a veces, el sistema presenta un error. Estoy intentando recrear el sistema de grabación en el laboratorio, sin la cámara real (es costosa y no hay repuestos), para intentar replicar el patrón de uso que causa el error.

Tengo problemas para domesticar ffmpeg.

Fondo:

El vídeo se captura en un hilo continuamente desde una URL rtsp:// proporcionada por la cámara adjunta con este comando:

ffmpeg -i rtsp://192.168.0.10/h264 -c copy -map 0 -f segment -segment_time 900 -segment_format mp4 -segment_atclocktime 1 -strftime 1 /tmp/capture-%s.mp4

Esto funciona y produce archivos de vídeo de 15 minutos de duración como se esperaba.

Problema:

En el laboratorio, no tengo la cámara ni la transmisión rtsp://. En su lugar, copié uno de los MP4 capturados del sistema real y lo estoy usando como entrada para ffmpeg. Algo como:

ffmpeg -stream_loop -1 -i capture-1469547000.mp4 -c copy -map 0 -f segment **-{NEED PARAM}** -segment_format mp4 -strftime 1 /tmp/captest-%s.mp4

El -stream_loop -1parámetro hace lo que se espera: lee el archivo de entrada (que tiene una duración de 15 minutos) y produce un flujo de salida infinito. Ésta es una aproximación razonable de la lectura del flujo rtsp://.

Lo que no puedo entender es qué parámetros usar para hacer que este sistema de laboratorio segmente el video en fragmentos de 15 minutos de duración tal como lo hace el sistema real. Lo que espero es una secuencia de archivos de salida, cada uno de ellos aproximadamente del mismo tamaño que el archivo de entrada.

Intento #1

El uso -segment_time 900parece indicar que a) se desea utilizar el valor del reloj de pared de 15 minutos ob) se ignora. Dado que copiar desde un MP4 existente es mucho más rápido que copiar desde la secuencia rtsp://, el archivo de captura resultante es muchas copias del original.

Intento #2

Usé este comando

ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 capture-1469547000.mp4

para determinar que el archivo de entrada tiene 13494 fotogramas.

El uso -segment_frames 13494parece ignorarse y la salida no está segmentada en absoluto.

Intento #3

He leído mucha documentación de ffmpeg y me falta lo que necesito o no existe.

El uso -ss *position* -t *duration*no realiza grabación ni segmentación continua de la salida.

Petición de socorro

¿Qué parámetros debo usar para que la segmentación a) funcione yb) tenga una duración de video de 15 minutos?

Posible complicación

Las marcas de tiempo (¿DTS?) en el ejemplo MP4 no son "buenas" porque este error se produce continuamente:

[segmento @ 0x2abc7c0] DTS no monótono en el flujo de salida 0:0; anterior: 80990160, actual: -74730276972; cambiando a 80990161. Esto puede dar como resultado marcas de tiempo incorrectas en el archivo de salida.  
DTS 191648787, siguiente:-830336344130 st:0 eliminación no válida  
PTS 191648787, siguiente:-830336344130 descartando st no válido:0

Sin embargo, no necesito que los archivos de vídeo resultantes se reproduzcan o estén intactos, por lo que lo ignoro, a menos que afecte la segmentación que necesito recrear.

Informacion adicional

versión ffmpeg:

\# /usr/share/local/bin/ffmpeg -versión  
Versión de ffmpeg N-79587-g9f9c833 Copyright (c) 2000-2016 los desarrolladores de FFmpeg  
construido con gcc 4.8 (Ubuntu/Linaro 4.8.2-16ubuntu4)  
configuración: --prefix=/home/t/dev/j/third-party/ffmpeg/../build --cross-prefix=/usr/bin/arm-linux-gnueabihf- --cpu=armv7-a - -disable-shared --enable-static --enable-gpl --enable-pthreads --enable-nonfree --enable-libx264 --enable-filters --extra-libs=-static --extra-cflags=-- estático --enable-cross-compile --target-os=linux --disable-inline-asm --arch=armv7 --disable-debug --disable-altivec --disable-sse --disable-armv6 --disable -armv6t2 --disable-mmx --disable-neon --disable-amd3dnow --disable-thumb --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/../build/ lib --extra-cflags=-I/home/t/dev/j/third-party/ffmpeg/../build/include --extra-ldflags=-L/home/t/dev/j/third-party /ffmpeg/libavcodec --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavdevice --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg /libavfilter --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavformat --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavresample --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavutil --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libswscale -- extra-ldflags=-lx264 --extra-ldflags=-lm --extra-ldflags=-ldl --extra-cflags='-fpic -mthumb'  
libavutil 55. 22.101 / 55. 22.101  
libavcodec 57. 38.100 / 57. 38.100  
formato libav 57. 34.103 / 57. 34.103  
dispositivo libav 57. 0.101 / 57. 0.101  
filtro libav 6. 44.100 / 6. 44.100  
escalalibsw 4. 1.100 / 4. 1.100  
bibliotecaswresample 2. 0.101 / 2. 0.101  
libpostproc 54. 0.100 / 54. 0.100

Respuesta1

segment_timeDeberia trabajar. Se refiere a la duración del segmento, no al reloj de pared.

La ubicación de los fotogramas clave puede estar interfiriendo, así que intenta

ffmpeg -fflags +genpts -i capture-1469547000.mp4 -c copy -map 0 -f segment -segment_time 900 -segment_format mp4 -break_non_keyframes 1 -strftime 1 /tmp/capture-%s.mp4

Eliminé la opción stream_loop ya que actualmente hay un error de generación de marca de tiempo relacionado con su uso. Eso también puede estar interfiriendo aquí.

Si necesita una secuencia realmente larga con la que trabajar, utilice el demuxer concat.

Crear un archivo de texto

file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'

Y luego usar

ffmpeg -f concat -i list.txt -c copy ...

Respuesta2

Tengo una solución que funciona.

La causa principal

El archivo de captura de muestra que guardé resultó no ser "bueno" para los propósitos que quiero (un flujo de entrada infinito), aunque por lo demás es un buen archivo de video (se reproduce bien, aunque no se puede buscar). El problema parece estar relacionado con las marcas de tiempo y posiblemente también con uno o más errores con el muxer de segmentos.

La solución

yo corrí

ffmpeg -i capture-1469547000.mp4 -c copy captemp.mp4

Al usarlo captemp.mp4, obtengo una buena transmisión con stream_loop o concat muxer.

No estoy seguro de cuál es la diferencia entre capture-1469547000.mp4 y captemp.mp4; AtomicParsley muestra que captemp.mp4 es 12 bytes más corto en el átomo 'elst'.

Echar otro vistazo a mi configuración original y agregar segment_listfue revelador: los segmentos se estaban generando correctamente pero muy, muy rápidamente. Simplemente se estaban agregando al archivo de segmento existente en lugar de crear uno nuevo. Eso es en parte culpa de...

error potencial de strftime

Estaba usando strftimeun %sformato. strftime resultó estar usando la hora del reloj de la máquina host, en lugar de la hora dentro del segmento de video. Esto es cierto incluso en el caso de "trabajo"; En su lugar , cambié a usar el %dformato del muxer de segmento.

Probablemente esto sea un error y la razón por la que, en el caso de que no funcionara, los segmentos se agregaban entre sí.

Estoy bastante seguro de que usar la -rebandera solucionaría este problema al ralentizar el procesamiento, pero en realidad quiero un procesamiento acelerado. Entonces no he probado esto.

información relacionada