B4J Question How to grab RTSP in console B4J app under Linux ?

peacemaker

Expert
Licensed User
Longtime User
Hi, All
It's needed to grab frames from IP-cam RTSP-stream under Linux, in console server app without window interface.
And to save JPG-frames.

Any solution now in 2022 in B4J under Linux ?
 

peacemaker

Expert
Licensed User
Longtime User
Hmmm, i guess, calling the console ffmpeg can solve this task...
 
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
Solved:

1. Install ffmpeg under Linux
2. Start it from B4J app:
B4X:
Sub Get_Frame()
    Dim URL As String = "rtsp://192.168.1.168:554/ch01/0"
  
    'Dim command As String = "/usr/bin/ffmpeg -rtsp_transport tcp -i " & URL & " -r 1 -vsync 1 -qscale 1 -frames:v 1 -f image2 images_$(date +%F_%H-%M-%S).jpg"
  
    Dim ff As String = "/usr/bin/ffmpeg"
    Dim Args As List
    Args.Initialize
    Args.Add("-rtsp_transport")
    Args.Add("tcp")
    Args.Add("-i")
    Args.Add(URL)
    Args.Add("-r")    'frame rate
    Args.Add("1")
    Args.Add("-vsync")
    Args.Add("1")
    Args.Add("-qscale:v")
    Args.Add("5")    '3=86%, 5=76%
    'Args.Add("-qscale")
    'Args.Add("1")
    Args.Add("-frames:v")
    Args.Add("1")
    Args.Add("-f")
    Args.Add("image2")
    Args.Add("image_" & Get_Stamp & ".jpg")
          
              
    Dim sh As Shell
    sh.Initialize("ffmpeg", ff, Args)
    sh.WorkingDirectory = File.DirApp
  
    Dim res As ShellSyncResult = sh.RunSynchronous(-1)
  
    #if Debug
    Log(res.Success & "; ExitCode = " & res.ExitCode)
    Log("StdOut = " &  res.StdOut)
    Log("StdErr = " &  res.StdErr)
    #end if
End Sub

Sub Get_Stamp As String
    Dim b As String, d, E As Long, f As Float
    DateTime.DateFormat = "yyyy-MM-dd"
    DateTime.TimeFormat = "HH-mm-ss"

    d = DateTime.Now
    E = d - DateTime.TimeParse(DateTime.Time(d))
    f = E/DateTime.TicksPerSecond
    b = NumberFormat(f, 0, 3)

    Dim stamp As String = DateTime.DAte(d) & " " & DateTime.Time(d) & b
    Return stamp 
End Sub
TempDownload.png

I guess, under Windows it will be the same cross-platform solution...
 
Last edited:
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
Result of such grabbing is so-so.

image_2022-08-20_17:21:51.334.jpg
image_2022-08-20_17:21:52.21.jpg
image_2022-08-20_17:21:52.741.jpg
image_2022-08-20_17:21:53.265.jpg
image_2022-08-20_17:21:54.197.jpg
image_2022-08-20_17:21:54.721.jpg
image_2022-08-20_17:21:55.243.jpg
image_2022-08-20_17:21:56.23.jpg
image_2022-08-20_17:21:56.74.jpg
image_2022-08-20_17:21:57.248.jpg
image_2022-08-20_17:21:58.217.jpg
image_2022-08-20_17:21:58.741.jpg
image_2022-08-20_17:21:59.261.jpg
image_2022-08-20_17:22:00.196.jpg
image_2022-08-20_17:22:00.708.jpg
image_2022-08-20_17:22:01.24.jpg
image_2022-08-20_17:22:02.226.jpg
image_2022-08-20_17:22:02.781.jpg
image_2022-08-20_17:22:03.291.jpg
image_2022-08-20_17:22:04.212.jpg
image_2022-08-20_17:22:04.728.jpg
image_2022-08-20_17:22:05.236.jpg
image_2022-08-20_17:22:06.199.jpg
image_2022-08-20_17:22:06.773.jpg
image_2022-08-20_17:22:07.329.jpg
image_2022-08-20_17:22:08.271.jpg
image_2022-08-20_17:22:08.844.jpg
image_2022-08-20_17:22:09.352.jpg

