You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails ActiveStorage文件处理:仅即时处理还是支持上传时?视频压缩咨询

ActiveStorage for Video Upload & Compression in Rails 5.2: A Practical Guide

Hey there! Great question—ActiveStorage absolutely works for video uploads and compression, it just doesn’t have this feature built right into the core. Let me walk you through how to set this up, since it’s similar to the Shrine+ffmpeg workflow you’re already familiar with.

Key Background

ActiveStorage handles file storage, model associations, and basic preview generation out of the box, but video compression (a resource-heavy task) needs to be handled separately with background jobs and ffmpeg, just like you did with Shrine.

Step-by-Step Implementation

1. Set Up ActiveStorage for Video Uploads

First, make sure you’ve got ActiveStorage configured (run rails active_storage:install and migrate if you haven’t already). Then add attachments to your model—you can choose to keep both original and compressed versions, or replace the original:

# app/models/video.rb
class Video < ApplicationRecord
  has_one_attached :original_video
  has_one_attached :compressed_video # Optional: retain original for backup
end

2. Use Background Jobs for Compression

Video compression is slow—never run it during a web request. Use a background job processor like Sidekiq or Delayed Job to handle this after upload.

Here’s an example Sidekiq job that uses ffmpeg to compress the video (tweak the ffmpeg parameters to match your quality/size needs):

# app/jobs/video_compression_job.rb
class VideoCompressionJob < ApplicationJob
  queue_as :video_processing

  def perform(video)
    # Download original video from ActiveStorage to a temp file
    original_temp = Tempfile.new(["original", ".mp4"], encoding: 'ascii-8bit')
    original_temp.write(video.original_video.download)
    original_temp.close

    # Create temp file for compressed output
    compressed_temp = Tempfile.new(["compressed", ".mp4"], encoding: 'ascii-8bit')

    # Run ffmpeg compression command
    # This example uses H.264 codec with balanced quality/size (CRF 28)
    system(
      "ffmpeg -i #{original_temp.path} " \
      "-vcodec libx264 -crf 28 -preset medium " \
      "-acodec aac -b:a 128k " \
      "#{compressed_temp.path}"
    )

    # Attach compressed video to the model
    video.compressed_video.attach(
      io: File.open(compressed_temp.path),
      filename: "compressed_#{video.original_video.filename.base}.mp4",
      content_type: "video/mp4"
    )

    # Clean up temp files to avoid clutter
    original_temp.unlink
    compressed_temp.unlink
  rescue => e
    # Log or alert on failure (corrupted files/unsupported formats happen!)
    Rails.logger.error "Video compression failed for video #{video.id}: #{e.message}"
  end
end

3. Trigger the Job After Upload

Add a callback to your Video model to kick off the compression job once the original video is attached:

# app/models/video.rb
class Video < ApplicationRecord
  has_one_attached :original_video
  has_one_attached :compressed_video

  after_create_commit :trigger_compression_job

  private

  def trigger_compression_job
    VideoCompressionJob.perform_later(self) if original_video.attached?
  end
end

4. Bonus: Generate Video Previews

Since you mentioned preview generation, you can extend the job to create a thumbnail at the same time using ffmpeg:

# Inside VideoCompressionJob#perform, after compression logic
# Generate a thumbnail from the 1st second of the video
thumbnail_temp = Tempfile.new(["thumbnail", ".jpg"], encoding: 'ascii-8bit')
system("ffmpeg -i #{original_temp.path} -ss 00:00:01 -vframes 1 #{thumbnail_temp.path}")

# Attach thumbnail to the model (add `has_one_attached :thumbnail` to Video first)
video.thumbnail.attach(
  io: File.open(thumbnail_temp.path),
  filename: "thumbnail_#{video.original_video.filename.base}.jpg",
  content_type: "image/jpeg"
)
thumbnail_temp.unlink

Important Notes

  • Install ffmpeg: Make sure your server has ffmpeg installed (most hosting providers support this, or install via apt-get install ffmpeg on Debian/Ubuntu).
  • Storage Choices: If you don’t need the original video, use video.original_video.purge before attaching the compressed file to save space.
  • Error Handling: Add alerts (like Slack notifications) for failed jobs—video processing can fail for corrupted files or unsupported formats.

Final Takeaway

ActiveStorage is a solid replacement for Shrine here. It handles the heavy lifting of file storage and model associations, while you can reuse your existing ffmpeg and background job knowledge to handle compression. It’s flexible and integrates seamlessly with Rails’ ecosystem.

内容的提问来源于stack exchange,提问作者R4ttlesnake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:11:21