| 
									
										
										
										
											2016-11-15 16:56:29 +01:00
										 |  |  | # frozen_string_literal: true | 
					
						
							| 
									
										
										
										
											2017-05-02 09:14:47 +09:00
										 |  |  | # == Schema Information | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Table name: media_attachments | 
					
						
							|  |  |  | # | 
					
						
							| 
									
										
										
										
											2019-01-05 12:43:28 +01:00
										 |  |  | #  id                  :bigint(8)        not null, primary key | 
					
						
							|  |  |  | #  status_id           :bigint(8) | 
					
						
							|  |  |  | #  file_file_name      :string | 
					
						
							|  |  |  | #  file_content_type   :string | 
					
						
							|  |  |  | #  file_file_size      :integer | 
					
						
							|  |  |  | #  file_updated_at     :datetime | 
					
						
							|  |  |  | #  remote_url          :string           default(""), not null | 
					
						
							|  |  |  | #  created_at          :datetime         not null | 
					
						
							|  |  |  | #  updated_at          :datetime         not null | 
					
						
							|  |  |  | #  shortcode           :string | 
					
						
							|  |  |  | #  type                :integer          default("image"), not null | 
					
						
							|  |  |  | #  file_meta           :json | 
					
						
							|  |  |  | #  account_id          :bigint(8) | 
					
						
							|  |  |  | #  description         :text | 
					
						
							|  |  |  | #  scheduled_status_id :bigint(8) | 
					
						
							| 
									
										
										
										
											2019-04-27 03:24:09 +02:00
										 |  |  | #  blurhash            :string | 
					
						
							| 
									
										
										
										
											2017-05-02 09:14:47 +09:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2016-11-15 16:56:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-05 17:46:36 +02:00
										 |  |  | class MediaAttachment < ApplicationRecord | 
					
						
							| 
									
										
										
										
											2017-03-04 22:17:10 +01:00
										 |  |  |   self.inheritance_column = nil | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |   enum type: [:image, :gifv, :video, :unknown, :audio] | 
					
						
							| 
									
										
										
										
											2017-03-04 22:17:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-02 20:25:04 +09:00
										 |  |  |   IMAGE_FILE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.webp'].freeze | 
					
						
							| 
									
										
										
										
											2018-07-30 19:33:05 +02:00
										 |  |  |   VIDEO_FILE_EXTENSIONS = ['.webm', '.mp4', '.m4v', '.mov'].freeze | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |   AUDIO_FILE_EXTENSIONS = ['.ogg', '.oga', '.mp3', '.wav', '.flac', '.opus'].freeze | 
					
						
							| 
									
										
										
										
											2017-09-21 02:07:23 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-02 20:25:04 +09:00
										 |  |  |   IMAGE_MIME_TYPES             = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze | 
					
						
							| 
									
										
										
										
											2019-06-22 16:54:06 +02:00
										 |  |  |   VIDEO_MIME_TYPES             = ['video/webm', 'video/mp4', 'video/quicktime', 'video/ogg'].freeze | 
					
						
							| 
									
										
										
										
											2018-07-30 19:33:05 +02:00
										 |  |  |   VIDEO_CONVERTIBLE_MIME_TYPES = ['video/webm', 'video/quicktime'].freeze | 
					
						
							| 
									
										
										
										
											2019-06-22 16:54:06 +02:00
										 |  |  |   AUDIO_MIME_TYPES             = ['audio/wave', 'audio/wav', 'audio/x-wav', 'audio/x-pn-wave', 'audio/ogg', 'audio/mpeg', 'audio/mp3', 'audio/webm', 'audio/flac'].freeze | 
					
						
							| 
									
										
										
										
											2016-09-12 18:22:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-27 03:24:09 +02:00
										 |  |  |   BLURHASH_OPTIONS = { | 
					
						
							|  |  |  |     x_comp: 4, | 
					
						
							|  |  |  |     y_comp: 4, | 
					
						
							|  |  |  |   }.freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 03:40:12 +01:00
										 |  |  |   IMAGE_STYLES = { | 
					
						
							|  |  |  |     original: { | 
					
						
							| 
									
										
										
										
											2018-07-28 03:33:00 +02:00
										 |  |  |       pixels: 1_638_400, # 1280x1280px | 
					
						
							| 
									
										
										
										
											2018-02-21 03:40:12 +01:00
										 |  |  |       file_geometry_parser: FastGeometryParser, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     small: { | 
					
						
							| 
									
										
										
										
											2018-07-28 03:33:00 +02:00
										 |  |  |       pixels: 160_000, # 400x400px | 
					
						
							| 
									
										
										
										
											2018-02-21 03:40:12 +01:00
										 |  |  |       file_geometry_parser: FastGeometryParser, | 
					
						
							| 
									
										
										
										
											2019-04-27 03:24:09 +02:00
										 |  |  |       blurhash: BLURHASH_OPTIONS, | 
					
						
							| 
									
										
										
										
											2018-02-21 03:40:12 +01:00
										 |  |  |     }, | 
					
						
							|  |  |  |   }.freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-04 22:17:10 +01:00
										 |  |  |   VIDEO_STYLES = { | 
					
						
							|  |  |  |     small: { | 
					
						
							|  |  |  |       convert_options: { | 
					
						
							|  |  |  |         output: { | 
					
						
							|  |  |  |           vf: 'scale=\'min(400\, iw):min(400\, ih)\':force_original_aspect_ratio=decrease', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       format: 'png', | 
					
						
							|  |  |  |       time: 0, | 
					
						
							| 
									
										
										
										
											2019-04-27 03:24:09 +02:00
										 |  |  |       file_geometry_parser: FastGeometryParser, | 
					
						
							|  |  |  |       blurhash: BLURHASH_OPTIONS, | 
					
						
							| 
									
										
										
										
											2017-03-04 22:17:10 +01:00
										 |  |  |     }, | 
					
						
							|  |  |  |   }.freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |   AUDIO_STYLES = { | 
					
						
							|  |  |  |     original: { | 
					
						
							| 
									
										
										
										
											2019-06-21 22:59:44 +02:00
										 |  |  |       format: 'mp3', | 
					
						
							|  |  |  |       content_type: 'audio/mpeg', | 
					
						
							|  |  |  |       convert_options: { | 
					
						
							|  |  |  |         output: { | 
					
						
							|  |  |  |           'q:a' => 2, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |     }, | 
					
						
							|  |  |  |   }.freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-30 19:33:05 +02:00
										 |  |  |   VIDEO_FORMAT = { | 
					
						
							|  |  |  |     format: 'mp4', | 
					
						
							| 
									
										
										
										
											2019-06-20 10:52:36 +02:00
										 |  |  |     content_type: 'video/mp4', | 
					
						
							| 
									
										
										
										
											2018-07-30 19:33:05 +02:00
										 |  |  |     convert_options: { | 
					
						
							|  |  |  |       output: { | 
					
						
							| 
									
										
										
										
											2018-11-27 11:19:12 +00:00
										 |  |  |         'loglevel' => 'fatal', | 
					
						
							| 
									
										
										
										
											2018-07-30 19:33:05 +02:00
										 |  |  |         'movflags' => 'faststart', | 
					
						
							|  |  |  |         'pix_fmt'  => 'yuv420p', | 
					
						
							|  |  |  |         'vf'       => 'scale=\'trunc(iw/2)*2:trunc(ih/2)*2\'', | 
					
						
							|  |  |  |         'vsync'    => 'cfr', | 
					
						
							|  |  |  |         'c:v'      => 'h264', | 
					
						
							|  |  |  |         'b:v'      => '500K', | 
					
						
							|  |  |  |         'maxrate'  => '1300K', | 
					
						
							|  |  |  |         'bufsize'  => '1300K', | 
					
						
							|  |  |  |         'crf'      => 18, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }.freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |   VIDEO_CONVERTED_STYLES = { | 
					
						
							|  |  |  |     small: VIDEO_STYLES[:small], | 
					
						
							|  |  |  |     original: VIDEO_FORMAT, | 
					
						
							|  |  |  |   }.freeze | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-30 19:33:05 +02:00
										 |  |  |   IMAGE_LIMIT = 8.megabytes | 
					
						
							|  |  |  |   VIDEO_LIMIT = 40.megabytes | 
					
						
							| 
									
										
										
										
											2018-03-26 21:02:10 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-05 12:43:28 +01:00
										 |  |  |   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 | 
					
						
							| 
									
										
										
										
											2016-09-05 17:46:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-08 15:15:43 +02:00
										 |  |  |   has_attached_file :file, | 
					
						
							| 
									
										
										
										
											2017-03-04 22:17:10 +01:00
										 |  |  |                     styles: ->(f) { file_styles f }, | 
					
						
							|  |  |  |                     processors: ->(f) { file_processors f }, | 
					
						
							| 
									
										
										
										
											2016-12-07 12:09:20 +01:00
										 |  |  |                     convert_options: { all: '-quality 90 -strip' } | 
					
						
							| 
									
										
										
										
											2017-05-18 22:43:10 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |   validates_attachment_content_type :file, content_type: IMAGE_MIME_TYPES + VIDEO_MIME_TYPES + AUDIO_MIME_TYPES | 
					
						
							|  |  |  |   validates_attachment_size :file, less_than: IMAGE_LIMIT, unless: :larger_media_format? | 
					
						
							|  |  |  |   validates_attachment_size :file, less_than: VIDEO_LIMIT, if: :larger_media_format? | 
					
						
							| 
									
										
										
										
											2018-07-30 19:33:05 +02:00
										 |  |  |   remotable_attachment :file, VIDEO_LIMIT | 
					
						
							| 
									
										
										
										
											2016-09-05 17:46:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-23 09:16:38 +02:00
										 |  |  |   include Attachmentable | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-05 17:46:36 +02:00
										 |  |  |   validates :account, presence: true | 
					
						
							| 
									
										
										
										
											2017-09-29 02:30:00 +02:00
										 |  |  |   validates :description, length: { maximum: 420 }, if: :local? | 
					
						
							| 
									
										
										
										
											2016-09-05 17:46:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-05 12:43:28 +01:00
										 |  |  |   scope :attached,   -> { where.not(status_id: nil).or(where.not(scheduled_status_id: nil)) } | 
					
						
							|  |  |  |   scope :unattached, -> { where(status_id: nil, scheduled_status_id: nil) } | 
					
						
							| 
									
										
										
										
											2017-09-16 03:01:45 +02:00
										 |  |  |   scope :local,      -> { where(remote_url: '') } | 
					
						
							|  |  |  |   scope :remote,     -> { where.not(remote_url: '') } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-16 10:35:17 +09:00
										 |  |  |   default_scope { order(id: :asc) } | 
					
						
							| 
									
										
										
										
											2016-11-28 13:49:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-05 17:46:36 +02:00
										 |  |  |   def local? | 
					
						
							| 
									
										
										
										
											2016-09-29 21:28:21 +02:00
										 |  |  |     remote_url.blank? | 
					
						
							| 
									
										
										
										
											2016-09-05 17:46:36 +02:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-09-05 18:39:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-16 03:01:45 +02:00
										 |  |  |   def needs_redownload? | 
					
						
							|  |  |  |     file.blank? && remote_url.present? | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |   def larger_media_format? | 
					
						
							|  |  |  |     video? || gifv? || audio? | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def audio_or_video? | 
					
						
							|  |  |  |     audio? || video? | 
					
						
							| 
									
										
										
										
											2019-02-04 12:46:05 +09:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-06 00:21:12 +01:00
										 |  |  |   def to_param | 
					
						
							|  |  |  |     shortcode | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-22 00:35:46 +01:00
										 |  |  |   def focus=(point) | 
					
						
							|  |  |  |     return if point.blank? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     x, y = (point.is_a?(Enumerable) ? point : point.split(',')).map(&:to_f) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     meta = file.instance_read(:meta) || {} | 
					
						
							|  |  |  |     meta['focus'] = { 'x' => x, 'y' => y } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     file.instance_write(:meta, meta) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def focus | 
					
						
							|  |  |  |     x = file.meta['focus']['x'] | 
					
						
							|  |  |  |     y = file.meta['focus']['y'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     "#{x},#{y}" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-28 06:42:34 +01:00
										 |  |  |   after_commit :reset_parent_cache, on: :update | 
					
						
							| 
									
										
										
										
											2017-09-28 15:31:31 +02:00
										 |  |  |   before_create :prepare_description, unless: :local? | 
					
						
							| 
									
										
										
										
											2017-01-06 00:21:12 +01:00
										 |  |  |   before_create :set_shortcode | 
					
						
							| 
									
										
										
										
											2017-04-18 23:15:44 +02:00
										 |  |  |   before_post_process :set_type_and_extension | 
					
						
							| 
									
										
										
										
											2017-04-26 09:48:12 +08:00
										 |  |  |   before_save :set_meta | 
					
						
							| 
									
										
										
										
											2017-01-06 00:21:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 11:56:04 +02:00
										 |  |  |   class << self | 
					
						
							| 
									
										
										
										
											2019-06-22 02:50:36 +02:00
										 |  |  |     def supported_mime_types | 
					
						
							|  |  |  |       IMAGE_MIME_TYPES + VIDEO_MIME_TYPES + AUDIO_MIME_TYPES | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def supported_file_extensions | 
					
						
							|  |  |  |       IMAGE_FILE_EXTENSIONS + VIDEO_FILE_EXTENSIONS + AUDIO_FILE_EXTENSIONS | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 11:56:04 +02:00
										 |  |  |     private | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def file_styles(f) | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |       if f.instance.file_content_type == 'image/gif' || VIDEO_CONVERTIBLE_MIME_TYPES.include?(f.instance.file_content_type) | 
					
						
							|  |  |  |         VIDEO_CONVERTED_STYLES | 
					
						
							|  |  |  |       elsif IMAGE_MIME_TYPES.include?(f.instance.file_content_type) | 
					
						
							| 
									
										
										
										
											2017-03-04 22:17:10 +01:00
										 |  |  |         IMAGE_STYLES | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |       elsif VIDEO_MIME_TYPES.include?(f.instance.file_content_type) | 
					
						
							| 
									
										
										
										
											2017-03-04 22:17:10 +01:00
										 |  |  |         VIDEO_STYLES | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |       else | 
					
						
							|  |  |  |         AUDIO_STYLES | 
					
						
							| 
									
										
										
										
											2017-03-04 22:17:10 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def file_processors(f) | 
					
						
							|  |  |  |       if f.file_content_type == 'image/gif' | 
					
						
							| 
									
										
										
										
											2019-04-27 03:24:09 +02:00
										 |  |  |         [:gif_transcoder, :blurhash_transcoder] | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |       elsif VIDEO_MIME_TYPES.include?(f.file_content_type) | 
					
						
							| 
									
										
										
										
											2019-06-20 10:52:36 +02:00
										 |  |  |         [:video_transcoder, :blurhash_transcoder, :type_corrector] | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |       elsif AUDIO_MIME_TYPES.include?(f.file_content_type) | 
					
						
							| 
									
										
										
										
											2019-06-20 10:52:36 +02:00
										 |  |  |         [:transcoder, :type_corrector] | 
					
						
							| 
									
										
										
										
											2017-03-04 22:17:10 +01:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2019-06-20 10:52:36 +02:00
										 |  |  |         [:lazy_thumbnail, :blurhash_transcoder, :type_corrector] | 
					
						
							| 
									
										
										
										
											2016-10-23 11:56:04 +02:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-10-08 15:15:43 +02:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2017-01-06 00:21:12 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   private | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def set_shortcode | 
					
						
							| 
									
										
										
										
											2017-04-29 00:18:32 +02:00
										 |  |  |     self.type = :unknown if file.blank? && !type_changed? | 
					
						
							| 
									
										
										
										
											2017-04-19 15:37:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-06 00:21:12 +01:00
										 |  |  |     return unless local? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     loop do | 
					
						
							|  |  |  |       self.shortcode = SecureRandom.urlsafe_base64(14) | 
					
						
							|  |  |  |       break if MediaAttachment.find_by(shortcode: shortcode).nil? | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2017-03-04 22:17:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-28 15:31:31 +02:00
										 |  |  |   def prepare_description | 
					
						
							| 
									
										
										
										
											2017-09-29 02:30:00 +02:00
										 |  |  |     self.description = description.strip[0...420] unless description.nil? | 
					
						
							| 
									
										
										
										
											2017-09-28 15:31:31 +02:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-18 23:15:44 +02:00
										 |  |  |   def set_type_and_extension | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |     self.type = begin | 
					
						
							|  |  |  |       if VIDEO_MIME_TYPES.include?(file_content_type) | 
					
						
							|  |  |  |         :video | 
					
						
							|  |  |  |       elsif AUDIO_MIME_TYPES.include?(file_content_type) | 
					
						
							|  |  |  |         :audio | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         :image | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2017-04-19 23:21:00 +02:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-26 09:48:12 +08:00
										 |  |  |   def set_meta | 
					
						
							|  |  |  |     meta = populate_meta | 
					
						
							|  |  |  |     return if meta == {} | 
					
						
							|  |  |  |     file.instance_write :meta, meta | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def populate_meta | 
					
						
							| 
									
										
										
										
											2018-02-22 00:35:46 +01:00
										 |  |  |     meta = file.instance_read(:meta) || {} | 
					
						
							| 
									
										
										
										
											2017-09-01 16:20:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-26 09:48:12 +08:00
										 |  |  |     file.queued_for_write.each do |style, file| | 
					
						
							| 
									
										
										
										
											2018-02-16 07:22:20 +01:00
										 |  |  |       meta[style] = style == :small || image? ? image_geometry(file) : video_metadata(file) | 
					
						
							| 
									
										
										
										
											2017-04-26 09:48:12 +08:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2017-09-01 16:20:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-26 09:48:12 +08:00
										 |  |  |     meta | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 07:22:20 +01:00
										 |  |  |   def image_geometry(file) | 
					
						
							| 
									
										
										
										
											2018-02-21 03:40:12 +01:00
										 |  |  |     width, height = FastImage.size(file.path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return {} if width.nil? | 
					
						
							| 
									
										
										
										
											2018-02-16 07:22:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-02-21 03:40:12 +01:00
										 |  |  |       width:  width, | 
					
						
							|  |  |  |       height: height, | 
					
						
							|  |  |  |       size: "#{width}x#{height}", | 
					
						
							|  |  |  |       aspect: width.to_f / height.to_f, | 
					
						
							| 
									
										
										
										
											2018-02-16 07:22:20 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def video_metadata(file) | 
					
						
							|  |  |  |     movie = FFMPEG::Movie.new(file.path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return {} unless movie.valid? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       width: movie.width, | 
					
						
							|  |  |  |       height: movie.height, | 
					
						
							|  |  |  |       frame_rate: movie.frame_rate, | 
					
						
							|  |  |  |       duration: movie.duration, | 
					
						
							|  |  |  |       bitrate: movie.bitrate, | 
					
						
							| 
									
										
										
										
											2019-06-19 23:42:38 +02:00
										 |  |  |     }.compact | 
					
						
							| 
									
										
										
										
											2018-02-16 07:22:20 +01:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2018-10-28 06:42:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def reset_parent_cache | 
					
						
							|  |  |  |     return if status_id.nil? | 
					
						
							|  |  |  |     Rails.cache.delete("statuses/#{status_id}") | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-09-05 17:46:36 +02:00
										 |  |  | end |