videoffmpegvideo-encodingmpegh.265

Transcoding MPEG-1 to MPEG-H (H.265/HEVC)


Transcoding MPEG-4 video to MPEG-H in order to reduce the size in half without losing perceivable quality is relatively easy with a 2-pass approach presented within FFMPEG documentation. The scheme that I've been using is to extract the bit_rate value from the original MPEG-4 video using ffprobe and then multiply that value by 4 / 10. Thus, that new lower value would be specified by -b:v and become the bit_rate value of the resulting MPEG-H video. This worked quite well for most of the videos, not only with MPEG-4, but also with QuickTime and Audio Video Interleave (AVI).

However, now I stumbled across the issue with transcoding MPEG-1 video in such a way. Somehow, the resulting MPEG-H video is unacceptably larger than the original video by a hefty margin. A 200MB original video could easily result in 1.5GB transcoded video. When I looked for a reason for such ridiculous behavior, I found out that somehow the advertised bit_rate value in MPEG-1 videos is also ridiculously high. Take the following two videos as an example (output from ffprobe):

164MB                           15MB
[STREAM]                        [STREAM]
index=0                         index=1
codec_name=mpeg4                codec_name=mpeg1video
codec_long_name=MPEG-4 part 2   codec_long_name=MPEG-1 video
profile=Simple Profile          profile=unknown
codec_type=video                codec_type=video
codec_time_base=1/24            codec_time_base=1/25
codec_tag_string=mp4v           codec_tag_string=[0][0][0][0]
codec_tag=0x7634706d            codec_tag=0x0000
width=960                       width=640
height=540                      height=480
coded_width=960                 coded_width=0
coded_height=540                coded_height=0
closed_captions=0               closed_captions=0
has_b_frames=0                  has_b_frames=1
sample_aspect_ratio=1:1         sample_aspect_ratio=1:1
display_aspect_ratio=16:9       display_aspect_ratio=4:3
pix_fmt=yuv420p                 pix_fmt=yuv420p
level=1                         level=-99
color_range=unknown             color_range=tv
color_space=unknown             color_space=unknown
color_transfer=unknown          color_transfer=unknown
color_primaries=unknown         color_primaries=unknown
chroma_location=left            chroma_location=center
field_order=unknown             field_order=unknown
timecode=N/A                    timecode=N/A
refs=1                          refs=1
quarter_sample=false            
divx_packed=false               
id=N/A                          id=0x1e0
r_frame_rate=24/1               r_frame_rate=25/1
avg_frame_rate=24/1             avg_frame_rate=25/1
time_base=1/24                  time_base=1/90000
start_pts=0                     start_pts=9900
start_time=0.000000             start_time=0.110000
duration_ts=7451                duration_ts=3690000
duration=310.458333             duration=41.000000
bit_rate=4096346                bit_rate=104857200
max_bit_rate=9000000            max_bit_rate=N/A
bits_per_raw_sample=N/A         bits_per_raw_sample=N/A
nb_frames=7451                  nb_frames=N/A
nb_read_frames=N/A              nb_read_frames=N/A
nb_read_packets=N/A             nb_read_packets=N/A
DISPOSITION:default=1           DISPOSITION:default=0
DISPOSITION:dub=0               DISPOSITION:dub=0
DISPOSITION:original=0          DISPOSITION:original=0
DISPOSITION:comment=0           DISPOSITION:comment=0
DISPOSITION:lyrics=0            DISPOSITION:lyrics=0
DISPOSITION:karaoke=0           DISPOSITION:karaoke=0
DISPOSITION:forced=0            DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0  DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0   DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0     DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0      DISPOSITION:attached_pic=0
DISPOSITION:timed_thumbnails=0  DISPOSITION:timed_thumbnails=0
[/STREAM]                       [/STREAM]

Clearly, the MPEG-4 video is like 11 times larger than MPEG-1, but at the same time MPEG-4 video has like 100000000 less bit rate advertised than MPEG-1. And since my algorithm does not consider anything else to compute the final bit rate, that is how the problem facilitates itself. Now I tried to look into some other field values in search for a hint that maybe something else should also be included into the equation, and my suspicions lie in the following ones:

time_base=1/24                  time_base=1/90000
start_pts=0                     start_pts=9900
start_time=0.000000             start_time=0.110000
duration_ts=7451                duration_ts=3690000
duration=310.458333             duration=41.000000

I'm not an expert with MPEG and the documentation isn't very informative on these in a way that I could derive some math out of it or otherwise somehow connect them to resolving my issue in a meaningful way. Could anybody experienced please assist here?


Solution

  • By searching the web, I figured out that bit rate value of 104857200 is some kind of indication of an issue, perhaps metadata related. One can search for the ffmpeg and 104857 kb/s keywords. Hence, this value simply cannot be taken seriously as already presented in my question. Luckily enough, the FORMAT section also has bit_rate of the file as per:

    ffprobe -v error -show_entries format=bit_rate -of default=noprint_wrappers=1:nokey=1 <video-file>
    

    In case of MPEG-1, this bit_rate value corresponds exactly to the required bit rate of the video stream only (yes, it's important that audio stream is not included there). For example, the subject MPEG-1 has a value of 2914159.

    As a result, the algorithm for transcoding videos to MPEG-H now simply tests whether the return value of

    ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 <video-file>
    

    is equal to mpeg1video, and if it is, it branches off to retrieve bit_rate from FORMAT section rather than video STREAM section.