J'utilise ffmpeg pour lire un flux RTSP h264 à partir d'une caméra IP Cisco 3050 et le réencoder sur le disque en tant que h264 (il y a des raisons pour lesquelles je n'utilise pas seulement -codec:copy
).
La version ffmpeg est la suivante:
ffmpeg version 3.2.6 Copyright (c) 2000-2017 the FFmpeg developers
built with gcc 6.3.0 (Alpine 6.3.0)
J'ai également essayé avec ffmpeg 2.8.14-0ubuntu0.16.04.1 et le dernier ffmpeg construit à partir de la source (j'ai utilisé this commit) et je vois le même comportement que ci-dessous.
La commande que j'exécute est:
ffmpeg -rtsp_transport udp -i 'rtsp://<user>:<pw>@<ip>:554/StreamingSetting?version=1.0&action=getRTSPStream&ChannelID=1&ChannelName=Channel1' -r 10 -c:v h264 -crf 23 -x264-params keyint=60:min-keyint=60 -an -f ssegment -segment_time 60 -strftime 1 /output/%Y%m%d_%H%M%S.ts -abort_on empty_output
J'obtiens une variété d'erreurs à un taux assez constant d'au moins une par seconde. Voici un exemple:
[rtsp @ 0x7f268c5e9220] max delay reached. need to consume packet
[rtsp @ 0x7f268c5e9220] RTP: missed 40 packets
[h264 @ 0x55b1e115d400] left block unavailable for requested intra mode
[h264 @ 0x55b1e115d400] error while decoding MB 0 12, bytestream 114567
[h264 @ 0x55b1e115d400] concealing 3889 DC, 3889 AC, 3889 MV errors in I frame
La plus courante est "erreur lors du décodage de MB x x, bytestream x". Cela correspond à une corruption grave du fichier vidéo lors de la lecture.
Je vois de nombreuses références à ce message d'erreur sur stackoverflow et ailleurs, mais je n'ai pas encore trouvé d'explication ou de solution satisfaisante. Cela vient de cette ligne qui semble correspondre aux données manquantes à la fin du flux. 'bloc gauche indisponible' vient de ici et ressemble également à des données manquantes.
D'autres ont suggéré d'utiliser -rtsp_transport tcp
à la place ( 1 , 2 , ) ce qui dans mon cas donne juste un mélange légèrement différent d'erreurs, et toujours une corruption vidéo:
[h264 @ 0x557923191b00] left block unavailable for requested intra4x4 mode -1
[h264 @ 0x557923191b00] error while decoding MB 0 28, bytestream 31068
[h264 @ 0x557923191b00] concealing 2609 DC, 2609 AC, 2609 MV errors in I frame
[rtsp @ 0x7f88e817b220] CSeq 5 expected, 0 received.
En utilisant Wireshark, j'ai confirmé qu'en UDP et en TCP, tous les paquets arrivent de l'appareil photo au PC (séquentiel RTP numéros de séquence sans aucun) manquant), ce qui me fait penser que les données sont perdues après leur arrivée à ffmpeg.
Je vois également un comportement similaire lors de l'exécution de la même commande contre un appareil photo Panasonic WV-SFV110, mais avec des erreurs moins fréquentes dans l'ensemble. Le passage d'UDP à TCP sur l'appareil photo Panasonic réduit mais n'élimine pas complètement les erreurs/corruption.
J'ai également essayé une commande similaire avec VLC et obtenu des erreurs similaires (cvlc rtsp://<user>:<pw>@<ip>/MediaInput/h264 :sout='#transcode{vcodec=h264}:std{access=file, mux=ts, dst="output.ts"}
) - sans doute le code n'a pas beaucoup divergé depuis libav dérivé de ffmpeg.
La caméra est branchée directement sur un port PoE du PC afin que la congestion du réseau ne puisse pas être un problème. Étant donné que le PC a suffisamment de CPU pour continuer à encoder le flux en direct, il me semble un problème avec ffmpeg qu'il supprime toujours les données du flux TCP.
Qualitativement, plusieurs facteurs semblent aggraver le problème:
-codec:copy
élimine toutes les erreurs sauf quelques-unes pendant le démarrage de ffmpeg)Que signifie l'erreur? Et que puis-je faire à ce sujet?
Il semble que la perte de paquets soit un problème. Une résolution vidéo plus élevée et un mouvement plus important augmentent tous deux le débit binaire du flux vidéo codé, ce qui augmentera la perte de vos paquets. Selon le paquet perdu, vous verrez différentes erreurs dans le processus de décodage comme vous l'avez indiqué dans votre message.
La charge système plus élevée exécutant ffmpeg indique également que votre carte réseau peut être en train de perdre des paquets, par exemple ffmpeg met trop de temps à les lire pendant qu'il est occupé à transcoder la vidéo.
La première question est quelle est la topologie de votre réseau? Le streaming sur Internet public est beaucoup plus difficile que le streaming sur votre LAN. Quels types de commutateurs/routeurs se trouvent sur le réseau?
Question suivante, à quel débit binaire votre caméra est-elle diffusée? Essayez de réduire cela et vérifiez les résultats. Soyez systématique dans votre approche, c'est-à-dire.
La prochaine chose que j'essaierais de faire est d'augmenter la taille des tampons récepteurs. Bien que je ne sois pas familier avec ffmpeg, il semble que vous pouvez le configurer via recv_buffer_size
Comme indiqué ici . Vous devez ensuite déterminer une taille assez grande en fonction de la configuration de votre caméra pour stocker par exemple quelques (5?) secondes de données vidéo. Vérifiez s'il y a moins d'artefacts lorsque vous augmentez la taille de la mémoire tampon du récepteur ou des périodes plus longues sans artefacts.
Bien sûr, si votre processeur est trop lent pour transcoder la vidéo en temps réel, vous manquerez d'espace tôt ou tard, auquel cas, vous devrez peut-être transcoder à une résolution/débit binaire inférieur ou utiliser des paramètres d'encodeur moins intensifs, etc. ou exécutez le transcodage sur une machine plus rapide.
Notez également que l'ajustement de la taille de la mémoire tampon du récepteur ne compensera pas la perte de paquets se produisant sur Internet public, donc ce qui précède aidera à supposer que vous diffusez en continu sur un réseau local qui prend en charge le débit binaire de la caméra. Si vous dépassez la bande passante du réseau, vous pouvez vous attendre à une perte de paquets. Dans ce cas, le streaming sur TCP pourrait aider quelque peu (au moins jusqu'à ce que le tampon du récepteur déborde éventuellement).
Plus de choses que vous pouvez essayer si ce qui précède n'aide pas ou ne résout pas complètement le problème:
En résumé, vous avez une architecture de pipeline et vous devez déterminer où se produit la perte dans le pipeline:
camera -> network -> receiver buffer (OS) -> application (ffmpeg)
En regardant le message d'erreur initial:
[rtsp @ 0x7f268c5e9220] max delay reached. need to consume packet
[rtsp @ 0x7f268c5e9220] RTP: missed 40 packets
Je suppose que vous perdez des paquets UDP. Les autres messages d'erreur H.264 sont dus à la réception d'un train de bits incomplet. Maintenant, la clé est d'isoler le problème. Votre réseau perd-il des paquets? Ou votre serveur est-il trop lent ou surchargé pour recevoir l'UDP (RTP).
Je vérifierais d'abord la taille du tampon UDP de votre système d'exploitation. https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Web_Platform/5/html/Administration_And_Configuration_Guide/jgroups-perf-udpbuffer.html
Si l'augmentation de la taille du tampon UDP n'aide pas - utilisez ffmpeg avec -codec:copy
pour réduire la charge du processeur. Avez-vous toujours des erreurs? Puisque vous voulez recoder, pensez à utiliser Intel Quicksync -vcodec h264_qsv
ou un autre encodeur matériel réduisant votre charge CPU.
La question n'est pas tant de savoir si le PC a assez de CPU . Mais plus sur l'identification du goulot dans le pipeline de traitement. Votre encodeur H.264 (x264) peut sur-abonner votre CPU afin que vous obteniez des charges de pointe momentanées qui entraînent des pertes de paquets. Essayez de limiter le nombre de threads pour x264 et/ou de réduire la qualité à "rapide" ou "plus rapide".