Getting the frame pkt_pts from ffmpeg - ffmpeg

I record a stream similar to this (but I pipe the image to stdout and process the frames in real time):
ffmpeg -debug_ts -y -i http://my_stream.com -strict -2 out.mp4
Now I need to map my frames to the pkt_pts. This pkt_pts I can get by running:
ffprobe -i http://my_stream.com -show_frames -select_streams v:0
Although starting ffprobe is not an option since I need to excactly know which pkt_pts belongs to what frame.
Therefore I'm using the -debug_ts in my ffmpeg call, which gives me a lot of output to stderr, which I then parse out. The only output line which matches the number of frames is the one which starts with: muxer <- type:video This line does contain a pkt_pts, but it always starts with 0 (not the global pkt_pts).
Is there a way to map a frame, to the global pkt_pts in real time with ffmpeg?

You can run your original command, and extract lines starting with
demuxer -> ist_index:X
where X is the index number of the stream you want.
In each line, e.g.
demuxer -> ist_index:12 type:video next_dts:10851838034 next_dts_time:10851.8 next_pts:10851705034 next_pts_time:10851.7 pkt_pts:976665480 pkt_pts_time:10851.8 pkt_dts:976665480 pkt_dts_time:10851.8 off:0 off_time:0
-pkt_pts divided by stream timebase, 90000 for TS input, will give you full precision pkt_pts_time. If you don't know the timebase, see the input dump for your stream
Stream #0:0: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p, 768x432, 29.97 tbr, 90k tbn, 59.94 tbc
and use the tbn value.
Be aware that your ffprobe command selects the first video stream, but your ffmpeg command leaves it to ffmpeg to select streams, which may not select the same streams.

Related

Downsampling / Filtering Data Stream with FFMPEG

