Rails 7.1 ActiveStorage's TransformJob cleverly pre-processes videos and PDFs for smooth previews
ActiveStorage preview functionality allows you to generate thumbnails
or
preview images from non-image file formats like videos
and
PDFs.
This enhances user experience by visually representing
files beyond textual descriptions.
To create a link to a lazily-generated preview,
you need to use the attachment's preview
method:
<%= image_tag user.video.preview(resize_to_limit: [100, 100])
ActiveStorage offers built-in previewers for video and PDF files.
-
Video: The ActiveStorage::Previewer::VideoPreviewer extracts the first frame as a preview image.
-
PDF:
ActiveStorage::Previewer::PopplerPDFPreviewer
: Requires Poppler library.ActiveStorage::Previewer::MuPDFPreviewer
: Requires MuPDF library (version 1.8 or newer).
You can create custom previewers by subclassing ActiveStorage::Previewer
and
implementing specific methods.
The previews can be created on the fly
or
pre-processed.
A background job performs pre-processing,
ActiveStorage::TransformJob
,
which runs when the file is attached
or
updated.
ActiveStorage::TransformJob is a job class in Rails that handles
processing uploaded files into different variants based on defined transformations.
It inherits from the ActiveStorage::BaseJob
class
and
comes with a single public method,
perform
.
Before Rails 7.1
Upon upload,
ActiveStorage processes the image using an ActiveStorage::TransformJob
background process,
creating a pre-sized variant for better performance.
The ready-made variant is delivered instead of the original when accessing the image.
If you try to upload to video
or
PDF,
the ActiveStorage::TransformJob
throws an ActiveStorage::InvariableError
exception.
Let's use an example Post
model with attribute
featured_video
to understand the issue better.
class Post < ApplicationRecord
has_one_attached :featured_video do |attachable|
attachable.variant :thumb, resize_to_limit: [100, 100], preprocessed: true
end
end
post = Post.first
post.featured_video.attach(new_video)
=> Performed ActiveStorage::TransformJob (Job ID: 2b98093b-c124-4cbd-baa4-ab460a56fa61) from Async(default)
# error logs
Error performing ActiveStorage::TransformJob
ActiveStorage::InvariableError (ActiveStorage::InvariableError):
# ...stacktrace
After Rails 7.1
Rails 7.1 ActiveStorage's TransformJob now pre-processes videos and PDFs.
The ActiveStorage::TransformJob will no longer raise ActiveStorage::InvariableError
and
generate the previews if the attachment is previewable.
Internally,
the perform
method of ActiveStorage::TransformJob
changed the
blog.variant
function to
blog.representation
function.
The #representation
method checks if the attachment is an image.
If it is an image,
it returns a variant.
If the attachment is a video
or
PDF,
it creates a preview.
For videos,
it picks the first frame as the preview,
and for PDFs,
the first page is the preview.
Note:
Variants do not exist for videos
and
PDFs.
Because of this issue,
the ActiveStorage::TransformJob#perform
failed for videos
and
PDFs.
To know more about this feature, please refer to this PR.