Log in

View Full Version : FFmpeg CLI Help Guide


EmKayVe
28th December 2018, 18:52
I've been learning and playing around with FFmpeg for the past month, specifically HDR to SDR tonemapping, asking questions over at this thread (https://forum.doom9.org/showthread.php?t=175125). There are still many questions I have, and from what I can tell there are not a whole lot of threads here for FFmpeg general discussion and use.

I figure this thread can be where for those of us that need advanced help with FFmpeg can ask the more experienced users questions. I'll throw a few links down below that have helped me get started as a beginner.

How to set up and use FFmpeg with Windows (https://video.stackexchange.com/questions/20495/how-do-i-set-up-and-use-ffmpeg-in-windows)

Emulating MadVR's HDR to SDR tonemapping using FFMPEG (https://forum.doom9.org/showthread.php?t=175125)

FFmpeg download link (https://ffmpeg.org/)

FFmpeg wiki (https://trac.ffmpeg.org/wiki)

EmKayVe
28th December 2018, 18:56
Here is what I'm currently working on and need help with:

Attempting to convert an UHD Blu Ray rip from HDR to SDR:

ffmpeg.exe -i video.mkv -vf zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p -c:v libx265 -crf 18 -preset slower output.mkv

So far, the output is good. I would like to pass through the audio and adding "acodec copy" gives me the following "Too many packets buffered for output stream 0:1"

Any help with the CLI would be appreciated.

Wakaku
29th December 2018, 04:54
I might had also encountered such message myself, but I can't remember how I ended up with it.

What is the codec for the audio track of the source Video.mkv?

Perhaps a workaround is to disable the audio track during the encoding process instead of lossless copy, via the "-an" option. Then after you end up with the new MKV without the audio track, use MKVToolNix to mux that new video file plus the audio track from the source MKV file. I think MKVToolNix has more chance to remux such problematic muxes. Of course sometimes FFmpeg is the more tolerant.

EmKayVe
29th December 2018, 05:01
I might had also encountered such message myself, but I can't remember how I ended up with it.

What is the codec for the audio track of the source Video.mkv?

Perhaps a workaround is to disable the audio track during the encoding process instead of lossless copy, via the "-an" option. Then after you end up with the new MKV without the audio track, use MKVToolNix to mux that new video file plus the audio track from the source MKV file. I think MKVToolNix has more chance to remux such problematic muxes. Of course sometimes FFmpeg is the more tolerant.

There are three audio codecs in the mkv file. I figured it would pick the first default audio track which is DTS-HD. Perhaps I should just encode instead since I was planning on taking the output and doing so in Handbrake.

How would I instead encode the following audio tracks into the final output using CLI in FFmpeg: AC3 5.1 at 384kbps & an AAC 2.0 at 128kbps.

Wakaku
29th December 2018, 05:28
There are three audio codecs in the mkv file. I figured it would pick the first default audio track which is DTS-HD. Perhaps I should just encode instead since I was planning on taking the output and doing so in Handbrake.

Indeed, I just tested now. I muxed together using MKVToolNix a video track plus 3 audio tracks in order: AAC, Vorbis, Opus. Then I remuxed that output file with FFmpeg (eg. ffmpeg -i Z.mkv -c copy Z2.mkv), and only the first audio track (which is the AAC) is retained.

How would I instead encode the following audio tracks into the final output using CLI in FFmpeg: AC3 5.1 at 384kbps & an AAC 2.0 at 128kbps.

Do you mean that you want to re-encode the original first audio track DTS-HD to both AC3 5.1 384kbps and AAC 2.0 128kbps?

Or the other two audio tracks from the source media file are those AC3 5.1 384kbps and AAC 2.0 128kbps, and you want to retain both of them?

Wakaku
29th December 2018, 06:05
I just tested again, still using my previous Z.mkv (which contains the 3 audio tracks). To retain all 3 audio tracks with FFmpeg, I now used:

ffmpeg -i "Z.mkv" -c:v copy -map 0:v:0 -c:a copy -map 0:a:0 -map 0:a:1 -map 0:a:2 "Z3.mkv"

0:v:0 = 1st video track
0:a:0 = 1st audio track
0:a:1 = 2nd audio track
0:a:2 = 3rd audio track

I just found out too that if I used mappings for the audio tracks, then I must also use mapping for the video track, because if I do not the output would only be the 3 audio tracks inside the MKV.

EmKayVe
29th December 2018, 08:28
Do you mean that you want to re-encode the original first audio track DTS-HD to both AC3 5.1 384kbps and AAC 2.0 128kbps?

Or the other two audio tracks from the source media file are those AC3 5.1 384kbps and AAC 2.0 128kbps, and you want to retain both of them?

Yes exactly (to the first part). I'd want to re-encode the original track to both AC3 & AAC. The other two tracks are a DTS track and AC3 track (but much higher bitrates than I would like).

Ideally, I want to be able to do this so that I don't have to turn to handbrake after an FFmpeg re-encode. I believe re-encoding an already re-encoded file is killing the quality more than if I just used FFmpeg to begin with.

EmKayVe
31st December 2018, 08:08
If someone could help me with the CLI, as I have very little idea of what I'm doing :). I'd like to change audio to include the following from the default track: AC3 5.1 384kbps and AAC 2.0 128kbps

Also, would like to encode to h264, 1080p, .mp4 - Thanks!

Just configure what I have already:

ffmpeg.exe -i video.mkv -vf zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p -c:v libx265 -crf 18 -preset slower output.mkv

Selur
6th January 2019, 11:12
You need to run 'ffmpeg -i video.mkv' to see the mapping ffmpeg assumes, based on that mapping adding (somewhere behind the loading of the inputs):
-c:a copy
would passthrough all audio streams from the source
-c:a copy -map 0:a:0
would passthrough only the first audio stream from your source
-c:a copy -map 0:a:1
would passthrough only the second audio stream from your source (run 'ffmpeg -i video.mkv' to see the mapping ffmpeg assumes)
-c:a copy -map 0:a:0 -map 0:a:1
would passthrough only the first and second audio stream from your source (run 'ffmpeg -i video.mkv' to see the mapping ffmpeg assumes)

Looking at:
-map A:a:B
A sets the index of the input to choose from
a sets that only audio streams should be looked at
B sets the index of the streams from the selection (here 'a' = audio)

sneaker_ger
6th January 2019, 12:42
-c:a copy
would passthrough all audio streams from the source
If you provide no explicit -map then ffmpeg will only use the default mapping (https://trac.ffmpeg.org/wiki/Map#Default) which means only one audio will be mapped.
"Passthrough all audio streams from first input file" is:
-map 0:a -c:a copy

EmKayVe
6th January 2019, 18:00
Awesome thank you both. To limit how many times I re-encode, could either of you provide the code for "AC3 5.1 384kbps and AAC 2.0 128kbps"? My target is taking the UHD/HDR down to FHD/SDR with those two aforementioned audio streams for remote Emby/Plex streams. This will limit the need for the server to transcode the file.

Also, does FFmpeg encode to .mp4? If so, how do I tell it to?

sneaker_ger
6th January 2019, 18:05
-c:a ac3
(it will downmix to 5.1 if necessary since the ac3 encoder doesn't support more than 6 channels anyways)

-c:a aac -ac 2
For aac encoding with stereo downmix.

Note that both of these will re-encode even if source is already ac3/aac. So use -c:a copy if that is the case to preserve 100% quality.

mp4 output:
If the output file name ends with ".mp4" ffmpeg will automatically create an mp4 file.

qyot27
6th January 2019, 18:55
I don't know if/how well FFmpeg can handle LFE mixing. Most of the time when I process my (4K or not) Blu-ray rips for watching on my desktop, I use eac3to to downmix and mix the LFE channel into the stereo signal (then encode the result to Opus and remux with the original video stream) so that when watching it back with mpv it doesn't cause nasty clipping when I try to use any volume boosting.

Of course, if you've got the right speaker setup, this is probably a completely moot point, but it is something to consider if not.

EmKayVe
6th January 2019, 19:21
-c:a ac3
(it will downmix to 5.1 if necessary since the ac3 encoder doesn't support more than 6 channels anyways)

-c:a aac -ac 2
For aac encoding with stereo downmix.

Note that both of these will re-encode even if source is already ac3/aac. So use -c:a copy if that is the case to preserve 100% quality.

mp4 output:
If the output file name ends with ".mp4" ffmpeg will automatically create an mp4 file.

I don't know if/how well FFmpeg can handle LFE mixing. Most of the time when I process my (4K or not) Blu-ray rips for watching on my desktop, I use eac3to to downmix and mix the LFE channel into the stereo signal (then encode the result to Opus and remux with the original video stream) so that when watching it back with mpv it doesn't cause nasty clipping when I try to use any volume boosting.

Of course, if you've got the right speaker setup, this is probably a completely moot point, but it is something to consider if not.

Ok got it thank you both for the help. The source is most likely TrueHD/Atmos (that is what I think all my UHDs are so far).

In regards to the LFE, I think the client would handle this if they have an AC3 capable player and if not the server will force the AAC instead.

So to recap my code will look like:

ffmpeg.exe -i video.mkv -vf zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p -c:a ac3 -c:a aac -ac 2 -c:v libx265 -crf 18 -preset slower output.mp4

ffmpeg.exe -i video.mkv -vf zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p -c:a ac3 -c:a aac -ac 2 -c:v libx265 -crf 18 -preset slower output.mp4

EDIT: It only encoded the red.

sneaker_ger
6th January 2019, 19:50
You want the same audio stream twice within the same output file? This wasn't clear to me from your other post. Then you have to map the same stream twice and use stream specifiers (https://ffmpeg.org/ffmpeg.html#Stream-specifiers-1) to tell ffmpeg which track the -c:a and -ac options apply to:
-map 0:v:0 -map 0:a:0 -map 0:a:0 -c:a:0 ac3 -c:a:1 aac -ac:a:1 2
Maps first video once, first audio twice.

EmKayVe
6th January 2019, 19:56
You want the same audio stream twice within the same output file? This wasn't clear to me from your other post. Then you have to map the same stream twice and use stream specifiers (https://ffmpeg.org/ffmpeg.html#Stream-specifiers-1) to tell ffmpeg which track the -c:a and -ac options apply to:
-map 0:v:0 -map 0:a:0 -map 0:a:0 -c:a:0 ac3 -c:a:1 aac -ac:a:1 2
Maps first video once, first audio twice.

Yes sorry. I would like the output file to have two audio streams for the client to choose from. Both streams encoded from the 1st audio source.

So something like this should work right?

ffmpeg.exe -i D:\Videos\Media\Temp\video.mkv -vf zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p,zscale=s=1920x1080 -map 0:v:0 -map 0:a:0 -map 0:a:0 -c:a:0 ac3 -c:a:1 aac -ac:a:1 2 -c:v libx265 -crf 20 -preset slower D:\Videos\Media\Temp\output.mp4

microchip8
6th January 2019, 20:00
it is not recommended to turn off desat (desat=0). This was derived from testing on the broken HDR sample from Sony (Camp fire). This sample is known to have screwed up HDR data, thus an incorrect conclusion was made that you should always disable desat

EmKayVe
7th January 2019, 02:58
it is not recommended to turn off desat (desat=0). This was derived from testing on the broken HDR sample from Sony (Camp fire). This sample is known to have screwed up HDR data, thus an incorrect conclusion was made that you should always disable desat

Ok got it. Recommendations? (desat=?)

EmKayVe
7th January 2019, 05:09
OK according to @Selur post here (https://forum.doom9.org/showthread.php?p=1854761#post1854761) he is using desat=2. I have found his code to be significantly different than my HDR to SDR conversion code I've been using. I'm till learning gents... Can anyone decode the code for me? Would this be superior for an UHD/HDR conversion? Remember, I'm re-encoding "UHD - BD movies" to a target of 1080p/SDR/AC3 (.mp4).

ffmpeg -y -loglevel fatal -threads 8 -i "F:\TestClips&Co\files\HDR\4K sun HDR test.mp4" -map 0:0 -an -sn -vf zscale=tin=smpte2084:min=bt2020nc:pin=bt2020:rin=tv:t=smpte2084:m=bt2020nc:p=bt2020:r=tv,zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=2.000:peak=0.000,zscale=t=bt709:m=bt709:r=tv -pix_fmt yuv420p10le -strict -1 -vsync 0 -f yuv4mpegpipe - | x265 --input - --output-depth 10 --y4m --profile main10 --qg-size 8 --limit-modes --no-open-gop --opt-ref-list-length-pps --radl 2 --lookahead-slices 0 --crf 18.00 --opt-qp-pps --cbqpoffs -2 --crqpoffs -2 --limit-refs 0 --ssim-rd --psy-rd 2.50 --rdoq-level 2 --psy-rdoq 10.00 --aq-mode 0 --deblock=-1:-1 --limit-sao --range limited --colormatrix bt709 --output "E:\Temp\00_35_54_2910_01.265"

Selur
7th January 2019, 19:06
I used the default values there for desat&peak, see: https://www.ffmpeg.org/ffmpeg-all.html#tonemap-1
While at is has anyone tested tonemap_opencl ? (see: https://www.ffmpeg.org/ffmpeg-all.html#tonemap_005fopencl)

EmKayVe
8th January 2019, 07:31
I used the default values there for desat&peak, see: https://www.ffmpeg.org/ffmpeg-all.html#tonemap-1
While at is has anyone tested tonemap_opencl ? (see: https://www.ffmpeg.org/ffmpeg-all.html#tonemap_005fopencl)

Got it ok I'll give it a shot thanks.

So my output files (from the code I used in #14) for a UHD/HDR to HD/SDR are approximately 2-3GB in size. This is unusually low compared to the output files I get from Handbrake (HEVC/CRF18/Slow) with a normal HD Blu Ray rip (same file). Is FFmpeg compressing more heavily than Handbrake?

Edit: also, I tried using the code you provided with no luck. CMD said it wasn't a command. Again, new to FFmpeg and trying to understand each command and its structure.

EmKayVe
12th February 2019, 06:51
Subtitles? Yep... I just realized I have a movie that needs English subs for Spanish speaking parts and the encoder didn't include them. Anyway to mux these back in? Perhaps there is a guide?

pandy
22nd February 2019, 16:42
I don't know if/how well FFmpeg can handle LFE mixing. Most of the time when I process my (4K or not) Blu-ray rips for watching on my desktop, I use eac3to to downmix and mix the LFE channel into the stereo signal (then encode the result to Opus and remux with the original video stream) so that when watching it back with mpv it doesn't cause nasty clipping when I try to use any volume boosting.

Of course, if you've got the right speaker setup, this is probably a completely moot point, but it is something to consider if not.


Usually LFE is ignored during downmixing (Dolby recommendation - personally i think this is due high risk of over-ranging but sane amount of LFE should be fine). Personally i use private down-mix:

for more than 5.1 to 5.1 scheme (critical feedback appreciated - didn't found anything on this topic - also Dolby documentation not very helpful)

"pan=5.1(side)|FL<1.414FL+FLC|FR<1.414FR+FRC|FC<2.828FC+FLC+FRC|LFE=LFE|SL<SL+BL|SR<SR+BR,aresample=resampler=soxr:osr=48000:cutoff=0.990:dither_method=0"

or quite classic 5.1 (compatible with 5.1 side and rear) to 2.0 downmixing (additional dynamic normalizer and resampler to 48k active)

"pan=stereo|FL < FL+1.414FC+0.5BL+0.5SL+0.25LFE|FR < FR+1.414FC+0.5BR+0.5SR+0.25LFE,dynaudnorm=p=1/sqrt(2):m=100:s=20,aresample=resampler=soxr:osr=48000:cutoff=0.990:precision=20"



or quite interesting HRTF based downmixed (main intention is headphone listening for example on your portable audio device
7.1 to 2.0@HRTF:

"[0:a:0]aformat=channel_layouts=7.1,aresample=resampler=soxr:osr=48000:cutoff=0.990:dither_method=0,asplit[71][sofai];[sofai]sofalizer=sofa=dodeca_and_7channel_3DSL_HRTF.sofa:gain=11:lfegain=9[sofao]"


File 'dodeca_and_7channel_3DSL_HRTF.sofa' is a HRTF coefficient set available for example in VLC distribution

pandy
22nd February 2019, 16:50
Subtitles? Yep... I just realized I have a movie that needs English subs for Spanish speaking parts and the encoder didn't include them. Anyway to mux these back in? Perhaps there is a guide?

Same as adding audio track to existing set

https://superuser.com/questions/1140452/ffmpeg-add-a-new-audio-track-to-existing-file

However you may wish to add additional metadata info (for example language descriptor) about this sub.
It can be done like this:
-map 1? -c:s copy -metadata:s:s:0 language=eng
question mark perform conditional processing - i.e. if input is not present ffmpeg will continue without error - useful thing for large scripts doing universal (many files) processing

pandy
22nd February 2019, 16:54
Got it ok I'll give it a shot thanks.

So my output files (from the code I used in #14) for a UHD/HDR to HD/SDR are approximately 2-3GB in size. This is unusually low compared to the output files I get from Handbrake (HEVC/CRF18/Slow) with a normal HD Blu Ray rip (same file). Is FFmpeg compressing more heavily than Handbrake?

Edit: also, I tried using the code you provided with no luck. CMD said it wasn't a command. Again, new to FFmpeg and trying to understand each command and its structure.

Asking such details you need to provide your command set - it may be case where default values used by ffmpeg are different than desired - x265/x264 are using private settings and not all ffmpeg global commands are mapped to external libraries (as ffmpeg use many external libraries side to own codecs).

for example my command line (script) may look like this:

@SET x264opts="crf=%vq%:level=4.1:qpmin=8:cabac=1:keyint=infinite:no-deblock=1:no-mbtree=1:me=dia:rc-lookahead=5:ref=3:subme=0:no-weightb=1:weightp=0:trellis=0:no-scenecut=1:no_psnr=1:no_ssim=1:fullrange=on:overscan=show:colorprim=bt709:transfer=bt709:colormatrix=bt709"

@ffmpeg.exe -hide_banner -v 32 -stats -y -color_range 2 -loop 1 -r 1 -i "%fimage%" -i "%faudio%" -vf %vproc% -c:v libx264 -preset faster -tune stillimage -profile:v high -level:v 4.1 -x264opts %x264opts% -x264-params %x264opts% -color_range 2 -c:a libfdk_aac -b:a 8k -af %aproc% -sn -dn -shortest -movflags faststart -f mp4 "%~n2_%~n1.mp4"

EmKayVe
8th March 2019, 03:24
Asking such details you need to provide your command set

Thanks pandy, here is my code:

ffmpeg.exe -i D:\Videos\Media\Temp\video.mkv -vf zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p,zscale=s=1920x1080 -map 0:v:0 -map 0:a:0 -map 0:a:0 -c:a:0 ac3 -c:a:1 aac -ac:a:1 2 -c:v libx265 -crf 20 -preset slower D:\Videos\Media\Temp\output.mp4

Looking for a "burn in" (since the output container is .mp4) of the 3rd subtitle track which is English.

EmKayVe
30th October 2019, 20:09
I tried the following code which I added in the code for burning the 3rd English sub track. The code is invalid. Can anyone provide a fix?

ffmpeg.exe -i G:\Videos\ffmpeg\video.mkv -vf zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=2,zscale=t=bt709:m=bt709:r=tv,format=yuv420p,zscale=s=1920x1080 -map 0:v:0 -map 0:a:0 -map 0:a:0 -c:a:0 ac3 -c:a:1 aac -ac:a:1 2 -c:v libx265 -crf 20 -preset slower -map 3? -c:s copy -metadata:s:s:0 language=eng G:\Videos\ffmpeg\output.mp4

sneaker_ger
30th October 2019, 20:41
You added "-map 3?" which should map all tracks from the 4th input file yet provided only a single input file ("-i G:\Videos\ffmpeg\video.mkv").

https://trac.ffmpeg.org/wiki/Map


When you receive errors: post the (complete) log so we can read the error messages.

Selur
31st October 2019, 09:57
-map 3? -c:s copy
seems wrong, try:
-c:s:2 copy
this should select the subtitle track with index 2 and copy it to the output. Note that if the format of the subtitle track is not supported by your output container this will fail.
-> best read the wiki sneaker linked to,...

For 'burning in' subtitles instead of remuxing them you need to use a filter, see: https://trac.ffmpeg.org/wiki/HowToBurnSubtitlesIntoVideo

sneaker_ger
31st October 2019, 12:08
-map 3? -c:s copy
seems wrong, try:
-c:s:2 copy
this should select the subtitle track with index 2 and copy it to the output.
No, that's not how it works. First you need to -map the track from the input to output. Then you need to tell ffmpeg to copy it (as opposed to convert/re-encode). The stream specifiers of -map are for the input, the specifiers for -c are for the output. So to copy (only) the 3rd subtitle track of the (first) input file:
-map 0:s:2 -c:s:0 copy

https://trac.ffmpeg.org/wiki/Map
https://ffmpeg.org/ffmpeg.html#Stream-specifiers-1

EmKayVe
22nd November 2019, 19:44
Ok I am encoding to mp4 so that is going to be more difficult. I suppose I could just encode to mkv then mux the subtitles back in via mkvtoolnix right?

EmKayVe
4th January 2020, 21:56
Please help me with this code. Here is what I'm trying to do. I want an ouput file at H265, SDR, 1080p, mp4, with both a AC3 audio and AAC audio track to choose from. Since it is MP4, the 3rd subtitle track has to be "burned" in. The file is an MKV, UHD Blu Ray rip with HDR.

ffmpeg.exe -i E:\ffmpeg\input.mkv -vf zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=2,zscale=t=bt709:m=bt709:r=tv,format=yuv420p,zscale=s=1920x1080 -map 0:v:0 -map 0:a:0 -map 0:a:0 -c:a:0 ac3 -c:a:1 aac -ac:a:1 2 -c:v libx265 -crf 20 -preset slow E:\ffmpeg\output.mp4

EDIT: Ok I realize I cannot encode to MP4 if I intend to copy over a subtitle track. So, changing code to mkv.

osgZach
11th January 2020, 01:05
Can anyone give me a reason why I should not trust/rely on Frame types provided by ffprobe? I have no reason to doubt it but I just want to be sure before I invest more time into what I'm doing.

I'm currently working on a method to batch analyse/split a file into chunks to accelerate VP9 encoding and despite reading such nonsense as ffmpeg cutting to the nearest keyframe (when -codec copy is used) I've had instances where a segment begins with corrupted (i.e non keyframe) frames. I could probably try -ss / -to but that would still require knowing where to cut ahead of time so the cuts were accurate and didn't include waste/unneeded frames. So I figure either way I'm looking at dumping every source files frame types with ffprobe so I can get the needed timecodes.

Unless someone knows a better way.
Also I'm little unclear on how its cutting range works.. Let's say I've got an I frame dead on at timecode 600. Should I be targeting the non-I frame directly preceding it as the segment_time to cut at? I'm unsure if I'm just getting lucky and ffmpeg is compensating for something when I tell it to cut a given timecode and it happens to come out clean.


The primary goal here is to cut clean, with no corrupt or repeated frames between any of the segments, and without re-encoding anything. Personally I don't need to do this because my workflow involves exporting to MagicYUV lossless AVI files, and I could probably just split those after the fact (and without a problem) with minimal difference in time losses due to cutting operations.

But it would be nice to produce something I can share with others that might actually be helpful, and sometimes I might want to bypass my workflow and just work on a given source directly.

EDIT: 1/10/20 7:53pm
Well this is interesting.

Here is a given set of frames. a keyframe, with a frame proceeding and preceeding it.
The source is an MKV from a bluray I own, ripped to MKV with MakeMKV. It plays fine looks fine, etc.



pkt_pts_time=825.283000
pkt_pos=3031059095
pict_type=B
coded_picture_number=19788


pkt_pts_time=825.325000
pkt_pos=3030754047
pict_type=I
coded_picture_number=19786


pkt_pts_time=825.366000
pkt_pos=3031301614
pict_type=B
coded_picture_number=19790



Now. If I specify this command


ffmpeg -i "input.mkv" -an -f segment -segment_times 825.283000 -reset_timestamps 1 -codec copy -map 0:0 "Input-test%03d.mkv"


I'll get two MKV files from the output. The second file opens fine in WMP playing from the start shows no corruption. It does in Vdub2 /VLC though.

If I change the output container to MP4, leaving everything else unchanged, the result changed slightly. Vdub2 and WMP preview it fine, but VLC shows corruption at the start of the file.


what in the lol is this ?
Is there something about file containers I am overlooking that would explain this? I can't tell if I've got a good cut or not. I know VLC can be a little finnicky too...

Even more puzzling is if I open both the MKV and MP4 with JRiver Media Center 26 (not sure what its using other than LAV) both play fine with no corruption.
I can convert the segment mkv to AVI (FMP4 and magicyuv) and it also shows no corruption in Vdub2, WMP, (VLC/FMP4 it won't play Magicyuv), etc even though the source MKV did... so I am guessing this is some weird decoding issue with players.

sneaker_ger
11th January 2020, 12:02
Looks like open GOP. The order in the text that ffprobe outputs is in display order (pts time). But notice how the coded_picture_number of the first B frame is higher than the one of the I frame. That means the B frame likely references said I frame (and/or a frame before that).

Bottom line is: not every I frame is a good split point. Not even every I frame that can be seeked to is a good one. Usually you want IDR frames for splitting.

osgZach
11th January 2020, 20:44
yeah funny that, I noticed that when I was trying to ascertain what actual frame I was viewing within Vdub, I assumed coded_picture_number meant something else and I was wrong.

I managed to find this discussion.. which didn't seem too promising in results for differentiating an IDR from other I Frames

https://video.stackexchange.com/questions/19250/how-to-identify-i-frame-from-idr-frame-in-the-ffprobe-show-frames-output

edit:

Did another stats dump to confirm it just lists every I frame as a keyframe. I also limited it to outputting I frames only. Which lead me to see this



key_frame=1
pkt_pts_time=1149.565000
pkt_pos=4213181483
pict_type=I
coded_picture_number=4893


key_frame=1
pkt_pts_time=1150.358000
pkt_pos=4216099860
pict_type=I
coded_picture_number=4894



This is the only time I've seen coded picture numbers follow sequentially in this source file (now that I've looked there are regular groupings like this), and also curious that two I frames are next to each other. Would it be correct to assume this would always be a safe cutting point?

sneaker_ger
11th January 2020, 23:26
Would it be correct to assume this would always be a safe cutting point?
Good question. I think specifically for Blu-Ray sources: yes (https://code.videolan.org/videolan/x264/commit/9fb055856a617f5ddca15a0c5745ff1c1486ad9a). Otherwise not. Not sure.

osgZach
12th January 2020, 00:35
Alright, thanks for your feedback. I'll do some more testing with other blu ray sourced files, since that is the primary intended purpose. Hopefully this behavior will stay consistent across all kinds of stuff. I've got some VC-1 discs I should also test with too.

edit:

I'm going to go with the aforementioned strategy of looking for groups of 2 or more consecutive iframes to target for cutting, but as an addendum I am still seeing weird as hell behavior which I will now relate my frustrations about.
I found a group of 4 consecutive iframes and started making test chunks, moving backwards in an attempt to try and find out where ffmpeg is actually deciding to cut (is it inclusive of the target specified or not). So I got all the way back to the first iframe in the bunch, specified its timecode and cut it.

Got corruption in VLC, got corruption in Vdub... OK, that's really weird...because if it was cutting the frame before the target it should still be clean, and if its cutting the frame after, it should still be clean since its an I-Frame also and its coded picture number is sequential.....

I repeated the test and switched the container from MKV to MP4 like I did in an earlier post. Corruption in VLC - NO corruption in Vdub, no corruption in Vivaldi (chromium), Firefox, WMP; I even checked in Vegas Pro 15. so I took it further and I encoded that chunk to a VP9 webm.

It came out clean. vivaldi plays it fine. VLC plays it fine. (wth???) WMP plays it fine. firefox plays it fine.

OK so what about the original MKV which showed corruption?
VLC shows corruption may be a weird playback buffer issue idk.. Vdub corruption, WMP no corruption.
I also encoded this file to VP9 webm.

Vdub, Vivaldi, Firefox, VLC all show no corruption.

As a final test I took the same MKV that showed corrupt, and again encoded it to MagicYUV M8Y0. Vdub/WMP show no corruption. (again VLC won't play this codec)

The only conclusions I can come to is
A) all these applications have inconsistent decoder behavior, even the same decoder maybe using different revisions?
or
B) the first I-Frame in the bunch is coded picture number 14444, the frame before it is a B frame, coded picture number 14446
And this harkens back to the first problem about out of order references, so as a sanity check - the first iframe in a group of iframes should never be used as a target? Because behavior is just too unpredictable even if ffmpeg seems to handle it properly itself.

I wanna rip my hair out

sneaker_ger
12th January 2020, 09:20
I'm going to go with the aforementioned strategy of looking for groups of 2 or more consecutive iframes to target for cutting, but as an addendum I am still seeing weird as hell behavior which I will now relate my frustrations about.
I found a group of 4 consecutive iframes and started making test chunks, moving backwards in an attempt to try and find out where ffmpeg is actually deciding to cut (is it inclusive of the target specified or not). So I got all the way back to the first iframe in the bunch, specified its timecode and cut it.
In my last answer I thought you wanted to cut on the 2nd (or later) I frame in a group of consecutive I frames of a Blu-Ray. The first I frame should not be safe.

(All in display order.)

mkver
12th January 2020, 16:56
I wonder whether the SPS and PPS in these tracks (we are talking about H.264 here, aren't we?) change in-band. In such instances, FFmpeg does not make sure that every frame that it flags as keyframe actually has the right parameter sets in front of it. Use mkvmerge (preferably the latest continuous build (https://mkvtoolnix.download/windows/continuous/64-bit/42.0.0/) as there has been a commit pertaining to this feature) to remux the transport stream from the BluRay as it inserts the correct SPS and PPS in such scenarios. (Remuxing a file already in mkv (or mp4) won't change anything.)

osgZach
12th January 2020, 20:33
In my last answer I thought you wanted to cut on the 2nd (or later) I frame in a group of consecutive I frames of a Blu-Ray. The first I frame should not be safe.

(All in display order.)

yeah I'm not always good at articulating things.




I wonder whether the SPS and PPS in these tracks (we are talking about H.264 here, aren't we?) change in-band. In such instances, FFmpeg does not make sure that every frame that it flags as keyframe actually has the right parameter sets in front of it. Use mkvmerge (preferably the latest continuous build (https://mkvtoolnix.download/windows/continuous/64-bit/42.0.0/) as there has been a commit pertaining to this feature) to remux the transport stream from the BluRay as it inserts the correct SPS and PPS in such scenarios. (Remuxing a file already in mkv (or mp4) won't change anything.)

I had considered mkvmerge before but I don't think I ever managed to find any really indepth examples on how cutting with it worked. In this case, yes I'd have to re-rip them (MakeMKV has two modes, one is full disc decryption/backup and the other lets you select what you want but only outputs decrypted streams to MKV)

But it'll be an interesting chore to get done and compare the results from. And yes they're H.264
At any rate, something more applicable to general files (a game recording or other unknown source), would still be nice to have as a tool I suspect.

I appreciate all the assistance thus far.