Sometimes 2 frames per second, but, actually minimally = 1 FPS only.
It's grabbing frames

  • from a FullHD H.265 4096 Kbps stream into .JPG of about 80% quality
  • grabber Linux-host is on 216...800 Mbps WiFi 11n connection (ping = 50...100 ms from my host)
  • ip-cam is on the wired 100 Mbps Ethernet port (ping = 5...10 ms)
  • grabbing using TCP transport protocol, as RTSP-stream may return distorted frame over UDP.
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
timer every 300ms (to take 3-4 fps)
Indeed, my timer was 500 ms, now i have tried 200 ms, and result looks maximal, almost same:

/mnt/ramdisk/image_2022-08-29_12:41:43.237.jpg
/mnt/ramdisk/image_2022-08-29_12:41:43.860.jpg
/mnt/ramdisk/image_2022-08-29_12:41:45.220.jpg
/mnt/ramdisk/image_2022-08-29_12:41:45.832.jpg
/mnt/ramdisk/image_2022-08-29_12:41:47.261.jpg
/mnt/ramdisk/image_2022-08-29_12:41:48.021.jpg
/mnt/ramdisk/image_2022-08-29_12:41:49.243.jpg
/mnt/ramdisk/image_2022-08-29_12:41:49.901.jpg
/mnt/ramdisk/image_2022-08-29_12:41:51.233.jpg
/mnt/ramdisk/image_2022-08-29_12:41:51.885.jpg
/mnt/ramdisk/image_2022-08-29_12:41:53.266.jpg
/mnt/ramdisk/image_2022-08-29_12:41:54.171.jpg
/mnt/ramdisk/image_2022-08-29_12:41:55.277.jpg
/mnt/ramdisk/image_2022-08-29_12:41:55.926.jpg
/mnt/ramdisk/image_2022-08-29_12:41:57.257.jpg
/mnt/ramdisk/image_2022-08-29_12:41:57.863.jpg
/mnt/ramdisk/image_2022-08-29_12:41:59.255.jpg
/mnt/ramdisk/image_2022-08-29_12:41:59.879.jpg
/mnt/ramdisk/image_2022-08-29_12:42:01.224.jpg
/mnt/ramdisk/image_2022-08-29_12:42:01.866.jpg
/mnt/ramdisk/image_2022-08-29_12:42:03.214.jpg
/mnt/ramdisk/image_2022-08-29_12:42:03.872.jpg
/mnt/ramdisk/image_2022-08-29_12:42:05.265.jpg
/mnt/ramdisk/image_2022-08-29_12:42:05.869.jpg
/mnt/ramdisk/image_2022-08-29_12:42:07.247.jpg
/mnt/ramdisk/image_2022-08-29_12:42:07.849.jpg
/mnt/ramdisk/image_2022-08-29_12:42:09.236.jpg
/mnt/ramdisk/image_2022-08-29_12:42:09.894.jpg

And it's saving to RAM-disk, even not to a SSD.
But all is synchronous, with waiting for result. It's important here, not to pass anything on video.

p.s. BTW, the all frames, each in the stream is the I-frame. And this IP-cam setting changes the result FPS directly.
 
Last edited:
Upvote 0

Magma

Expert
Licensed User
Longtime User
You need to play with timer... and your pc-specs... also with compression... if you select different compression or uncompressed may will be more faster !

Also you need to know that timer will be with right delay... to have the option to use your app - not lag.. and not to fight with your RAM ! - but 10 ffmpeg running the same time will no need more than 1GB ! (i am saying much)....
 
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
The same. Frequency here depends directly on the cam stream settings.
If to change the codec to H.264 - freq immediately runtime is just

