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 -1
parâ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 900
parece 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 13494
parece 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_time
Deveria 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_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 é parcialmente culpa de...
potencial bug do strftime
Eu estava usando strftime
com um %s
formato. 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 %d
formataçã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 -re
sinalizador solucionaria esse problema, desacelerando o processamento, mas na verdade quero um processamento acelerado. Então eu não tentei isso.