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 -1
pará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 900
parece 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 13494
parece 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_time
Deberia 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_list
fue 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 strftime
un %s
formato. 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 %d
formato 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 -re
bandera solucionaría este problema al ralentizar el procesamiento, pero en realidad quiero un procesamiento acelerado. Entonces no he probado esto.