kokorin / Jaffree

______ Stop the War in Ukraine! _______ Java ffmpeg and ffprobe command-line wrapper
Apache License 2.0
475 stars 80 forks source link

Streaming last for only 3 to 6 seconds #321

Closed ashif-ismail closed 2 years ago

ashif-ismail commented 2 years ago

Hello, I'm using the following code in my spring boot controller to convert the RTSP stream and then expose as streaming response body to frontend client.

everything works great, but the streaming works only for 3 to 6 seconds, and then process stops

following is the code

carbon (2)

Logs from spring boot console.

Screen Shot 2022-10-14 at 10 20 04 AM Screen Shot 2022-10-14 at 10 20 20 AM
kokorin commented 2 years ago

Hello!

First of all controllers are not intended to transfer real time data.

Second, you set frame count to 100, and you got 100 frames in output:

image Notice reported FPS - it's 15, not 1/10. Which gives 100/15 = 6.66 seconds.

Third, you set also max stream duration. FFMPEG will stop at either 100th frame, or after 1 hour.

I would highly recommend to revisit the approach to delivering a stream to a client. With current approach ffmpeg will be started for every client, which is not optimal of course. It's better to read rtsp stream and write fragmented MP4 chunks on disk. When a client connects, chunks should be served from disk.

ashif-ismail commented 2 years ago

Thanks @kokorin

This is my first attempt with RTSP streams, your answer's to my following questions would be helpful ?

  1. Your comment "First of all controllers are not intended to transfer real time data" is even valid if i use Spring Streaming Response body which is intended for the realtime data transfer purpose ?
  2. Your comment "It's better to read rtsp stream and write fragmented MP4 chunks" , I'm planning to convert RTSP to HLS and then save ts/m3u8 files and expose those files to client. Is this way optimal ?
kokorin commented 2 years ago

Your comment "First of all controllers are not intended to transfer real time data" is even valid if i use Spring Streaming Response body which is intended for the realtime data transfer purpose ?

Yes. Consider that HTTP requests pass through different HTTP reverse proxy servers. Default response timeout is 30 seconds. So intermediate servers will close connection after timeout, despite server transfers data. I can recommend you to read about long polling technic.

Your comment "It's better to read rtsp stream and write fragmented MP4 chunks" , I'm planning to convert RTSP to HLS and then save ts/m3u8 files and expose those files to client. Is this way optimal ?

Yes, it would be much better. ffmpeg allows to dump chunks on disk, and it will update manifest file periodically. So you need only to keep tracking of old chunks and delete them after some time (10-30 minutes).

ashif-ismail commented 2 years ago

Thanks @kokorin for the great library and your help regarding my comments..

kokorin commented 2 years ago

You are welcome, let me know regarding your progress, I'm really interested in it :-)

ashif-ismail commented 2 years ago

sure, i will share the updates :)

@Kokorin does the API have any callback that gets fired if the index.m3u8 is created for the first time

kokorin commented 2 years ago

Sorry @SheikhZayed but you ask unrelated questions in "not-an-issue" thread. If you mean ffmpeg API - check ffmpeg. If you mean Jaffree - you can find examples in readme. Rule of thumb: before implementing something with Jaffree just experiment with ffmpeg CLI.

ashif-ismail commented 2 years ago

Thanks @kokorin

ashif-ismail commented 2 years ago

You are welcome, let me know regarding your progress, I'm really interested in it :-)

Hey @kokorin Many thanks for this wonderful library, since you have asked my progress about the project. I was able to build a complete streaming server using spring boot using you lib.

Instead of converting RTSP to MP4 like I showed in my previous code, I consume the RTSP stream and then convert it to HLS. Also I have optimized the code to not to repeat for each individual request.

Unfortunately I cannot share screen shots or disclose further details respecting the nature of the project. Sorry for that.

Many thanks Again @kokorin God Bless

kokorin commented 2 years ago

@SheikhZayed thank you for updating me, I'm really glad you managed to make it working.

Just625 commented 1 year ago

Hi @SheikhZayed, can you share a bit more info about how you send the hls files to clients?

kokorin commented 1 year ago

@Just625 I believe segments and manifest are stored on disk using ffmpeg. User's player requests m3u8 manifest using http, it's served from disk, then player starts requesting segments which are also served from disk

Just625 commented 1 year ago

@kokorin thank you for the fast reply. So I created a Restfull API to get file from disk using the input as the file name. In the FFmpeg command: I add "-hls_base_url http://my-api-i-just-created/". So in front-end I use videojs library and I just put the API in src property of the video tag to get the .m3u8 file and it will automatically call that API many times to get child files (.ts files)

kokorin commented 1 year ago

@Just625 I didn't get it: does it work for you? if you need further advises use discussions, not issues. And one more thing: consider using fragmented MP4 chunks instead of TS.

Just625 commented 1 year ago

Hi @kokorin, yes it works for me. Thanks for the advice, I didn't know about fragmented MP4 before. I will try to use it to replace TS

ashif-ismail commented 1 year ago

@Just625 I believe segments and manifest are stored on disk using ffmpeg. User's player requests m3u8 manifest using http, it's served from disk, then player starts requesting segments which are also served from disk

@Just625 sorry for the delayed response, yes this is what i did..

In short -> this is how it goes

  1. Client requests a camera stream through a REST API
  2. FFmpeg reads RTSP stream and start dumping chunks in server root (in mycase a folder inside IIS root)
  3. My backend waits (Deferred Result in Spring Boot)until index.m3u8 gets generated for the requested stream and respond back to the client the link of the chunks (IIS folder mentioned in step 2) as response to API mentioned in step 1
  4. The link received is played by Hls.js in my angular frontend
ashif-ismail commented 1 year ago

@Just625 I didn't get it: does it work for you? if you need further advises use discussions, not issues. And one more thing: consider using fragmented MP4 chunks instead of TS.

@kokorin what is the benifit of using fragmented MP4 over TS ?