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

2

Eu tenho um sistema que grava vídeo em disco e, às vezes, o sistema tem um erro. Estou tentando recriar o sistema de gravação no laboratório, sem a câmera real (é cara e não há peças de reposição), 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 um URL rtsp: // fornecido 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 15 minutos de duração, conforme o esperado.

Problema:

No laboratório, não tenho a câmera nem o rtsp: // stream. Em vez disso, copiei um dos MP4s de captura do sistema real e estou usando isso como uma 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: ele lê o arquivo de entrada (com 15 minutos de duração) e produz um fluxo de saída infinito. Essa é uma aproximação razoável da leitura do rtsp: // stream.

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

Tentativa nº 1

O uso de -segment_time 900aparece para a) deseja 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 rtsp: // stream, o arquivo de captura resultante é composto por muitas cópias do original.

Tentativa # 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 13494 quadros.

O uso -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 ele 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 obter a segmentação para a) trabalho eb) 15 minutos de duração do vídeo?

Possível complicação

Os registros de data e hora (DTS?) No exemplo MP4 não são 'bons', pois esse erro é produzido continuamente:

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

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

Mais informações

versão ffmpeg:

\ # / usr / share / local / bin / ffmpeg -version  
versão ffmpeg N-79587-g9f9c833 Copyright (c) 2000-2016 the FFmpeg developers  
construído com o gcc 4.8 (Ubuntu / Linaro 4.8.2-16ubuntu4)  
configuração: --prefix = / home / t / dev / j / de terceiros / 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 = -estatic --extra-cflags = - static --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 / terceiros / ffmpeg /../ build / lib --extra-cflags = -I / home / t / dev / j / de terceiros / ffmpeg / ../ build / include --extra-ldflags = -L / home / t / dev / j / de terceiros / ffmpeg / libavcodec --extra-ldflags = -L / home / t / dev / j / de terceiros / ffmpeg / libavdevice --extra-ldflags = -L / home / t / dev / j / terceiros / ffmpeg / libavfilter --extra-ldflags = -L / home / t / dev / j / terceiros / ffmpeg / libavformat --extra-ldflags = -L / home / t / dev / j / de terceiros / ffmpeg / libavresample --extra-ldflags = -L / home / t / dev / j / de terceiros / ffmpeg / libavutil - extra-ldflags = -L / home / t / dev / j / de terceiros / ffmpeg / libswscale --extra-ldflags = -lx264 --extra-ldflags = -lm --extra-ldflags = -ldl --extra- cflags = '- fpic -mthumb'-fpic -mthumb '-fpic -mthumb '  
libavutil 55. 22.101 / 55. 22.101  
libavcodec 57. 38.100 / 57. 38.100  
libavformat 57. 34.103 / 57. 34.103  
dispositivo de biblioteca 57. 0.101 / 57. 0.101  
libavfilter 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
studog
fonte

Respostas:

1

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

Eu removi a opção stream_loop, pois atualmente há um erro de geração de carimbo de data e hora relacionado ao seu uso. Isso pode estar interferindo aqui também.

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

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 ...
Gyan
fonte
Obrigado pela ajuda, muito apreciada. O concat desmuxer funciona. Usar -break_non_keyframes 1não muda o comportamento. :-( Todas as combinações de {stream_loop, concat} x {<null>, break_non_keyframes} o comportamento é o mesmo: existe um primeiro segmento criado com aproximadamente o dobro do tamanho do arquivo de entrada (eu não estava esperando o suficiente ontem) , e o segundo segmento parece crescer sem limite, para pelo menos mais de 3x o tamanho do primeiro segmento. O tempo de vídeo da entrada não está sendo respeitado. Vou examinar os DTS não monótonos 'erros mais de perto.'
studog 11/08/16
0

Eu tenho uma solução funcional.

A causa raiz

O arquivo de captura de amostra que eu salvei acabou por não ser 'bom' para os propósitos que eu quero (um fluxo de entrada infinito), embora seja um bom arquivo de vídeo de outra forma (ele funciona bem, embora não seja possível procurar). O problema parece estar relacionado aos carimbos de data e hora e, possivelmente, a um ou mais erros do muxer de segmento.

A solução

Eu corri

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

Usando, em captemp.mp4vez disso, recebo um bom fluxo com stream_loop ou o concat muxer.

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

Olhar novamente para 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 ...

bug em potencial do strftime

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

Provavelmente, isso é um bug, e por que, no caso não útil, os segmentos foram anexados um ao outro.

Estou bastante certo de que o uso do -resinalizador contornaria esse problema, retardando o processamento, mas na verdade eu quero um processamento acelerado. Então, eu não tentei isso.

studog
fonte