mirror of
https://github.com/mediacms-io/mediacms.git
synced 2024-11-22 16:23:35 +01:00
Framerate fix (#246)
* Framerate fix Keep original framerate up to 60fps, halve any framerate above 60fps. Because of "video_frame_rate": Fraction(video_info["r_frame_rate"]), it does not work, when float used, the video is encoded but framerate suffers from rounding error. * Framerate fix Keep original framerate up to 60fps, halve any framerate above 60fps. Because of "video_frame_rate": Fraction(video_info["r_frame_rate"]), it does not work, when float used, the video is encoded but framerate suffers from rounding error. * Introduction of minimum bitrate modifier A minimum bitrate modifier introduced as per https://developers.google.com/media/vp9/settings/vod * Introduction of minimum bitrate modifier A minimum bitrate modifier introduced as per https://developers.google.com/media/vp9/settings/vod
This commit is contained in:
parent
062e4be6c2
commit
48838ac406
@ -23,6 +23,8 @@ CRF_ENCODING_NUM_SECONDS = 2 # 0 * 60 # videos with greater duration will get
|
|||||||
# you should use CRF encoding.
|
# you should use CRF encoding.
|
||||||
|
|
||||||
MAX_RATE_MULTIPLIER = 1.5
|
MAX_RATE_MULTIPLIER = 1.5
|
||||||
|
MIN_RATE_MULTIPLIER = 0.5
|
||||||
|
|
||||||
BUF_SIZE_MULTIPLIER = 1.5
|
BUF_SIZE_MULTIPLIER = 1.5
|
||||||
|
|
||||||
# in seconds, anything between 2 and 6 makes sense
|
# in seconds, anything between 2 and 6 makes sense
|
||||||
@ -238,7 +240,8 @@ def media_file_info(input_file):
|
|||||||
- `filename`: Filename
|
- `filename`: Filename
|
||||||
- `file_size`: Size of the file in bytes
|
- `file_size`: Size of the file in bytes
|
||||||
- `video_duration`: Duration of the video in `s.msec`
|
- `video_duration`: Duration of the video in `s.msec`
|
||||||
- `video_frame_rate`: Framerate in Hz
|
- `video_frame_rate_d`: Framerate franction denominator
|
||||||
|
- `video_frame_rate_n`: Framerate fraction nominator
|
||||||
- `video_bitrate`: Bitrate of the video stream in kBit/s
|
- `video_bitrate`: Bitrate of the video stream in kBit/s
|
||||||
- `video_width`: Width in pixels
|
- `video_width`: Width in pixels
|
||||||
- `video_height`: Height in pixels
|
- `video_height`: Height in pixels
|
||||||
@ -367,17 +370,30 @@ def media_file_info(input_file):
|
|||||||
stream_size = sum([int(line) for line in stdout.split("\n") if line != ""])
|
stream_size = sum([int(line) for line in stdout.split("\n") if line != ""])
|
||||||
video_bitrate = round((stream_size * 8 / 1024.0) / video_duration, 2)
|
video_bitrate = round((stream_size * 8 / 1024.0) / video_duration, 2)
|
||||||
|
|
||||||
|
if "r_frame_rate" in video_info.keys():
|
||||||
|
video_frame_rate = video_info["r_frame_rate"].partition("/")
|
||||||
|
video_frame_rate_n = video_frame_rate[0]
|
||||||
|
video_frame_rate_d = video_frame_rate[2]
|
||||||
|
|
||||||
ret = {
|
ret = {
|
||||||
"filename": input_file,
|
"filename": input_file,
|
||||||
"file_size": file_size,
|
"file_size": file_size,
|
||||||
"video_duration": video_duration,
|
"video_duration": video_duration,
|
||||||
"video_frame_rate": float(Fraction(video_info["r_frame_rate"])),
|
"video_frame_rate_n": video_frame_rate_n,
|
||||||
|
"video_frame_rate_d": video_frame_rate_d,
|
||||||
"video_bitrate": video_bitrate,
|
"video_bitrate": video_bitrate,
|
||||||
"video_width": video_info["width"],
|
"video_width": video_info["width"],
|
||||||
"video_height": video_info["height"],
|
"video_height": video_info["height"],
|
||||||
"video_codec": video_info["codec_name"],
|
"video_codec": video_info["codec_name"],
|
||||||
"has_video": has_video,
|
"has_video": has_video,
|
||||||
"has_audio": has_audio,
|
"has_audio": has_audio,
|
||||||
|
"color_range": video_info.get("color_range"),
|
||||||
|
"color_space": video_info.get("color_space"),
|
||||||
|
"color_transfer": video_info.get("color_space"),
|
||||||
|
"color_primaries": video_info.get("color_primaries"),
|
||||||
|
"field_order": video_info.get("field_order"),
|
||||||
|
"display_aspect_ratio": video_info.get("display_aspect_ratio"),
|
||||||
|
"sample_aspect_ratio": video_info.get("sample_aspect_ratio"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if has_audio:
|
if has_audio:
|
||||||
@ -492,7 +508,7 @@ def get_base_ffmpeg_command(
|
|||||||
codec {str} -- video codec
|
codec {str} -- video codec
|
||||||
encoder {str} -- video encoder
|
encoder {str} -- video encoder
|
||||||
audio_encoder {str} -- audio encoder
|
audio_encoder {str} -- audio encoder
|
||||||
target_fps {int} -- target FPS
|
target_fps {fractions.Fraction} -- target FPS
|
||||||
target_height {int} -- height
|
target_height {int} -- height
|
||||||
target_rate {int} -- target bitrate in kbps
|
target_rate {int} -- target bitrate in kbps
|
||||||
target_rate_audio {int} -- audio target bitrate
|
target_rate_audio {int} -- audio target bitrate
|
||||||
@ -501,10 +517,12 @@ def get_base_ffmpeg_command(
|
|||||||
enc_type {str} -- encoding type (twopass or crf)
|
enc_type {str} -- encoding type (twopass or crf)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
target_fps = int(target_fps)
|
# avoid very high frame rates
|
||||||
# avoid Frame rate very high for a muxer not efficiently supporting it.
|
while target_fps > 60:
|
||||||
if target_fps > 90:
|
target_fps = target_fps/2
|
||||||
target_fps = 90
|
|
||||||
|
if target_fps < 1:
|
||||||
|
target_fps = 1
|
||||||
|
|
||||||
base_cmd = [
|
base_cmd = [
|
||||||
settings.FFMPEG_COMMAND,
|
settings.FFMPEG_COMMAND,
|
||||||
@ -622,6 +640,8 @@ def get_base_ffmpeg_command(
|
|||||||
str(keyframe_distance),
|
str(keyframe_distance),
|
||||||
"-maxrate",
|
"-maxrate",
|
||||||
str(int(int(target_rate) * MAX_RATE_MULTIPLIER)) + "k",
|
str(int(int(target_rate) * MAX_RATE_MULTIPLIER)) + "k",
|
||||||
|
"-minrate",
|
||||||
|
str(int(int(target_rate) * MIN_RATE_MULTIPLIER)) + "k",
|
||||||
"-bufsize",
|
"-bufsize",
|
||||||
str(int(int(target_rate) * BUF_SIZE_MULTIPLIER)) + "k",
|
str(int(int(target_rate) * BUF_SIZE_MULTIPLIER)) + "k",
|
||||||
"-speed",
|
"-speed",
|
||||||
@ -669,8 +689,8 @@ def produce_ffmpeg_commands(media_file, media_info, resolution, codec, output_fi
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
src_framerate = media_info.get("video_frame_rate", 30)
|
target_fps = Fraction(int(media_info.get("video_frame_rate_n", 30)), int(media_info.get("video_frame_rate_d", 1)))
|
||||||
if src_framerate <= 30:
|
if target_fps <= 30:
|
||||||
target_rate = VIDEO_BITRATES[codec][25].get(resolution)
|
target_rate = VIDEO_BITRATES[codec][25].get(resolution)
|
||||||
else:
|
else:
|
||||||
target_rate = VIDEO_BITRATES[codec][60].get(resolution)
|
target_rate = VIDEO_BITRATES[codec][60].get(resolution)
|
||||||
@ -687,8 +707,6 @@ def produce_ffmpeg_commands(media_file, media_info, resolution, codec, output_fi
|
|||||||
# target_fps = 25
|
# target_fps = 25
|
||||||
# else:
|
# else:
|
||||||
|
|
||||||
# adjust the target frame rate if the input is fractional
|
|
||||||
target_fps = src_framerate if isinstance(src_framerate, int) else math.ceil(src_framerate)
|
|
||||||
|
|
||||||
if media_info.get("video_duration") > CRF_ENCODING_NUM_SECONDS:
|
if media_info.get("video_duration") > CRF_ENCODING_NUM_SECONDS:
|
||||||
enc_type = "crf"
|
enc_type = "crf"
|
||||||
@ -700,6 +718,7 @@ def produce_ffmpeg_commands(media_file, media_info, resolution, codec, output_fi
|
|||||||
elif enc_type == "crf":
|
elif enc_type == "crf":
|
||||||
passes = [2]
|
passes = [2]
|
||||||
|
|
||||||
|
|
||||||
cmds = []
|
cmds = []
|
||||||
for pass_number in passes:
|
for pass_number in passes:
|
||||||
cmds.append(
|
cmds.append(
|
||||||
|
Loading…
Reference in New Issue
Block a user