ffmpeg segment por video-time em vez de wall-time

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 (é caro e não há peças de reposição), para tentar replicar o padrão de uso que causa o erro.

Estou com problemas para domar o ffmpeg.

Histórico:

O vídeo é capturado em um thread continuamente a partir de um URL rtsp: // fornecido pela câmera conectada 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, como esperado.

Problema:

No laboratório, não tenho a câmera nem o fluxo rtsp: //. Eu 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 parâmetro -stream_loop -1 faz o que é esperado: ele 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 partes de 15 minutos de duração, exatamente como o sistema real faz. O que eu espero é uma sequência de arquivos de saída com aproximadamente o mesmo tamanho que o arquivo de entrada.

Tentativa nº 1

Usar -segment_time 900 aparece como a) deseja usar o valor de clock de 15 minutos ou b) ser ignorado. Como copiar a partir 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 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 o arquivo de entrada tenha 13494 quadros.

A utilização de -segment_frames 13494 parece ser ignorada e a saída não é segmentada de todo.

Tentativa nº 3

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

O uso de -ss *position* -t *duration* não faz gravações contínuas & segmentação de saída.

Pedido de ajuda

Quais parâmetros devo usar para obter a segmentação para a) trabalho eb) ter 15 minutos de duração do vídeo?

Possível complicação

Os timestamps (DTS?) no exemplo MP4 não são 'bons' porque esse erro é produzido continuamente:

[segment @ 0x2abc7c0] Non-monotonous DTS in output stream 0:0; previous: 80990160, current: -74730276972; changing to 80990161. This may result in incorrect timestamps in the output file.  
DTS 191648787, next:-830336344130 st:0 invalid dropping  
PTS 191648787, next:-830336344130 invalid dropping st:0

No entanto, não preciso que os arquivos de vídeo resultantes sejam 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 ffmpeg:

\# /usr/share/local/bin/ffmpeg -version  
ffmpeg version N-79587-g9f9c833 Copyright (c) 2000-2016 the FFmpeg developers  
built with gcc 4.8 (Ubuntu/Linaro 4.8.2-16ubuntu4)  
configuration: --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=--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/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  
libavformat    57. 34.103 / 57. 34.103  
libavdevice    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
    
por studog 10.08.2016 / 21:34

2 respostas

0

Eu tenho uma solução de trabalho.

A causa raiz

O arquivo de captura de amostra que salvei acabou não sendo 'bom' para os propósitos que eu quero (um fluxo de entrada infinito), embora seja um bom arquivo de vídeo (ele funciona bem, embora não seja procurado). O problema parece estar relacionado aos timestamps, e também possivelmente um ou mais bugs com o muxer do segmento.

A solução

eu corri

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

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

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

Analisando novamente minha configuração original, e adicionando segment_list foi 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 é em parte culpa de ...

erro potencial de strftime

Eu estava usando strftime com um formato %s . O strftime acabou usando o tempo do relógio da máquina host, em vez do tempo de dentro do segmento de vídeo. Isso é verdade mesmo no caso de 'trabalho'; Eu mudei para usar a formatação %d do muxer do segmento.

Este é provavelmente um bug, e porque no caso não funcional os segmentos foram anexados uns aos outros.

Tenho quase certeza de que usar o -re flag poderia solucionar esse problema diminuindo o processamento, mas na verdade quero um processamento acelerado. Então eu não tentei isso.

    
por 15.08.2016 / 16:48
0

segment_time deve funcionar. Refere-se à duração do segmento, não ao relógio de parede.

A veiculação de quadros-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 há atualmente um bug de geração de timestamp relacionado ao seu uso. Isso pode estar interferindo aqui também.

Se você precisar de um fluxo muito longo para trabalhar, use o demuxer de concatenação.

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, em seguida, use

ffmpeg -f concat -i list.txt -c copy ...
    
por 10.08.2016 / 22:13

Tags