2 votes

Ffmpeg segmente par temps de vidéo au lieu de temps mural

J'ai un système qui enregistre des vidéos sur disque, et parfois le système rencontre une erreur. J'essaie de recréer le système d'enregistrement en laboratoire, sans la caméra réelle (c'est cher et il n'y a pas de pièces de rechange), afin de tenter de reproduire le modèle d'utilisation qui provoque l'erreur.

J'ai du mal à maîtriser ffmpeg.

Contexte:

La vidéo est capturée en continu dans un thread à partir d'une URL rtsp:// fournie par la caméra connectée avec cette commande :

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

Cela fonctionne et produit des fichiers vidéo de 15 minutes de durée comme prévu.

Problème:

En laboratoire, je n'ai ni la caméra ni le flux rtsp://. J'ai plutôt copié l'un des fichiers MP4 capturés du système réel et l'utilise comme entrée pour ffmpeg. Quelque chose comme :

ffmpeg -stream_loop -1 -i capture-1469547000.mp4 -c copy -map 0 -f segment **-{PARAMÈTRE NÉCESSAIRE}** -segment_format mp4 -strftime 1 /tmp/captest-%s.mp4

Le paramètre -stream_loop -1 fait ce qui est attendu : il lit à partir du fichier d'entrée (qui dure 15 minutes) et produit un flux de sortie infini. C'est une approximation raisonnable de la lecture à partir du flux rtsp://.

Ce que je n'arrive pas à comprendre sont les paramètres à utiliser pour que ce système de laboratoire segmente la vidéo en morceaux de 15 minutes, tout comme le fait le système réel. Ce que je m'attends à obtenir est une séquence de fichiers de sortie à peu près de la même taille que le fichier d'entrée.

Tentative n°1

L'utilisation de -segment_time 900 semble soit a) vouloir utiliser la valeur de l'horloge murale de 15 minutes, soit b) être ignorée. Comme copier à partir d'un MP4 existant est beaucoup plus rapide que copier à partir du flux rtsp://, le fichier de capture résultant est en réalité de nombreuses copies de l'original.

Tentative n°2

J'ai utilisé cette commande

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

pour déterminer que le fichier d'entrée comporte 13494 images.

Utiliser -segment_frames 13494 semble être ignoré, et la sortie n'est pas du tout segmentée.

Tentative n°3

J'ai lu une bonne partie de la documentation de ffmpeg et soit je ne trouve pas ce dont j'ai besoin, soit cela n'existe pas.

Utiliser -ss *position* -t *durée* ne permet pas l'enregistrement continu et la segmentation de la sortie.

Demande d'aide

Quels paramètres devrais-je utiliser pour que la segmentation fonctionne a) et soit de 15 minutes de durée de vidéo?

Complication possible

Les horodatages (DTS ?) dans l'exemple de MP4 ne sont pas 'bons' en ce sens qu'une erreur est constamment produite :

\[segment @ 0x2abc7c0\] Non-monotone DTS dans le flux de sortie 0:0; précédent : 80990160, actuel : -74730276972; passage à 80990161. Cela peut entraîner des horodatages incorrects dans le fichier de sortie.  
DTS 191648787, suivant : -830336344130 st : 0 invalid dropping  
PTS 191648787, suivant : -830336344130 invalid dropping st : 0

Cependant, je n'ai pas besoin que les fichiers vidéo résultants puissent être lus ou intacts, donc j'ignore cela, sauf si cela affecte la segmentation que je dois recréer.

Informations supplémentaires

Version de 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

1voto

Gyan Points 29437

segment_time devrait fonctionner. Il fait référence à la durée du segment, pas à l'horloge murale.

L'emplacement des images clés peut poser problème, donc essayez

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

J'ai supprimé l'option stream_loop car il existe actuellement un bug de génération de timestamp lié à son utilisation. Cela pourrait également interférer ici.

Si vous avez besoin de travailler avec un flux vraiment long, utilisez le multiplexeur concat.

Créez un fichier texte

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'

Et ensuite utilisez

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

0voto

studog Points 313

J'ai une solution fonctionnelle.

La cause racine

Le fichier de capture d'exemple que j'ai enregistré s'est avéré ne pas être 'bon' pour les besoins que je veux (un flux d'entrée infini), même s'il s'agit par ailleurs d'un bon fichier vidéo (il se lit bien, bien qu'il ne soit pas déplaçable). Le problème semble être lié aux horodatages, et aussi éventuellement à un ou plusieurs bugs avec le segment muxer.

La solution

J'ai exécuté

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

En utilisant captemp.mp4 à la place, j'obtiens un bon flux avec soit stream_loop soit le concat muxer.

Je ne suis pas sûr de la différence entre capture-1469547000.mp4 et captemp.mp4; AtomicParsley montre que captemp.mp4 est 12 octets plus court dans l'atome 'elst'.

Revoir ma configuration originale et ajouter segment_list était révélateur : les segments étaient générés correctement mais très rapidement. Ils étaient simplement ajoutés au fichier de segment existant au lieu d'en créer un nouveau. C'est en partie la faute de...

Potentiel bug de strftime

J'utilisais strftime avec un format %s. Il s'est avéré que strftime utilisait l'heure de l'horloge de la machine hôte, plutôt que l'heure à l'intérieur du segment vidéo. C'est vrai même dans le cas 'fonctionnel'; j'ai basculé sur l'utilisation du formatage %d du segment muxer à la place.

C'est probablement un bug, et c'est pourquoi dans le cas non fonctionnel les segments s'ajoutaient les uns aux autres.

Je suis assez sûr que l'utilisation du drapeau -re contournerait ce problème en ralentissant le traitement, mais je veux en fait un traitement accéléré. Donc je n'ai pas essayé cela.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X