如何在Rails应用中构建含FFmpeg操作的表单?求实现示例
First off, yes—you absolutely can create a Rails form that lets authorized users trigger FFmpeg-based video edits like adding reverb to audio or overlaying audio tracks. Let’s walk through this with practical, actionable examples, since documentation can be sparse for this specific use case.
Step 1: Set Up Dependencies
First, make sure FFmpeg is installed on your server/local machine (verify with ffmpeg -v). Then add the streamio-ffmpeg gem to your Gemfile—it’s a Ruby wrapper that simplifies calling FFmpeg commands:
# Gemfile gem 'streamio-ffmpeg'
Run bundle install to install it. We’ll assume you’re using Active Storage for handling user-uploaded videos (Rails’ built-in file system, but you can adapt this to CarrierWave or Paperclip too).
Step 2: Create a Video Processing Form
We’ll build a form with radio buttons for different FFmpeg operations. Let’s assume you have a Video model with an active_storage_attached :file attachment.
First, add columns to track processing state and selected action:
rails generate migration AddProcessingFieldsToVideos processing_status:string processing_option:string rails db:migrate
Now build the form in your view (e.g., app/views/videos/edit.html.erb):
<% if current_user.admin? || current_user == @video.user %> <%= form_with model: @video do |form| %> <h3>Select Video Processing Action</h3> <%= form.radio_button :processing_option, "add_reverb" %> <%= form.label :processing_option_add_reverb, "Add Reverb to Audio" %> <%= form.radio_button :processing_option, "overlay_audio" %> <%= form.label :processing_option_overlay_audio, "Overlay Background Audio" %> <%= form.submit "Start Processing", class: "btn btn-primary" %> <% end %> <% end %>
Replace the permission check with your actual logic (e.g., admin access or video ownership).
Step 3: Handle Form Submission in the Controller
Video processing is slow, so we’ll use Active Job to run it in the background. First, generate a job:
rails generate job VideoProcessingJob
Update the VideosController to trigger the job on form submission:
# app/controllers/videos_controller.rb def update @video = Video.find(params[:id]) # Add permission check here if not using the view check # redirect_to @video, alert: "No permission" unless current_user.authorized? if @video.update(video_params) @video.update(processing_status: "processing") VideoProcessingJob.perform_later(@video) redirect_to @video, notice: "Video processing started—we’ll notify you when it’s done!" else render :edit end end private def video_params params.require(:video).permit(:processing_option) end
Step 4: Implement FFmpeg Logic in the Job
Add the actual FFmpeg commands to the job—this is where you define how each edit works:
# app/jobs/video_processing_job.rb class VideoProcessingJob < ApplicationJob queue_as :default def perform(video) input_path = video.file.service.path_for(video.file.key) output_path = "#{Rails.root}/tmp/processed_#{video.id}.mp4" begin case video.processing_option when "add_reverb" # FFmpeg command to add reverb (adjust parameters for your desired effect) ffmpeg_command = "ffmpeg -i #{input_path} -filter_complex \"afftdn=nf=-20:tn=-20,aecho=0.8:0.9:1000:0.3\" #{output_path}" system(ffmpeg_command) when "overlay_audio" # Use a pre-stored background audio file (or let users upload their own) background_audio_path = "#{Rails.root}/app/assets/audio/background.mp3" ffmpeg_command = "ffmpeg -i #{input_path} -i #{background_audio_path} -filter_complex \"[1:a]volume=0.3[a1];[0:a][a1]amix=inputs=2:duration=shortest\" -c:v copy #{output_path}" system(ffmpeg_command) end # Replace original video with processed version video.file.attach(io: File.open(output_path), filename: "processed_#{video.file.filename}", content_type: "video/mp4") video.update(processing_status: "completed") rescue StandardError => e video.update(processing_status: "failed", error_message: e.message) ensure # Clean up temporary file File.delete(output_path) if File.exist?(output_path) end end end
Tweak the FFmpeg filter parameters (like aecho or volume) to get your desired effect—FFmpeg has a huge library of filters to explore.
Step 5: Show Processing Status to Users
Add status feedback in your video show view:
# app/views/videos/show.html.erb <% case @video.processing_status %> <% when "processing" %> <p class="text-info">Video is being processed—please wait.</p> <% when "completed" %> <p class="text-success">Video processing done!</p> <%= video_tag @video.file %> <% when "failed" %> <p class="text-danger">Processing failed: <%= @video.error_message %></p> <% end %>
That’s the core setup! You can expand this with more options (trimming, subtitles, etc.) by adding more radio buttons and corresponding FFmpeg commands in the job.
内容的提问来源于stack exchange,提问作者Yozuu

