Die Konvertierung von RTSP zu RTMP schlägt nach einer bestimmten Zeit nur dann fehl, wenn die IP-Kamera in den Nachtmodus wechselt

Ich habe eine billige IP-Kamera Escam QF002 gekauft, die eine Ausgabe in RTSP erzeugt. Ich möchte es mit einem RTMP- oder HLS-Stream sichern, der von nginx mit dem nginx-rtmp-Modul bereitgestellt wird.

Dazu würde ich den Videostream (h264) kopieren und Audio (pcm_alaw -> aac) transkodieren, indem ich Folgendes verwende:

/usr/bin/ffmpeg -loglevel debug \
  -i 'rtsp://192.168.1.2:554/user=admin&password=******&channel=0&stream=0.sdp?real_stream--rtp-caching=100' \
  -vcodec copy -acodec aac -f flv "rtmp://localhost/escam/stream"

Nach ~260 Sekunden (jedes Mal derselbe Wert) eines erfolgreichen Streams wird keine gültige Ausgabe mehr erzeugt und die Nachricht wird als Spam versendet:

Delay between the first packet and last packet in the muxing queue is 10020000 > 10000000: forcing output

Dies scheint nur zu passieren, wenn sich die Kamera im "Nacht-/Infrarot"-Modus befindet. Einige Unterschiede können protokolliert werden:

Nachtmodus: Die gemeldete Framerate konvergiert auf 13 fps und anfängliche Frames werden mit 488 DTS weitergeleitet

...
[flv @ 0x1d53710] Non-monotonous DTS in output stream 0:0; previous: 488, current: 385; changing to 488. This may result in incorrect timestamps in the output file.
....
frame= 1451 fps= 13 q=-1.0 size=    5357kB time=00:02:11.84 bitrate= 332.8kbits/s speed=1.16x

Tag-Modus: gemeldete fps konvergieren auf 20 fps und anfängliche Frames werden mit 300 DTS übergeben.

Aber jedes Mal, wenn der Eingabestrom definiert ist als:

Stream #0:0, 0, 1/1000: Video: h264 (Main), 1 reference frame ([7][0][0][0] / 0x0007), yuvj420p(pc, bt709, progressive, left), 1280x720 (0x0), 0/1, q=2-31, 20 fps, 13 tbr, 1k tbn, 90k tbc
Stream #0:1, 0, 1/1000: Audio: pcm_alaw ([7][0][0][0] / 0x0007), 8000 Hz, mono, 64 kb/s

Bisher -anermöglicht nur das Deaktivieren des Audiostreams ein kontinuierliches Streaming. Das Kopieren des Streams ohne Neucodierung des Audios ( -acodec copy) oder das Schreiben in eine Datei führt zu demselben Fehler.

Was könnte das Problem sein? Warum ist dies nur für den Nachtmodus spezifisch?


EDIT: Ich denke, ich muss es als einen anderen Thread posten, da sich herausstellt, dass es sich um ein XY-Problem handelt.

Ich denke, das Problem hängt mit dem falschen PTS/DTS für die von RTP zurückgegebenen Videoframes zusammen. FFmpeg meldet, dass der Videoeingang 20 fps hat, während er tatsächlich ~ 13 fps zurückgibt (tbr):

Stream #0:0: Video: h264 (Main), yuvj420p(pc, bt709, progressive), 1280x720, 20 fps, 13 tbr, 90k tbn, 40 tbc

Das Prüfen der Eingabeframes mit ffprobe -show_frames -read_intervals %+100 'rtsp://host/stream'ergibt die folgenden Informationen für Videoframes:

  • pkt_duration_time = 0,05 s, pkt_duration = 4500
  • Increment von pkt_pts ist 6923, Increment von pkt_pts_time ist ~ 0.077s, gleiches gilt für pkt_dts, pkt_dts_time, sowie best_effort_timestamp, best_effort_timestamp_time

Der PTS/DTS muss irgendwie von der Voreinstellung 0,05 neu berechnet werden (ich bin mir nicht sicher, ob das von ffmpeg oder der Quelle selbst gemacht wird). Dieses Intervall ist jedoch im Vergleich zum Audiostream zu klein - wie in der Grafik unten zu sehen ist. Dies führt dazu, dass Video schneller remuxt wird als Audio.

Fragen:

  • Wird RTP h264 DTS/PTS vom Stream selbst angegeben oder von ffmpeg berechnet?
  • Was ist der richtige Weg, um diese so zu ändern, dass sie mit Audio DTS/PTS übereinstimmen?

RTSP

Antworten (1)

Ich habe das Problem gelöst, indem ich die Zeitstempel mit -use_wallclock_as_timestamps 1und von Grund auf neu erstellt habe -fflags +genpts.

/usr/bin/ffmpeg -use_wallclock_as_timestamps 1 -i "rtsp://${source}" -fflags +genpts -vcodec copy -acodec aac -f flv "rtmp://${dest}"

Dies ist nur eine Teillösung bzw. Problemumgehung, da mir noch unklar ist, was dieses Verhalten verursacht.

Ihre Eingabestream-Konfiguration, wie sie im Eingabevideo-Bitstream eingestellt ist, unterscheidet sich vom tatsächlichen Frame-Durchsatz. Tritt während der Nacht oder im Energiesparmodus auf.
Ist dann die gepostete Methode die richtige Lösung, oder sollte ich einen anderen Ansatz in Betracht ziehen? Das Festlegen von variablen fps bei der Eingabe mit -reder Option funktioniert nicht, da es dazu führt, dass mehrere Pakete verworfen werden.