segmento ffmpeg por tempo de vídeo em vez de tempo de parede

segmento ffmpeg por tempo de vídeo em vez de tempo de parede

Eu tenho um sistema que grava vídeo em disco e às vezes o sistema apresenta um erro. Estou tentando recriar o sistema de gravação em laboratório, sem a câmera propriamente dita (é cara e não tem peças sobressalentes), para tentar replicar o padrão de uso que causa o erro.

Estou tendo problemas para domar o ffmpeg.

Fundo:

O vídeo é capturado em um thread continuamente a partir de uma URL rtsp:// fornecida pela câmera anexada com 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

Isso funciona e produz arquivos de vídeo com duração de 15 minutos conforme o esperado.

Problema:

No laboratório não tenho a câmera nem o stream rtsp://. Em vez disso, copiei um dos MP4s de captura do sistema real e estou usando-o como entrada para o 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

O -stream_loop -1parâmetro faz o que é esperado: lê o arquivo de entrada (que tem 15 minutos de duração) e produz um fluxo de saída infinito. Esta é uma aproximação razoável da leitura do fluxo rtsp://.

O que não consigo descobrir é quais parâmetros usar para fazer com que esse sistema de laboratório segmente o vídeo em pedaços de 15 minutos de duração, assim como o sistema real faz. O que espero é uma sequência de arquivos de saída, cada um com aproximadamente o mesmo tamanho do arquivo de entrada.

Tentativa nº 1

Usando -segment_time 900parece a) querer usar o valor do relógio de parede de 15 minutos ou b) ser ignorado. Como copiar de um MP4 existente é muito mais rápido do que copiar do fluxo rtsp: //, o arquivo de captura resultante é muitas cópias do original.

Tentativa nº 2

Eu usei esse 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 se o arquivo de entrada possui 13.494 quadros.

Using -segment_frames 13494parece ser ignorado e a saída não é segmentada.

Tentativa nº 3

Eu li um monte de documentação do ffmpeg e estou perdendo o que preciso ou não existe.

O uso -ss *position* -t *duration*não faz gravação contínua e segmentação de saída.

Peça ajuda

Quais parâmetros devo usar para que a segmentação a) funcione eb) tenha 15 minutos de duração do vídeo?

Possível complicação

Os carimbos de data e hora (DTS?) no exemplo MP4 não são 'bons' porque este erro é produzido continuamente:

[segmento @ 0x2abc7c0] DTS não monótono no fluxo de saída 0:0; anterior: 80990160, atual: -74730276972; alterando para 80990161. Isso pode resultar em carimbos de data/hora incorretos no arquivo de saída.  
DTS 191648787, próximo: -830336344130 st:0 eliminação inválida  
PTS 191648787, próximo: -830336344130 eliminação inválida de st:0

No entanto, não preciso que os arquivos de vídeo resultantes sejam realmente reproduzidos ou estejam intactos, por isso estou ignorando isso, a menos que esteja afetando a segmentação que preciso recriar.

Mais informações

versão do ffmpeg:

\# /usr/share/local/bin/ffmpeg -versão  
versão ffmpeg N-79587-g9f9c833 Copyright (c) 2000-2016 os desenvolvedores do FFmpeg  
construído com gcc 4.8 (Ubuntu/Linaro 4.8.2-16ubuntu4)  
configuração: --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/terceiro/ffmpeg/libavutil --extra-ldflags=-L/home/t/dev/j/terceiro/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  
libswscale 4.1.100 / 4.1.100  
libswresample 2.0,101 / 2.0,101  
libpostproc 54.0,100 / 54.0,100

Responder1

segment_timeDeveria trabalhar. Refere-se à duração do segmento, não ao relógio de parede.

O posicionamento do quadro-chave pode estar atrapalhando, então tente

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

Removi a opção stream_loop porque atualmente há um bug de geração de carimbo de data/hora relacionado ao seu uso. Isso pode estar interferindo aqui também.

Se você precisar de um fluxo muito longo para trabalhar, use o desmultiplicador concat.

Crie um arquivo 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'

E então use

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

Responder2

Eu tenho uma solução funcional.

A causa raiz

O arquivo de captura de amostra que salvei acabou não sendo 'bom' para os propósitos que desejo (um fluxo de entrada infinito), embora seja um bom arquivo de vídeo (ele reproduz bem, embora não seja pesquisável). O problema parece estar relacionado aos carimbos de data e hora e também possivelmente a um ou mais bugs no muxer de segmento.

A solução

eu corri

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

Usando captemp.mp4, em vez disso, obtenho um bom fluxo com stream_loop ou concat muxer.

Não tenho certeza qual é a diferença entre capture-1469547000.mp4 e captemp.mp4; AtomicParsley mostra que captemp.mp4 é 12 bytes mais curto no átomo 'elst'.

Dar uma nova olhada na minha configuração original e adicionar segment_listfoi revelador: os segmentos estavam sendo gerados corretamente, mas muito rapidamente. Eles estavam apenas sendo anexados ao arquivo de segmento existente, em vez de criar um novo. Isso é parcialmente culpa de...

potencial bug do strftime

Eu estava usando strftimecom um %sformato. strftime acabou usando a hora do relógio da máquina host, em vez da hora do segmento de vídeo. Isto é verdade mesmo no caso “de trabalho”; Em vez disso , passei a usar a %dformatação do muxer de segmento.

Isso provavelmente é um bug e por que, no caso de não funcionamento, os segmentos estavam anexados uns aos outros.

Tenho quase certeza de que o uso do -resinalizador solucionaria esse problema, desacelerando o processamento, mas na verdade quero um processamento acelerado. Então eu não tentei isso.

informação relacionada