Ffmpeg hangs while transcoding HDHomerun Prime on channel change - ffmpeg

I'm using ffmpeg to transcode a live stream from a HDHomerun Prime. Everything is working beautifully. However, one ability that I would like, if possible, is the ability to change the channel on the HDHomerun without having to stop and restart the ffmpeg transcoding process.
I start the ffmpeg process to begin reading the UDP feed from the HDHomerun. It writes the stream to a series of *.ts files with a m3u8 playlist.
The second I use hdhomerun_config to change the channel on the device, ffmpeg immediately reports the following and hangs:
[mpegts # 0000018b4e05be60] New video stream 0:3 at pos:295211888 and DTS:40884.7s=108 drop=0 speed=1.02x
[mpegts # 0000018b4e05be60] New audio stream 0:5 at pos:295279568 and DTS:40884.4s
frame= 4488 fps= 29 q=23.0 q=27.0 q=23.0 size=N/A time=00:02:28.94 bitrate=N/A dup=108 drop=0 speed=0.959x
The command I am using to launch ffmpeg is:
ffmpeg.exe -t 03:00:00 -i "udp://192.168.1.150:5000?fifo_size=1000000&overrun_nonfatal=1" -vf yadif=0:-1:1 -y -threads 4 -c:v libx264 -s 1280x720 -r 30 -b:v 4500k -force_key_frames expr:gte(t,n_forced*2) -profile:v high -preset fast -x264opts level=41 -c:a libfdk_aac -b:a 96k -ac 2 -hls_time 10 -hls_list_size 6 -hls_wrap 6 -hls_base_url /stream/ -hls_flags temp_file -hls_playlist_type event "C:\temp\streams\4500-stream.m3u8"
Is there a specific command that I can pass to allow ffmpeg to "recover" from this? Or, is there an arg that prevents this hang in the first place? I'm using the latest version v3.4 of ffmpeg cross-compiled for Windows from Ubuntu. The issue also occurred using the stable version v3.4 of ffmpeg for Windows from ffmpeg.org.
Edit:
A new discovery to the issue, but still not yet resolved:
If I change to the channel BACK to the original channel, Ffmpeg is able to continue writing the stream.
Example: I start on channel X. Ffmpeg is recording to a file. I change to channel Y. Ffmpeg outputs a message similar to the one posted above and "hangs." I change back to channel X and ffmpeg picks up where it left off, no problem.

No answer for your issue and too new to comment, but I had been trying to do this for a while based on another software package at https://github.com/bkirkman/hdhrtv
Basically what this implementation is doing is opening a new stream for each channel. I suspect that you will need to do the same and that also explains why when you go "back" the channel resumes itself. Unfortunately, unless you make a playlist and buffer every channel you may not be able to get a solution since the input stream changes.
I'd be interested in taking a look and testing if your willing to share your code.

Related

Is it possible to stream MJPEG content over MPEG-DASH?

I am trying to re-stream an MJPEG stream over dash using ffmpeg.
I have an ESP32 camera module that outputs an MJPEG livestream at 192.168.2.128:81/stream (Arduino code here).
I can open this stream directly in the browser and see the video in realtime, but the camera will only allow for a single client at a time while I am in need of a multi client solution.
What doesn't work
A solution I am currently trying to implement is to use a seperate server (Raspberry Pi) running apache and ffmpeg to re-stream the MJPEG content using DASH:
ffmpeg -re -i http://192.168.2.128:81/stream -strict -2 -an -c:v copy -b:v 2000k -f dash -window_size 4 -extra_window_size 0 -min_seg_duration 2000000 -remove_at_exit 1 /var/www/html/out.mpd
I get no errors when executing this command on the server.
I then use this ffmpeg-dash.html to display the video in the browser.
This code unfortunately fails, in Firefox the console reports the error:
[72][Stream] No streams to play.
followed by:
Cannot play media. No decoders for requested formats: video/mp4;codecs="mp4v.6c";width="640";height="480"
What does work
What is puzzling me is that the above code works fine if I replace the MJPEG livestream url with a sample .mkv file, so if I use
ffmpeg -re -i /var/www/html/video.mkv -strict -2 -an -c:v copy -b:v 2000k -f dash -window_size 4 -extra_window_size 0 -min_seg_duration 2000000 -remove_at_exit 1 /var/www/html/out.mpd
I can view the livestreamed sample video (video.mkv) without problems using the previously mentioned ffmpeg-dash.html file.
Furthermore, it seems that ffmpeg can read the MJPEG livestream without problems, since
ffmpeg -t 10 -i http://192.168.2.128:81/stream -filter:v fps=15 -c:v flv test.flv
returns a 10 second clip of the livestream succesfully.
So to me it seems that the problem lies in how I combine the two. What am I missing? Is it even possible to stream MJPEG content over MPEG-DASH?
(I am new to this, sorry in advance for my ignorance)

How to make ffmpeg exit when rtmp input stream ends?

I am using ffmpeg to transcode a stream from my local nginx rtmp server, and send the transcoded media back to the same local rtmp server. When the stream goes offline, ffmpeg stays active. When the stream starts again, ffmpeg picks up the transcoding work.
I'd like ffmpeg to exit when the input rtmp stream stops, but I cannot find out to configure it to do that. I've looked through the manual page and the online documentation.
For completeness, these are the arguments I currectly provide to ffmpeg:
ffmpeg -i 'rtmp://localhost/live/ijsbeer' -s '1280x720' -vcodec 'libx264' -preset 'veryfast' -crf '25' -maxrate '2000k' -bufsize '1000.0k' -force_key_frames '0:00:02' -max_muxing_queue_size '4096' -acodec 'copy' -copyts -copytb '0' -f 'flv' 'rtmp://localhost/live/ijsbeer_720p'
Making ffmpeg exit itself solves two of my problems. Firstly, ffmpeg sometimes experiences non-monotonous DTS issues when the encoder (OBS) streaming to the rtmp server restarts. Second, I'd like to implement a basic monitoring system to notify me of issues in the transcoder. Making ffmpeg exit when the input stream stops seems like to most reliable way to determine if ffmpeg is doing work. Parsing the stderr/stdout isn't reliable as there is no clear output format.
When transcoding I receive these regular stderr lines:
frame= 241 fps= 30 q=30.0 size= 38kB time=00:00:09.74 bitrate= 32.0kbits/s speed= 1.2x
Which pause when I stop the source stream. There is no log output stating the source stream has exited.

Can ffmpeg seek when using an input stream (or url)?

I've been using ffmpeg quite a lot in the past few weeks, and recently I've encountered a very annoying issue - when I use ffmpeg with an input stream (usually, just a url as the input) and try to set a start time (with -ss option), I always get a warn message that says "could not seek to position: XXX".
Then, ffmpeg just starts to download the file, and it ouputs nothing until it has downloaded enough data and got to my desired start time.
I'll give an example:
I use this command to execute ffmpeg:
ffmpeg -ss 50 -re -i https://ascent.usbank.com/acp/videos/041114ascent.flv -b:a 128k -ac 2 -acodec libvorbis -b:v 1024k -vcodec libtheora -strict 2 -preset ultrafast -tune zerolatency -pix_fmt yuv420p -f ogg pipe:1
and I get the warn message
https://ascent.usbank.com/acp/videos/041114ascent.flv: could not seek to position 50.000
Then, it takes about 30 seconds until ffmpeg starts to output data to stdout. And when I try this with longer videos (and longer seek times), it takes even longer.
My question is, what can I do? I guess it's impossible for ffmpeg to seek when it haven't got the whole input stream... Am I wrong? Or is there any other solution?
Of course I try to avoid downloading the entire file from the web...
Thanks in advance!
Roee.
I guess you can't do really anything about it other than to buffer the FLV locally and (eventually) seek that.
Whether or not a http resource allows seeking largely depends on the capabilities of the server, unfortunately...

What does 'Past duration X.XXX too large' mean?

When encoding H.264 using ffmpeg I get the following type of warnings en masse:
Past duration 0.603386 too large
Past duration 0.614372 too large
Past duration 0.606377 too large
What do they mean? I have not found anything clear online or in the ffmpeg documentation.
One of the maintainers for the DVDStyler project on SourceForge said this about it:
FFMpeg versions after Jan 15 2015 often display this warning. It has
been added to warn about possible rate control distortion, otherwise
it does not cause any harm.
This warning message appears when trying to encode a high frame rate source to a low frame rate output, which means frames need to be dropped.
I had this error because I wanted to convert a series of images to a video:
ffmpeg -i %05d.png -r 24 -c:v libx264 -crf 5 out.mkv
The problem seems to be, that if no frame rate is give for the input, then a frame rate of 25 fps is assumed:
Input #0, image2, from 'frames/%04d.bmp':
Duration: 00:00:15.96, start: 0.000000, bitrate: N/A
Stream #0:0: Video: bmp, bgra, 920x650, 25 fps, 25 tbr, 25 tbn, 25 tbc
This also can be seen on the total number of frames encoded. I had 400 images, but the above command only encoded 384:
frame= 384 fps= 68 q=-1.0 Lsize= 10931kB time=00:00:15.91 bitrate=5626.1kbits/s dup=0 drop=15
video:10928kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.033807%
The error messages disappears by setting the input frame rate instead if the output frame rate. The output frame rate will then be automatically chosen to be that of the input. Additionally in newer ffmpeg versions you have to watch out, because when using PNG images with the -i option or rather the image2 or v4l2 input format, you have to use -framerate instead of -r, see the documentation for the -r option.
ffmpeg -framerate 24 -i %05d.png -c:v libx264 -crf 5 out.mkv
It is also possible to specify the frame rate of both input and output separately:
ffmpeg -framerate 25 -i %05d.png -r 10 -c:v libx264 -crf 5 out.mkv
In this case only 161/400 frames will be encoded. The other frames interim will be dropped.
Also the error message disappears, I guess in order to not slow down ffmpeg by spamming to stdout, see:
https://trac.ffmpeg.org/ticket/4700
https://trac.ffmpeg.org/ticket/4401
Looking at the source code it seems to be that the difference between the presentation time (pts) in the input stream differs from the one in the output stream by more than a fixed limit set to 0.6 .
Snippets from the source:
delta0 = sync_ipts - ost->sync_opts;
delta = delta0 + duration;
...
if (delta0 < 0 &&
delta > 0 &&
format_video_sync != VSYNC_PASSTHROUGH &&
format_video_sync != VSYNC_DROP) {
double cor = FFMIN(-delta0, duration);
if (delta0 < -0.6) {
av_log(NULL, AV_LOG_WARNING, "Past duration %f too large\n", -delta0);
} else
av_log(NULL, AV_LOG_DEBUG, "Cliping frame in rate conversion by %f\n", -delta0);
sync_ipts += cor;
duration -= cor;
delta0 += cor;
}
This is only a quick glance, so please feel free to dig deeper.
I was getting thousands of these warnings with a particular encode. I was downscaling 1080p video to 480p. At an edit point, where there was some dodgy video due to a defect in the source laserdisc, these messages started coming up and then appeared for, I think, every frame thereafter. They went on and on, like this short excerpt:
Past duration 0.901115 too large= 535031kB time=00:54:15.06 bitrate=1346.5kbits/s dup=0 drop=19 speed=1.15x
Last message repeated 31 times
Past duration 0.901115 too large= 535031kB time=00:54:15.62 bitrate=1346.3kbits/s dup=0 drop=19 speed=1.15x
Last message repeated 34 times
Past duration 0.901115 too large= 535031kB time=00:54:16.21 bitrate=1346.0kbits/s dup=0 drop=19 speed=1.15x
Last message repeated 36 times
Past duration 0.901115 too large= 535338kB time=00:54:16.83 bitrate=1346.5kbits/s dup=0 drop=19 speed=1.15x
Last message repeated 39 times
The original ffmpeg invocation was this:
ffmpeg -i input.mp4 -s 720x480 -c:v libx264 -preset slower \
-crf 17 -c:a copy -y output.mkv
Following suggestions here I first added -framerate 60000/1001 to the input. That did not improve anything. I retained -framerate and added -r 60000/1001 to the output. That still did not improve anything. Retaining both I finally added -async 1 -vsync 1. This resulted in my receiving a single warning, and that's all. That invocation was:
ffmpeg -i input.mp4 -framerate 60000/1001 -s 720x480 -c:v libx264 \
-preset slower -crf 17 -c:a copy -y output.mkv \
-r 60000/1001 -async 1 -vsync 1
The only difference I found in a detailed dump from MediaInfo was the removal of this line found in the original invocation but not in the second one:
Delay relative to video : -33ms
However, I checked A/V sync near the beginning of the files and near the end, and there was no discernible difference in sync between the two files. Their running times were also the same, but that was only measured to the nearest second, in VLC. So I checked the frame counts using ffmpeg like so:
ffmpeg -i output.mkv -map 0:v:0 -c copy -f null -
and looking for "frame=#" near the end of the output.
Turns out the source video was 375226 frames long, the original invocation yielded 375195 frames, and the second invocation yielded 375200. So the second invocation, with vastly fewer warning messages also dropped 5 fewer frames.
Subsequent testing showed that -framerate and -r were unnecessary, and just using the two sync flags was sufficient. This produced identical results to the second invocation above, so the third and simplest invocation I found to solve the problem is this:
ffmpeg -i input.mp4 -s 720x480 -c:v libx264 -preset slower \
-crf 17 -c:a copy -y output.mkv -async 1 -vsync 1
And yet another file subsequently produced a bunch of these warnings even with the sync flags, but adding back the rate flags "fixed" it (only produced two instead of thousands of warnings). So sometimes the second invocation works when the third doesn't. For my immediate purposes I'm going to settle on the second invocation and hope it fixes most of these problems.
This was all with ffmpeg version 4.0.
The command should actually be:
ffmpeg -loglevel quiet -i input_file.xyz ...
There is no "-" prefix to the "quiet" parameter, as it's not an option, rather a value for the "-loglevel" option.
As per FFmpeg issue #4700 -
Past duration 0.999992 too large
it is only a warning.
Use -loglevel option to stop it:
ffmpeg -loglevel quiet -i input_file.xyz ....
Possible levels are numbers or:
"quiet"
"panic"
"fatal"
"error"
"warning"
"info"
"verbose"
"debug"
"trace"

ffmpeg rtsp_transport to rtmp issues

I'm working on a project that requires taking rtsp links from youtube, and using ffmpeg to stream those videos to an rtmp server. My solution works, however it is having some issues.
I'm using these settings:
-max_delay 0 -initial_pause 0 -rtsp_transport udp -i " + inputLink + " -vcodec libx264 -acodec mp3 -ab 48k -bit_rate 450 -r 25 -s 640x480 -f flv " + stream
inputLink is replaced with the rtsp link, and stream is replaced with the rtmp server link
So this works but here are the issues I'm having:
At the beginning of each video, there is a big lag spike/lots of frames dropped, and then the video resyncs and plays normally
Some videos would crash ffmpeg, with a "Conversion failed" message and many frames dropped during the conversion/stream.
At the end of each video it would start lagging/ dropping frame, right near the end of the video, in other words it doesn't end normally, every video ends by lagging out / dropping frames
I've been struggling for a long time just to get this working, and now I finally did, I just need to perfect it by taking care of those two issues, if anyone has useful information about the rtsp_transport protocol and how to make it stream with no issues, I would greatly appreciate it. Thanks!
You got some settings wrong.
-bit_rate 450: you asked for a 450 bits per second, it's no wonder it drops a lot of frames! It should be 450k.
If you want a 450 kbps stream then use -ab 48k -vb 402k, where 402 = 450 - 48.
The flv format only supports certain audio rates. You need to also use -ar with one of the following values: 44100, 22050 or 11025.
ffmpeg -i rtsp://... -c:v libx264 -c:a mp3 -ab 48k -ar 44100 -vb 402k -r 25 -s 640x480 -f flv test.flv

Resources