all posts
260905 · September 5, 2026 · 7 min read

Inspecting an RTSP Stream with ffprobe (IPStreamMedia #3)

FFmpeg is awesome! 🤩

UE5 plugin FFmpeg RTSP C++
SD
Sanjyot Dahale · Unreal Engine Developer

Back from the dead

I’ve been AFK since the last devlog as I was away on a much-needed vacation 🚞. Before I left I finished most of the theoretical pre-requisites, and now I’m going to begin some actual practical work — which starts with some tests to see some practical data supporting the theory we discussed in the previous devlogs.

Probing

Before beginning the implementation of the actual plugin I wanted to ensure if the external dependencies like FFmpeg and my RTSP test sources were working the way they should. Also this was a great opportunity to practically dig inside an RTSP stream and check if the I-frames, P-frames and GOPs actually exist or if they are just a conspiracy theory 👽.

So I fired up a terminal and wrote,

PS> ffmpeg

Well, obviously I had to check if FFmpeg was installed 🙃.

After a great success on that it was time to start probing,

PS> ffprobe -hide_banner 'rtsp://MY_RTSP_URL'

Input #0, rtsp, from 'rtsp://MY_RTSP_URL':
  Metadata:
    title           : Media Server
  Duration: N/A, start: 0.040000, bitrate: N/A
  Stream #0:0: Video: hevc (Main), yuv420p(tv), 1280x720, 25 fps, 25 tbr, 90k tbn, start 0.040000

So the reponse of the ffprobe command gave me the top-level details of the RTSP stream. It tells me that this video stream is a 1280 x 720px feed running at 25fps which encoded in H.265 (hevc) with yuv420(tv) pixel format.

Similar to the video feed denoted as “Stream #0:0”, if your feed has audio it will also show up as another stream in the above output.

Now let’s go one step deeper,

PS> ffprobe -hide_banner -show_frames -select_streams v -read_intervals "%+5" 'rtsp://MY_RTSP_URL'

Input #0, rtsp, from 'rtsp://MY_RTSP_URL':
  Metadata:
    title           : Media Server
  Duration: N/A, start: 0.040000, bitrate: N/A
  Stream #0:0: Video: hevc (Main), yuv420p(tv), 1280x720, 25 fps, 25 tbr, 90k tbn, start 0.040000

[FRAME]
media_type=video
stream_index=0
key_frame=1
...
pkt_size=142937     # Size of the frame
width=1280
height=720
...
pict_type=I         # I-frame
...
[/FRAME]
[FRAME]
...
key_frame=0
...
pkt_size=1242       # Size of the frame (much smaller than the I-frame)
...
pict_type=P         # P-frame
...
[/FRAME]
[FRAME]
...
key_frame=0
...
pkt_size=963
...
pict_type=P         # P-frame
...
[/FRAME]

[ ... 47 more P-frames, ranging 800-4,000 bytes ... ]

[FRAME]
media_type=video
stream_index=0
key_frame=1
...
pkt_size=143316
width=1280
height=720
...
pict_type=I         # I-frame : GOP Length = 50 frames (2 seconds)!
...
[/FRAME]

The above command basically reads 5 seconds of the RTSP stream and dumps a per frame data of the stream for us to review. Here we can clearly see a few things practically that we discussed in the previous devlog,

  • First of all we can see that the first frame recorded is an I-frame, which means that even if the RTSP connection was successful the stream could be only be decoded after the first I-frame arrived.
  • We can also see that the first I-frame was then followed immediately by a P-frame, which denotes the start of a new GOP. We have 48 more frames after that which are also P-frames which denotes that the GOP length is 50 frames which is 2 seconds at 25fps.
  • We can also see that the size of each P-frame is much smaller than the size of one I-frame — which is massive in comparison.
  • Finally we can see that after 50 frames a new I-frame has arrived which marks the beginning of the next GOP.

If you are ever trying this command yourself, FYI the output is super long as there are many parameters inside each [FRAME] [/FRAME] block which I have omitted here. Just append the above command with “ > output.txt” at the end so that this entire output is stored in a .txt file. The final codeblock should look like this,

PS> ffprobe -hide_banner -show_frames -select_streams v -read_intervals "%+5" 'rtsp://MY_RTSP_URL' > output.txt

Enough probing, let’s watch

Even though we have used ffprobe to see the data inside the RTSP stream in text format, it has not shown us the video feed playing as an actual video. To do that we can run this command,

ffplay -rtsp transport tcp "rtsp://MY_RTSP_URL"

This opened a new window on my screen with the video feed running live inside it. You have to believe me when I say it works because I cannot post a screenshot of the video playback here due to obvious privacy concerns.

What’s Next ?

Pre-requisite theory and practicals are now complete 🙌. It’s time to begin working on the actual plugin.

Until now I was writing these devlogs parallel to the research and experiments I was doing, but now as the real work begins I guess the future devlogs will be spaced out a bit more (maybe once a week ?! ), but I will definitely try to stay disciplined and keep publishing my progress.

This is the Github repo for the actual project by the way.

That’s all for this one. Cheers! 🍻