1

I'm trying to restream with ffmpeg. I don't care if it will be mjpeg or whatever else, as long as it will be playable in modern browsers. But latency is critical, it would be great to have <5 sec delay added.

I was trying to make hls stream, then gave up and tried mjpeg.So far I came up with something like this:

hls

ffmpeg -i input -an -c:v libx264 -crf 21 -preset veryfast -fflags nobuffer -flags low_delay  -f hls -hls_time 6 -hls_list_size 10 -hls_flags delete_segments restreamed.m3u8

(I have this outputing to folder which is server via nginx, so I could test if I can play the stream in browser or vlc)

The main issue with this is that the m38u file is always missing the last segment: ffmpeg creates restreamed0.ts, there is no m3u8 file. After given time, the (restreamed)0.ts is done, and it starts another chunk 1.ts. At this point, m3u8 is created, but it only has 0.ts in it. When the 1.ts if finished, another chunk 2.ts is started, and the 1.ts is written to the m3u8 file, and so on. This obviously creates the delay of the length of one segment, which is too much.

I tried tweaking with the -hls_time and -hls_list_size parameters and other flags I came across while Googling, but without any success. I've been trying to get this working for two days and it this point, I've completely lost track of what doesn't work at all, and what is somewhat working (usually it either takes insanely long for vlc to start playing the stream, or there is a huge delay, but I had no success creating perfect stream). I'm totally lost and I would appreciate some help.

mjpeg

I then gave up ad tried doing mjpeg stream, but it ended similar. My best result is this:

 ffmpeg -i input -vcodec mjpeg -f segment -segment_time 10  -segment_list video.m3u8  -max_delay 0    out%d.mjpg

ffmpeg output:

Input #0, mpjpeg, from '...':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: mjpeg, yuvj420p(pc, bt470bg/unknown/unknown), 640x480, 25 tbr, 25 tbn, 25 tbc
Stream mapping:
  Stream #0:0 -> #0:0 (mjpeg (native) -> mjpeg (native))
Press [q] to stop, [?] for help
[segment @ 0x1d62900] Opening 'out0.mjpg' for writing
Output #0, segment, to 'out%d.mjpg':
  Metadata:
    encoder         : Lavf58.20.100
    Stream #0:0: Video: mjpeg, yuvj420p(pc), 640x480, q=2-31, 200 kb/s, 25 fps, 25 tbn, 25 tbc
    Metadata:
      encoder         : Lavc58.35.100 mjpeg
    Side data:
      cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
[segment @ 0x1d62900] Opening 'video.m3u8.tmp' for writingte=N/A speed=0.403x
[segment @ 0x1d62900] Opening 'out1.mjpg' for writing
[segment @ 0x1d62900] Opening 'video.m3u8.tmp' for writingte=N/A speed=0.401x    
[segment @ 0x1d62900] Opening 'out2.mjpg' for writing
[segment @ 0x1d62900] Opening 'video.m3u8.tmp' for writingte=N/A speed=0.401x    
[segment @ 0x1d62900] Opening 'out3.mjpg' for writing
[segment @ 0x1d62900] Opening 'video.m3u8.tmp' for writingte=N/A speed=0.401x    

I had no success loading that m3u8 file in vlc or in bowser (html video element). (However, if I try to play one of the .mjpg files, it's working as expected (except it plays faster, but I think that's caused by the source stream being 10fps, I can deal with this later)). The m3u8 file looks like this:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:10
#EXTINF:10.000000,
out0.mjpg
#EXTINF:10.000000,
out1.mjpg
#EXTINF:10.000000,
out2.mjpg

and apart from not being able to play it in vlc, neither in browser (I tried solutions offered in this question), it's always missing the last segment.

Could you please tell me what I'm doing wrong or point me in the right direction?

2 Answers2

1

First of all: .m3u8 files are not expected to work with mJPEG in any portable way, so this is a dead end.

Concerning HLS: The .m3u8 file always only contains the finished segments, so the one just being created is never in the list. Due to consumption via a browser this is necessary and can't be circumvented.

What you can do is to make that last segment short - by making all segments short: Try

ffmpeg -i input -an -c:v libx264 -crf 21 -preset veryfast -fflags nobuffer -flags low_delay  -f hls -hls_time 1 -hls_list_size 3 -hls_flags delete_segments restreamed.m3u8

The -hls_time 1 wil reduce the length of all segments to one second, so the delay while creating the last segment is a maximum of a second. The -hls_list_size 3 will shorten the list to 3 segments of a second each.

Eugen Rieck
  • 20,637
0

-hls_list_size 0 will ok

ffmpeg -i input -an -c:v libx264 -crf 21 -preset veryfast -fflags nobuffer -flags low_delay  -f hls -hls_time 6 -hls_list_size 0 -hls_flags delete_segments restreamed.m3u8