class VideoMetadataExtractor
attr_reader :duration, :bitrate, :video_codec, :audio_codec,
- :colorspace, :width, :height, :frame_rate
+ :colorspace, :width, :height, :frame_rate, :r_frame_rate
def initialize(path)
@path = path
@width = video_stream[:width]
@height = video_stream[:height]
@frame_rate = video_stream[:avg_frame_rate] == '0/0' ? nil : Rational(video_stream[:avg_frame_rate])
+ @r_frame_rate = video_stream[:r_frame_rate] == '0/0' ? nil : Rational(video_stream[:r_frame_rate])
end
if (audio_stream = audio_streams.first)
MAX_DESCRIPTION_LENGTH = 1_500
+ IMAGE_LIMIT = 10.megabytes
+ VIDEO_LIMIT = 40.megabytes
+
+ MAX_VIDEO_MATRIX_LIMIT = 2_304_000 # 1920x1200px
+ MAX_VIDEO_FRAME_RATE = 60
+
IMAGE_FILE_EXTENSIONS = %w(.jpg .jpeg .png .gif).freeze
VIDEO_FILE_EXTENSIONS = %w(.webm .mp4 .m4v .mov).freeze
AUDIO_FILE_EXTENSIONS = %w(.ogg .oga .mp3 .wav .flac .opus .aac .m4a .3gp .wma).freeze
VIDEO_FORMAT = {
format: 'mp4',
content_type: 'video/mp4',
+ vfr_frame_rate_threshold: MAX_VIDEO_FRAME_RATE,
convert_options: {
output: {
'loglevel' => 'fatal',
all: '-quality 90 -strip +set modify-date +set create-date',
}.freeze
- IMAGE_LIMIT = 10.megabytes
- VIDEO_LIMIT = 40.megabytes
-
- MAX_VIDEO_MATRIX_LIMIT = 2_304_000 # 1920x1200px
- MAX_VIDEO_FRAME_RATE = 60
-
belongs_to :account, inverse_of: :media_attachments, optional: true
belongs_to :status, inverse_of: :media_attachments, optional: true
belongs_to :scheduled_status, inverse_of: :media_attachments, optional: true
@time = options[:time] || 3
@passthrough_options = options[:passthrough_options]
@convert_options = options[:convert_options].dup
+ @vfr_threshold = options[:vfr_frame_rate_threshold]
end
def make
when 'mp4'
@output_options['acodec'] = 'aac'
@output_options['strict'] = 'experimental'
+
+ if high_vfr?(metadata) && !eligible_to_passthrough?(metadata)
+ @output_options['vsync'] = 'vfr'
+ @output_options['r'] = @vfr_threshold
+ end
end
command_arguments, interpolations = prepare_command(destination)
end
def update_options_from_metadata(metadata)
- return unless @passthrough_options && @passthrough_options[:video_codecs].include?(metadata.video_codec) && @passthrough_options[:audio_codecs].include?(metadata.audio_codec) && @passthrough_options[:colorspaces].include?(metadata.colorspace)
+ return unless eligible_to_passthrough?(metadata)
@format = @passthrough_options[:options][:format] || @format
@time = @passthrough_options[:options][:time] || @time
@convert_options = @passthrough_options[:options][:convert_options].dup
end
+ def high_vfr?(metadata)
+ @vfr_threshold && metadata.r_frame_rate && metadata.r_frame_rate > @vfr_threshold
+ end
+
+ def eligible_to_passthrough?(metadata)
+ @passthrough_options && @passthrough_options[:video_codecs].include?(metadata.video_codec) && @passthrough_options[:audio_codecs].include?(metadata.audio_codec) && @passthrough_options[:colorspaces].include?(metadata.colorspace)
+ end
+
def update_attachment_type(metadata)
@attachment.instance.type = MediaAttachment.types[:gifv] unless metadata.audio_codec
end