class VideoTranscoder require 'streamio-ffmpeg' def initialize @ffmpeg_path = ENV['FFMPEG_PATH'] || 'ffmpeg' @ffprobe_path = ENV['FFPROBE_PATH'] || 'ffprobe' end def transcode_for_web(input_path:, output_path:, on_progress: nil) movie = FFMPEG::Movie.new(input_path) # Calculate progress callback progress_callback = ->(progress) { on_progress&.call(progress, 100) } # Transcoding options for web compatibility options = { video_codec: 'libx264', audio_codec: 'aac', custom: [ '-pix_fmt yuv420p', '-preset medium', '-crf 23', '-movflags +faststart', '-tune fastdecode' ] } movie.transcode(output_path, options, &progress_callback) output_path end def extract_frame(input_path, seconds) movie = FFMPEG::Movie.new(input_path) output_path = "#{Rails.root}/tmp/thumbnail_#{SecureRandom.hex(8)}.jpg" movie.screenshot(output_path, seek_time: seconds, resolution: '320x240') output_path end def extract_metadata(input_path) movie = FFMPEG::Movie.new(input_path) { width: movie.width, height: movie.height, duration: movie.duration, video_codec: movie.video_codec, audio_codec: movie.audio_codec, bit_rate: movie.bitrate, frame_rate: movie.frame_rate, format: movie.container } end def web_compatible?(input_path) movie = FFMPEG::Movie.new(input_path) # Check if video is already web-compatible return false unless movie.valid? # Common web-compatible formats web_formats = %w[mp4 webm] web_video_codecs = %w[h264 av1 vp9] web_audio_codecs = %w[aac opus] format_compatible = web_formats.include?(movie.container.downcase) video_compatible = web_video_codecs.include?(movie.video_codec&.downcase) audio_compatible = movie.audio_codec.blank? || web_audio_codecs.include?(movie.audio_codec&.downcase) format_compatible && video_compatible && audio_compatible end end