/mnt/ramdisk/image_2022-08-29_12:56:45.782.jpg
/mnt/ramdisk/image_2022-08-29_12:56:49.774.jpg
/mnt/ramdisk/image_2022-08-29_12:56:53.782.jpg
/mnt/ramdisk/image_2022-08-29_12:56:57.777.jpg
/mnt/ramdisk/image_2022-08-29_12:57:01.778.jpg
/mnt/ramdisk/image_2022-08-29_12:57:05.809.jpg
/mnt/ramdisk/image_2022-08-29_12:57:09.762.jpg
/mnt/ramdisk/image_2022-08-29_12:57:13.766.jpg
/mnt/ramdisk/image_2022-08-29_12:57:17.774.jpg
/mnt/ramdisk/image_2022-08-29_12:57:21.762.jpg
/mnt/ramdisk/image_2022-08-29_12:57:25.854.jpg
/mnt/ramdisk/image_2022-08-29_12:57:29.782.jpg
/mnt/ramdisk/image_2022-08-29_12:57:33.769.jpg
/mnt/ramdisk/image_2022-08-29_12:57:37.776.jpg
/mnt/ramdisk/image_2022-08-29_12:57:41.784.jpg
/mnt/ramdisk/image_2022-08-29_12:57:45.802.jpg
/mnt/ramdisk/image_2022-08-29_12:57:49.784.jpg
/mnt/ramdisk/image_2022-08-29_12:57:53.768.jpg
/mnt/ramdisk/image_2022-08-29_12:57:57.805.jpg
/mnt/ramdisk/image_2022-08-29_12:58:01.784.jpg
/mnt/ramdisk/image_2022-08-29_12:58:05.774.jpg
/mnt/ramdisk/image_2022-08-29_12:58:09.784.jpg
/mnt/ramdisk/image_2022-08-29_12:58:13.841.jpg
/mnt/ramdisk/image_2022-08-29_12:58:17.839.jpg
/mnt/ramdisk/image_2022-08-29_12:58:21.807.jpg
/mnt/ramdisk/image_2022-08-29_12:58:25.780.jpg
/mnt/ramdisk/image_2022-08-29_12:58:29.763.jpg
/mnt/ramdisk/image_2022-08-29_12:58:33.773.jpg
 
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
No :) 3-5 times more slow.
Even just disabling the audio in the stream makes grabbing freq .... SLOWER ! :)
But bitrate of 8192 Kbps (twice more, max) makes just a bit slower, it's good.
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
...But the frames grabbing having different time stamp... you mean you are capturing the same thing many times ?

That's may be not compatible decoder (for rtsp) for linux... did you ve tried from windows (have installed codecs) ????
 
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
you are capturing the same thing many times ?
unclear. Now cam is just in a dark corner, pictures are 99.9% same.
Yes, maybe some in codecs or so... And it's ffmpeg's magic - i think for each grabbing is to be prepared, initialized, networking, look for something in the stream to sync and .... finally grab the frame.

Under Windows - the same situation:

image_2022-08-29_14-27-41.496.jpg
image_2022-08-29_14-27-41.978.jpg
image_2022-08-29_14-27-42.745.jpg
image_2022-08-29_14-27-44.692.jpg
image_2022-08-29_14-27-45.484.jpg
image_2022-08-29_14-27-45.957.jpg
image_2022-08-29_14-27-46.732.jpg
image_2022-08-29_14-27-48.682.jpg
image_2022-08-29_14-27-49.511.jpg
image_2022-08-29_14-27-49.981.jpg
image_2022-08-29_14-27-50.793.jpg
image_2022-08-29_14-27-52.688.jpg
image_2022-08-29_14-27-53.510.jpg
image_2022-08-29_14-27-53.979.jpg
image_2022-08-29_14-27-54.813.jpg
image_2022-08-29_14-27-56.692.jpg
image_2022-08-29_14-27-57.144.jpg
image_2022-08-29_14-27-57.923.jpg
image_2022-08-29_14-27-58.711.jpg
image_2022-08-29_14-28-00.604.jpg
image_2022-08-29_14-28-01.379.jpg
image_2022-08-29_14-28-01.850.jpg
image_2022-08-29_14-28-02.661.jpg
image_2022-08-29_14-28-03.118.jpg
image_2022-08-29_14-28-04.693.jpg
image_2022-08-29_14-28-05.519.jpg
image_2022-08-29_14-28-06.002.jpg

