The SSIM values calculated using FFMPEG are not what I expected - ffmpeg

I'm trying to encode an m2ts (MPEG-2 Transport Stream) file to mp4 (H.264) and get the ssim value.
I did get some SSIM values, but the results were contrary to my expectations.
Are there wrong command options for ffmpeg?
Encoding and SSIM calculation commands
# encode
$ ffmpeg -hide_banner -fflags +discardcorrupt -i input.m2ts \
-c:v libx264 -crf <CRF> -preset:v medium \
-c:a copy -bsf:a aac_adtstoasc \
output_ff_crf-<CRF>.mp4
# calculate ssim
$ ffmpeg -hide_banner -i <A> -i <B> \
-lavfi "[0:v]settb=AVTB,setpts=PTS-STARTPTS[main];[1:v]settb=AVTB,setpts=PTS-STARTPTS[ref];[main][ref]ssim" \
-f null -
The results of the SSIM
(a) A=input.m2ts, B=input.m2ts, ssim=0.973266
(b) A=input.m2ts, B=output_ff_crf-0.mp4, ssim=0.813347
(c) A=input.m2ts, B=output_ff_crf-30.mp4, ssim=0.819897
(d) A=output_ff_crf-0.mp4, B=output_ff_crf-0.mp4, ssim=1.000000
(e) A=output_ff_crf-0.mp4, B=output_ff_crf-30.mp4, ssim=0.972911
(d)(e): These are what I expected.
(a): The files are the same, but ssim≠1.
(b)(c): SSIMs with CRF=0 and CRF=30 have almost the same value, although the image quality is different.
In the case of HandBrakeCLI
To determine if there was a problem with input.m2ts, I ran HandBrakeCLI with almost the same parameters as ffmpeg.
# encode
HandBrakeCLI --verbose --format av_mp4 --encoder x264 --quality <CRF> --x264-preset medium \
--aencoder copy \
--input input.m2ts --output output_hb_crf-<CRF>.mp4
# calculate ssim (same as ffmpeg)
$ ffmpeg -hide_banner -i <A> -i <B> \
-lavfi "[0:v]settb=AVTB,setpts=PTS-STARTPTS[main];[1:v]settb=AVTB,setpts=PTS-STARTPTS[ref];[main][ref]ssim" \
-f null -
(b') A=input.m2ts, B=output_hb_crf-0.mp4, ssim=0.999999
(c') A=input.m2ts, B=output_hb_crf-30.mp4, ssim=0.972886
(d') A=output_hb_crf-0.mp4, B=output_hb_crf-0.mp4, ssim=1.000000
(e') A=output_hb_crf-0.mp4, B=output_hb_crf-30.mp4, ssim=0.972886
It's all as I expected. (although A is not ssim=1.0)
Therefore, I don't see a problem with input.m2ts.
Informations about video files and tools
Results of the ffprobe
input.m2ts
[mpeg2video # 0x5655577c1680] Invalid frame dimensions 0x0.
Last message repeated 1 times
[mpegts # 0x5655577bd080] start time for stream 2 is not set in estimate_timings_from_pts
[mpegts # 0x5655577bd080] PES packet size mismatch
Input #0, mpegts, from 'input.m2ts':
Duration: 00:30:02.68, start: 39593.392600, bitrate: 19019 kb/s
Program 211
Stream #0:0[0x140]: Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p(tv, bt709, top first), 1920x1080 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc
Stream #0:1[0x141]: Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 255 kb/s
Stream #0:2[0x138]: Data: bin_data ([6][0][0][0] / 0x0006)
Unsupported codec with id 100359 for input stream 2
output_ff_crf-0.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output_ff_crf-0.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf57.83.100
Duration: 00:30:02.67, start: 0.000000, bitrate: 109301 kb/s
Stream #0:0(und): Video: h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 109040 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 252 kb/s (default)
Metadata:
handler_name : SoundHandler
output_hb_crf-0.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output_hb_crf-0.mp4':
Metadata:
major_brand : mp42
minor_version : 512
compatible_brands: isomiso2avc1mp41
creation_time : 2020-05-17T06:22:06.000000Z
encoder : HandBrake 1.1.0 2018042400
Duration: 00:30:02.22, start: 0.000000, bitrate: 109661 kb/s
Stream #0:0(und): Video: h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 109405 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 180k tbc (default)
Metadata:
creation_time : 2020-05-17T06:22:06.000000Z
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 252 kb/s (default)
Metadata:
creation_time : 2020-05-17T06:22:06.000000Z
handler_name : Stereo
Tools
version
ffmpeg: 3.4.6-0ubuntu0.18.04.1
HandBrakeCLI: 1.1.0
ldd
$ ldd /usr/bin/ffmpeg
...
libx264.so.152 => /usr/lib/x86_64-linux-gnu/libx264.so.152 (0x00007efbf1f33000)
...
$ ldd /usr/bin/HandBrakeCLI
...
libx264.so.152 => /usr/lib/x86_64-linux-gnu/libx264.so.152 (0x00007efbfb38f000)
...
ffmpeg and HandBrakeCLI are using the same libx264.

Related

combining a png and a video file with ffmpeg without re-encoding

I'm trying to create a oneline for ffmpeg where I have:
original a/v recording in h264/mkv from which I need part of recording
png image as title card
I want to create a 5 second silent title before a part of video starts, possible in one ffmpeg line and codec-copy for the video.
Things I tried so far:
generate an mp4 from png with silence as audio track (needed by concating later):
ffmpeg -f lavfi \
-i anullsrc=channel_layout=stereo:sample_rate=44100 \
-loop 1 \
-i TITLE1080.png \
-s hd1080 \
-vf "fps=25,format=yuv420p" \
-c:a aac \
-t 5 \
TITLE1080.mp4
Cutting out a relevant portion from the video in mkv container (copy video in h264) and reenconcoding audio to aac:
ffmpeg -i VIDEO.mkv \
-ss 01:12:21 \
-to 02:12:40 \
-c:v copy \
-b:a 320k \
-avoid_negative_ts 1 \
OUTPUT.mp4
Concatenating the two h264/mp4 files via filelist1.txt file:
file '/path/to/TITLE1080.mp4'
file '/path/to/OUTPUT.mp4'
and then:
ffmpeg -f concat \
-safe 0 \
-segment_time_metadata 1 \
-i filelist1.txt \
-c copy \
-r 30 \
FINAL.mp4
The result has audio that seemingly drifts out of sync like it runs slightly faster so it finishes before and that after an hour there's silence for cca 5 minutes while the video still runs.
Re-encoding fixes all those problems but I would like to work with -c copy but rebuild the timestamps and ensure av sync.
How to make av sync correct and is it possible to have a one-liner ffmpeg command in bash/shell on linux?
here's ffprobe for both video files:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'TITLE1080.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.29.100
Duration: 00:00:05.02, start: 0.000000, bitrate: 79 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 67 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 2 kb/s (default)
Metadata:
handler_name : SoundHandler
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'OUTPUT.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.29.100
Duration: 00:42:56.67, start: 0.000000, bitrate: 5334 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 5002 kb/s, 30 fps, 30 tbr, 16k tbn, 60 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 322 kb/s (default)
Metadata:
handler_name : SoundHandler

How can I concatenate multiple MP4 videos with FFMPEG without audio sync issues?

My procedure is as follows:
convert the videos to 1920x1080 at 60 FPS (some videos had only 30 FPS)
save the converted videos in a text file
merging the video by an FFMPEG concat
After the videos are merged, the audio is out of sync with the video.
To convert the videos I use the following command: ffmpeg -i input.mp4 -vf scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:-1:-1,setsar=1 -r 60 output.mp4
(got it from here: How can I upscale videos with FFmpeg to a fixed resolution?)
My FFMPEG command to concat the videos: ffmpeg -f concat -safe 0 -i videolist.txt -c copy final.mp4
When I concatonate the videos, I sometimes get a lot of these warnings:
[mp4 # 0x55740b62ad40] Non-monotonous DTS in output stream 0:1; previous: 336921, current: 336064; changing to 336922. This may result in incorrect timestamps in the output file.
A question for the FFMPEG professionals, how can I make sure that video and audio are in sync?
UPDATE:
Here are the details of the files being listed in the videolist.txt
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'intro.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.20.100
Duration: 00:00:07.04, start: 0.000000, bitrate: 291 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 187 kb/s, 60 fps, 60 tbr, 15360 tbn, 120 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 91 kb/s (default)
Metadata:
handler_name : SoundHandler
Input #1, mov,mp4,m4a,3gp,3g2,mj2, from '4t6Brqa4E5BnD6vC5inICusEtPtd3nU88NgbmUJ.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.20.100
Duration: 00:00:37.66, start: 0.000000, bitrate: 1608 kb/s
Stream #1:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 1532 kb/s, 60 fps, 60 tbr, 15360 tbn, 120 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #1:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 69 kb/s (default)
Metadata:
handler_name : SoundHandler
Input #2, mov,mp4,m4a,3gp,3g2,mj2, from 'cut.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.20.100
Duration: 00:00:00.65, start: 0.000000, bitrate: 7128 kb/s
Stream #2:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 7576 kb/s, 60 fps, 60 tbr, 15360 tbn, 120 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #2:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 115 kb/s (default)
Metadata:
handler_name : IsoMedia File Produced by Google, 5-11-2011
Input #3, mov,mp4,m4a,3gp,3g2,mj2, from '80SEh7RoTyVPNj3zTZSaixxATvUYXMNyzu15evs.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.20.100
Duration: 00:00:07.75, start: 0.000000, bitrate: 1191 kb/s
Stream #3:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 1106 kb/s, 60 fps, 60 tbr, 15360 tbn, 120 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #3:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 70 kb/s (default)
Metadata:
handler_name : SoundHandler
Input #4, mov,mp4,m4a,3gp,3g2,mj2, from 'outro.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.20.100
Duration: 00:00:15.17, start: 0.000000, bitrate: 3417 kb/s
Stream #4:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 3286 kb/s, 60 fps, 60 tbr, 15360 tbn, 120 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #4:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s (default)
Metadata:
handler_name : SoundHandler
All attributes must be the same, but your audio has varying channel layouts (stereo & mono) and sample rates (48000 & 44100).
Add -ar 48000 -ac 2 to your command:
ffmpeg -i input.mp4 -vf scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:-1:-1,setsar=1 -r 60 -ar 48000 -ac 2 output.mp4
Alternatively, if you want to avoid any temporary files you can do everything in one command using the concat filter as shown in How to concatenate videos in ffmpeg with different attributes?.

Crop black padding and resize back to original 1920x1080

I have video of resolution 1920x1080 (16:9 aspect ratio). When played its padded with black box on all sides. How to remove the black boxes to get the 1920x1080 video?
Screenshot of video
Below the audio and video details:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'Maths Logic.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.19.102
Duration: 00:43:11.24, start: 0.000000, bitrate: 1475 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 1405 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 64 kb/s (default)
Metadata:
handler_name : SoundHandler
Use cropdetect filter to get crop values:
ffmpeg -i input.mp4 -vf cropdetect -frames:v 3 -f null -
...
[Parsed_cropdetect_0 # 0x559116cfe440] x1:240 x2:1679 y1:56 y2:1078 w:1440 h:1008 x:240 y:64 pts:2 t:2.000000 crop=1440:1008:240:64
Then use crop filter to crop the black, scale to upscale back to 1080, and then pad to fill in missing area to make 16:9 aspect ratio:
ffmpeg -i input.mp4 -vf "crop=1440:1008:240:64,scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:-1:-1" -c:a copy output.mp4
Before and after:

video png overlay issue using concat

may i ask help to understand why the png logo appears only on the first video of the concat result?
Thanks!
ffmpeg -f concat -safe 0 -y -i list.txt -i ../logo/logo.png -c:a copy -c:v libx264 -x264opts keyint=$50:min-keyint=$50:no-scenecut -bf 0 -r $25 -b:v 4800k -maxrate 9600k -bufsize 19200k -profile:v main -crf 22 -filter_complex "[0:v][1:v]overlay=main_w-overlay_w-10:10,scale=1920:1080,setsar=1" -t 370 1080set.mp4
I suspect the 2nd and possibly further inputs have video streams with differing properties, so the filtergraph gets reinitialized, and at that point, since you haven't looped the image, there's no image frame left to overlay.
So, loop the image,
ffmpeg -f concat -safe 0 -y -i list.txt -loop 1 -i ../logo/logo.png -c:a copy -c:v libx264 -x264opts keyint=$50:min-keyint=$50:no-scenecut -bf 0 -r $25 -b:v 4800k -maxrate 9600k -bufsize 19200k -profile:v main -crf 22 -filter_complex "[0:v][1:v]overlay=main_w-overlay_w-10:10,scale=1920:1080,setsar=1" -t 370 1080set.mp4
Metadata:
major_brand : isom
minor_version : 1
compatible_brands: isomavc1
creation_time : 2007-05-09T07:55:25.000000Z
Duration: 00:01:29.22, start: 0.000000, bitrate: 7490 kb/s
Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 1920x816, 7403 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
Metadata:
creation_time : 2007-05-09T07:55:25.000000Z
handler_name : GPAC ISO Video Handler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 94 kb/s (default)
Metadata:
creation_time : 2007-05-09T07:55:29.000000Z
handler_name : GPAC ISO Audio Handler
Metadata:
major_brand : isom
minor_version : 1
compatible_brands: isomavc1
creation_time : 2007-07-17T09:18:37.000000Z
genre : Trailer
artist : Fox
title : The Simpsons Movie
date : 2007
Duration: 00:02:17.25, start: 0.000000, bitrate: 8591 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x800, 8486 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
Metadata:
creation_time : 2007-07-17T09:18:37.000000Z
handler_name : GPAC ISO Video Handler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, 5.1, fltp, 107 kb/s (default)
Metadata:
creation_time : 2007-07-17T09:18:45.000000Z
handler_name : GPAC ISO Audio Handler
Stream #0:2: Video: mjpeg (Progressive), yuvj420p(pc, bt470bg/unknown/unknown), 101x150 [SAR 72:72 DAR 101:150], 90k tbr, 90k tbn, 90k tbc (attached pic)

Firefox says some files converted from mkv to mp4 in ffmpeg are corrupt

I have recently converted many videos for web playback, but all videos from one "series" all show up in firefox as "Video can't be played because the file is corrupt." (They work for google chrome and VLC. Not for firefox or edge.) All files have been converted with this command:
ffmpeg -i "file.mkv" -vcodec h264 -movflags +faststart -map 0 -vf subtitles="file.mkv" "file.mp4"
ffmpeg output from one of the non-working files:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'Episode_7.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.3.100
Duration: 00:23:53.52, start: -0.001333, bitrate: 1900 kb/s
Stream #0:0(und): Video: h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuv444p, 1920x1080 [SAR 1:1 DAR 16:9], 1763 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 130 kb/s (default)
Metadata:
handler_name : SoundHandler
ffmpeg output from a working file:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'Episode_7.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.3.100
Duration: 00:23:40.06, start: 0.000000, bitrate: 1848 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 1710 kb/s, 23.81 fps, 23.81 tbr, 16k tbn, 47.62 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(jpn): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 131 kb/s (default)
Metadata:
handler_name : SoundHandler
Of a collection of over 100 files, only 12 episodes of a single series show up as corrupted in firefox. I see some differences in the information about the two files, but I don't know why one file works and the other does not. What do I need to tell ffmpeg to make the videos playable in firefox?
It's the 4:4:4 chroma sampling. Add -pix_fmt yuv420p to the output file.

Resources