We have a .ts input file that contains (among other streams) a video stream and MISB 0604-compliant KLV data stream. The output of ffprobe for these stream are:
Stream #0:0[0x111]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p(progressive), 1280x720 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc
...
Stream #0:2[0x1001]: Data: klv (KLVA / 0x41564C4B)
We are hoping to extract every Nth frame of the video as a .tiff. We also need to associate each of these frames with a corresponding KLV packet from the MISB 0604-compliant data stream.
The following command that select filters and adjusts the original FPS by the corresponding ratio does result in the expected frames being saved out as TIFF (in this case the original video has 1187 frames, and I expect to get 12 frames from the select filter).
ffmpeg -y -i 2205Z.ts -map 0:0 -vf "select='not(mod(n,100))'",fps=30000/1001/100 -compression_algo raw -pix_fmt rgb24 %05d.tif
However I can't seem to get any filters working on the data stream. For example using filter:d does not throw an error, but also doesn't seem to actually filter. My question is whether ffmpeg can be used to save out a "downsampled" data stream corresponding to the downsampling operations performed on the video stream above?
Using a recent git master build, run
ffmpeg -i 2205Z.ts -map 0:2 -bsf "noise=drop=mod(n\,100)" -f segment -segment_format data -segment_time 0.01 %d.bin
The noise bsf uses an expression to drop, not select i.e. select=EXPR === drop=not(EXPR).
Add -loglevel verbose to see details about which packets are kept, in a format like this:
[noise # 000001cd418a68c0] Stream #2 packet 1099 pts 3420417 - amount 0 drop 1
[noise # 000001cd418a68c0] Stream #2 packet 1100 pts 3423419 - amount 0 drop 0
[noise # 000001cd418a68c0] Stream #2 packet 1101 pts 3426423 - amount 0 drop 1

How to concat MTS videos and apply filters without re-encoding using FFmpeg?

I have a txt file with many MTS video files. I want to merge them all together using FFmpeg and get one big MTS file. But I want to apply fade-in and fade-out to the final video. Can I do it without re-encoding? Because re-encoding takes a lot of time, but I need to do it fast.
Edit
Here is the output when I run
ffmpeg -i C:/Users/aleks/Downloads/IMPORTANT/MTS_videos/my.MTS
Output:
Input #0, mpegts, from 'C:/Users/aleks/Downloads/IMPORTANT/MTS_videos/my.MTS':
Duration: 00:00:08.51, start: 1.433367, bitrate: 5275 kb/s
Program 1
Metadata:
service_name : Service01
service_provider: FFmpeg
Stream #0:0[0x100]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p(tv, bt709, progressive), 1920x1080, 59.94 fps, 59.94 tbr, 90k tbn, 120k tbc
Edit 2
ok, I think I figured it out. The problem was in audio codec, I added -c:a mp3 and it seems to be working. However now I have the second problem. I have 3 videos. I apply fade in to the first one, fade out to the third one and nothing to the second one. I get them from one video by slicing using this command 3 times
ffmpeg -i 'C:/Users/aleks/Downloads/video.MTS' -ss 20 -t 5 -c copy 'C:/Users/aleks/Downloads/third.MTS'
But when I run it my video is 2 seconds long (it must be 5 seconds long). Can you help me with fixing this problem.
PS. i have seen similar question and there was a suggestion to add -async 1. It didn't help. And moving -t 5 to the position before -i didn't help as well.
Also if I delete -c copy everything works fine. But I need to keep it because I don't want to re-encode.

Ffmpeg: 4K RGB->YUV realtime conversion

I'm trying to use Ffmpeg for creating a hevc realtime stream from a Decklink input. The goal is high quality HDR stream usage with 10 bits.
The Decklink SDI input is fed RGB 10 bits, which is well handled by ffmpeg with the decklink option -raw_format rgb10, which gets recognized by ffmpeg as 'gbrp10le'.
I have a Nvidia pascal-based card, which supports yuv444 10 bit (as 'yuv444p16le') and when when using '-c:v hevc_nvenc' the auto_scaler kicks in and converts to 'yuv444p16le', which I guess is the same conversion as giving '-pix_fmt yuv444p16le'.
This is working very well in 1920x1080 resolution, but in 4096x2160 resolution ffmpeg can't keep up realtime 24 or 25 fps, and I get input buffer overruns.
The culprit seems to be the RGB->YUV conversion in ffmpeg swscale because;
When piping the Decklink 4K RGB input with '-c:v copy' straight to /dev/null, there's is no problems with buffer underruns,
And when feeding the Decklink YUV and giving '-raw_format yuv422p10’ (no YUV444 input for decklink seems available for decklink in ffmpeg) I get no underrun and everything works well in 4K. Even if I set '-pix_fmt yuv444p16le'.
Any ideas how I could accomplish a 4K hevc in NVENC with the 10-bit RGB signal from the Decklink? Is there a way to make NVENC accept and use the RGB data without first converting to YUV? Or is there maybe a way to convert gbrp10le->yuv444p16le with cuda or scale_npp filter? I have compiled ffmpeg with npp and cuda, but I cannot figure out if I can get it to work with RGB? Whenever I try to do '-vf "hwupload_cuda"', auto_scaler kicks in and tries to convert to yuv on the cpu, which again creates underruns.
Another thing I guess could help is if there was a way to make the swscale cpu filter(or if there is another suitable filter?) use multiple threads? Right now it seems to only use one thread at a time, maxing out at 99% on my Ryzen 3950x (3,5GHz, 32 threads).
Example ffmpeg output:
$ ffmpeg -loglevel verbose -f decklink -raw_format rgb10 -i "Blackmagic Card 1" -c:v hevc_nvenc -preset medium -profile:v main10 -cbr 1 -b:v 20M -f nut - > /dev/null
--
Stream #0:1: Video: r210, 1 reference frame, gbrp10le(progressive), 4096x2160, 6635520 kb/s, 25 tbr, 1000k tbn, 1000k tbc
--
[graph 0 input from stream 0:1 # 0x4166180] w:4096 h:2160 pixfmt:gbrp10le tb:1/1000000 fr:25000/1000 sar:0/1
[auto_scaler_0 # 0x4168480] w:iw h:ih flags:'bicubic' interl:0
[format # 0x4166080] auto-inserting filter 'auto_scaler_0' between the filter 'Parsed_null_0' and the filter 'format'
[auto_scaler_0 # 0x4168480] w:4096 h:2160 fmt:gbrp10le sar:0/1 -> w:4096 h:2160 fmt:yuv444p16le sar:0/1 flags:0x4
[hevc_nvenc # 0x4139640] Loaded Nvenc version 11.0
--
Stream #0:0: Video: hevc (Rext), 1 reference frame (HEVC / 0x43564548), yuv444p16le(tv, progressive), 4096x2160 (0x0), q=2-31, 2000 kb/s, 25 fps, 51200 tbn
--
[decklink # 0x40f0900] Decklink input buffer overrun!:02.52 bitrate= 30471.3kbits/s speed=0.627x

What is the default FFMPEG codec for outputting images and what are alternatives?

I took a look at Default ffmpeg codec when nothing is specified. I see that the default codec is likely libx264 for video. Is this the same answer for using an FFMPEG command to make a JPG?
If it's libx264, what would be a good alternative codec to generate an image? I took a look at https://johnvansickle.com/ffmpeg/git-readme.txt, and I can't seem to find anything on what those codecs do. For example, searching libzimg just comes up with pages of people enabling it in a long list of options. https://ffmpeg.org/ffmpeg-codecs.html has no mention of zimg.
My current command is ffmpeg -loglevel quiet -report -timelimit 9 -timeout 9 -i www.example.com/manifest -vframes 1 output.jpg -y. I want to make sure I know what codec is being used when doing this.
I'm using https://johnvansickle.com/ffmpeg/git-readme.txt, which has mjpeg listed. I just want to be sure that this would be the default, when nothing is specified. (I can specify things going forward, but want to know what would have been used before).
Default JPG encoder is mjpeg. Default encoders are not really documented as it depends on your ffmpeg configuration, but you can refer to the log from your ffmpeg command.
Example:
ffmpeg -i input.mp4 -frames:v 1 output.jpg
Log excerpt:
Output #0, image2, to 'output.jpg':
Metadata:
encoder : Lavf58.42.102
Stream #0:0: Video: mjpeg, yuvj444p(pc), 320x240 [SAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 25 fps, 25 tbn, 25 tbc
So in this example the default muxer is image2 and the default encoder is mjpeg.
Get more info on these with ffmpeg -h muxer=image2 and ffmpeg -h encoder=mjpeg as shown in What are all codecs and formats supported by FFmpeg?

Trying to tonemap 14-bit grayscale video

I'm trying to generate h.264 video from raw 2-byte gray video (14-bit range encoded in 16-bit values). I can do something like:
ffmpeg -f rawvideo -pix_fmt gray16le -s:v 1280x720 -r 60 -i input.raw -c:v libx264 output.mp4
And I get video but it's pretty dark, not sure if it's clipping, doing a linear remap, or storing the 16-bit data and VLC is doing the remap. ffprobe is reporting Video: h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuvj444p(pc), 1280x720, 108 kb/s, 60 fps, 60 tbr, 15360 tbn, 120 tbc
I was figuring I'd use the tonemap filter to make a better mapping. I added a filter before the output file with -vf.
tonemap=hable errors Impossible to convert between the formats supported by the filter 'graph 0 input from stream 0:0' and the filter 'auto_scaler_0'
zscale=transfer=linear,tonemap=hable errors Impossible to convert between the formats supported by the filter 'Parsed_tonemap_1' and the filter 'auto_scaler_1'
zscale=transfer=linear,tonemap=hable,zscale=transfer=bt709,format=yuvj444p errors code 3074: no path between colorspaces
I'm not sure where to proceed from here...

Resources