Files
redux-scraper/app/lib/loaded_media.rb
2025-08-20 15:00:54 +00:00

67 lines
1.6 KiB
Ruby

# typed: strict
# frozen_string_literal: true
class LoadedMedia
extend T::Sig
extend T::Helpers
abstract!
class FileNotFound < StandardError
end
sig do
params(content_type: String, media_path: String).returns(
T.nilable(LoadedMedia),
)
end
def self.from_file(content_type, media_path)
case content_type
when %r{image/gif}
VipsUtil.try_load_gif(
media_path,
load_gif: -> { LoadedMedia::Gif.new(media_path) },
on_load_failed: ->(detected_content_type) do
return from_file(detected_content_type, media_path)
end,
)
when %r{image/jpeg}, %r{image/jpg}, %r{image/png}, %r{image/bmp}
LoadedMedia::StaticImage.new(media_path)
when %r{video/webm}, %r{video/mp4}
LoadedMedia::WebmOrMp4.new(media_path)
else
return nil
end
end
sig { abstract.returns(Integer) }
def num_frames
end
sig do
abstract
.params(frame: Integer, path: String, options: ThumbnailOptions)
.void
end
def write_frame_thumbnail(frame, path, options)
end
protected
sig(:final) do
params(image: Vips::Image, path: String, options: ThumbnailOptions).void
end
def write_image_thumbnail(image, path, options)
FileUtils.mkdir_p(File.dirname(path))
tmp_path =
File.join(BlobFile::TMP_DIR, "thumbnail-#{SecureRandom.uuid}.jpg")
image.thumbnail_image(
options.width,
height: options.height,
size: options.size,
).jpegsave(tmp_path, interlace: options.interlace, Q: options.quality)
FileUtils.mv(tmp_path, path)
ensure
File.delete(tmp_path) if tmp_path && File.exist?(tmp_path)
end
end