Rails 7.1 ActiveStorage's TransformJob cleverly pre-processes videos and PDFs for smooth previews

railsDecember 20, 2023Dotby Alkesh Ghorpade

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.

Closing Remark

Could your team use some help with topics like this and others covered by ShakaCode's blog and open source? We specialize in optimizing Rails applications, especially those with advanced JavaScript frontends, like React. We can also help you optimize your CI processes with lower costs and faster, more reliable tests. Scraping web data and lowering infrastructure costs are two other areas of specialization. Feel free to reach out to ShakaCode's CEO, Justin Gordon, at justin@shakacode.com or schedule an appointment to discuss how ShakaCode can help your project!
Are you looking for a software development partner who can
develop modern, high-performance web apps and sites?
See what we've doneArrow right