I think my issue is faced from time to time by several people, but I didn't manage to find a tool for this, so I decided to build one.

Elaborating from this answer, I built a simple bash script that should take a source video to be reencoded and a destination video as reference, like so (ffmatch.sh):



# parse the ini-like multiline text in $1, return
# the value of the field $2, e.g.:
# ini="
# color=red
# size=small
# "
# get_field $ini "color" # prints "red"
get_field() {
  echo -e "$1" | grep "^$2=" | cut -d = -f 2

video=`ffprobe -v quiet -select_streams v:0 -show_entries stream "$dst_file"`
audio=`ffprobe -v quiet -select_streams a:0 -show_entries stream "$dst_file"`

vcodec=`get_field "$video" "codec_name"`
w=`get_field "$video" "width"`
h=`get_field "$video" "height"`
vbps=`get_field "$video" "bit_rate"`
fps=`get_field "$video" "r_frame_rate"`
tbn=`get_field "$video" "time_base" | cut -d "/" -f 2`
tbc=`get_field "$video" "codec_time_base"`

acodec=`get_field "$audio" "codec_name"`
hz=`get_field "$audio" "sample_rate"`
abps=`get_field "$audio" "bit_rate"`

-vcodec $vcodec
-vf scale=w=$w:h=$h
-r $fps
-time_base $tbc
-video_track_timescale $tbn
-b:v $vbps
-acodec $acodec
-ar $hz
-b:a $abps

echo -e "reencoding using the following options:$opts"

ffmpeg -i "$src_file" $opts "$out_file"

It should work, but the fps, tbr, tbn and tbc values are mismatching, as you can see from the output of the following commands.

During the processing, ffmpeg displays several times the error: Queue input is backward in time.

$ ./ffmatch.sh source.mp4 destination.mp4
reencoding using the following options:
-vcodec h264
-vf scale=w=2160:h=1080
-r 181/12
-time_base 815767/24598800
-video_track_timescale 90000
-b:v 552061
-acodec aac
-ar 48000
-b:a 125375


$ ffprobe source.mp4 2>&1 | grep '\(Audio\|tbn\)'               
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 435 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 223 kb/s (default)

$ ffprobe destination.mp4 2>&1 | grep '\(Audio\|tbn\)'  
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc), 2160x1080, 552 kb/s, 15.08 fps, 15.08 tbr, 90k tbn, 2400k tbc (default)
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, mono, fltp, 125 kb/s (default)

$ ffprobe source_reencoded.mp4 2>&1 | grep '\(Audio\|tbn\)'     
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 2160x1080 [SAR 8:9 DAR 16:9], 544 kb/s, 30.09 fps, 30 tbr, 90k tbn, 60.31 tbc (default)
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 73 kb/s (default)

Note that if I remove the -time_base parameter, the values for fps, tbr and tbn will indeed match the reference video, but the tbc of course would not (it goes from 50 to 30.17 instead of the desired 2400k).

How should I tweak the script to get what I want?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.