It looks like it's only i-frame is grabbed.
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
i think for each grabbing is to be prepared, initialized, networking, look for something in the stream to sync and .... finally grab the frame.
I see the point...

[First read the files of directory at a list)

I think you can run only one jshell and never-ending capturing to jpeg files.. "not just a grab and exit - but looping grab"... but with one jshell - with ffmpeg and auto-grabbing, saving... (search a little the documentation of cli)

Then in a timer from your b4j app read again the files of directory... and use or show or transfer (make anything you need)... with those files...
 
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
never-ending capturing to jpeg files
I was discussing with a ML-developer and he told that for neural networks - the stable grabbing process is the key feature. And for ex. OpenCV has a big trouble with it - rare, but can work un-stable with IP-cams inside Python code.
It's very experienced man, so, i trust him, and try to avoid this unstability - better if each time the grabber is restarted, and works slow, but stable.
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
@peacemaker But this had to do... with browsing the rtsp... not to "reconnect" again and again... to get just a frame..

I think you can achieve... more... without need to reconnect...

Also... you can taskkill every some seconds... the ffmpeg and restart... the process to be sure..
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
...Check that - if works for you...

B4X:
#Region Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 600
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private xui As XUI
    Private Button1 As B4XView
    Private Button2 As Button
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
End Sub

Sub Button1_Click
    Get_Frame
End Sub


Sub Get_Frame()
    Dim URL As String = "rtsp://rtsp.stream/pattern"
 
    'Dim command As String = "/usr/bin/ffmpeg -rtsp_transport tcp -i " & URL & " -r 1 -vsync 1 -qscale 1 -frames:v 1 -f image2 images_$(date +%F_%H-%M-%S).jpg"
 
    Dim ff As String = "ffmpeg.exe"
    Dim Args As List
    Args.Initialize
    Args.Add("-i")
    Args.Add(QUOTE & URL & QUOTE)
    Args.Add("-r")
    Args.Add("10") 'try for 10fps
    Args.Add("image%01d.jpg")
         
             
    Dim sh As Shell
    sh.Initialize("ffmpeg", ff, Args)
    sh.WorkingDirectory = File.DirApp
 
    sh.Run(-1)
    'Dim res As ShellSyncResult =
 
'    #if Debug
'    Log(res.Success & "; ExitCode = " & res.ExitCode)
'    Log("StdOut = " &  res.StdOut)
'    Log("StdErr = " &  res.StdErr)
'    #end if
End Sub

Sub Get_Stamp As String
    Dim b As String, d, E As Long, f As Float
    DateTime.DateFormat = "yyyy-MM-dd"
    DateTime.TimeFormat = "HH:mm:ss"

    d = DateTime.Now
    E = d - DateTime.TimeParse(DateTime.Time(d))
    f = E/DateTime.TicksPerSecond
    b = NumberFormat(f, 0, 3)

    Dim stamp As String = DateTime.DAte(d) & " " & DateTime.Time(d) & b
    Return stamp
End Sub

Private Sub Button2_Click
    Dim ff As String = "taskkill.exe"
    Dim Args As List
    Args.Initialize
    Args.Add("/F")
    Args.Add("/IM")
    Args.Add("ffmpeg.exe")

         
             
    Dim sh As Shell
    sh.Initialize("tk", ff, Args)
    sh.WorkingDirectory = "c:\windows\system32"
 
    sh.Run(-1)
End Sub

Get_Frame runs in backround the ffmpeg and start capture 10 fps (you can change it)... never exit from ffmpeg... every image save like a different file...
Button2_Click kills ffmpeg.exe from background execution...

(tested in windows... you can easily change for linux)
 
Upvote 0
Top