Search code examples
ruby-on-railsangularjspaperclippaperclip-validation

Paperclip for both images and Videos


In my app I already have paperclip for upload images, but requirement changed in order to accept both images and videos. The images are already defined in a model with a belongs_to relationship, called Attachment. Since the video will also be an attachment of the same parent model (in my case, articles) I wanted to reuse the same Attachment model for images & videos. Is this a good idea?

The code of my attachment.rb is:

class Attachment < ActiveRecord::Base

  belongs_to :article 

  has_attached_file :url, :s3_protocol => :https , 
    styles: { 
      medium: "300x300>", thumb: "100x100>", big: "1200x1200>", normal: "600x600>" 
    }

  validates_attachment_content_type :url, content_type: /\Aimage|\Avideo\/.*\Z/

  validates_attachment :url, content_type: { content_type: ["image/jpeg", "image/gif", "image/png", "video/mp4"] }

end

But as it is, it's not storing videos on the S3. I get the following in the terminal

Command :: file -b --mime '/var/folders/v_/pf2bsxnj1y37ccd2pjksv7z80000gn/T/f3e2afc957bb9fb2aa3e77e69359c48920160131-13311-pyeez1.mp4'
Command :: identify -format '%wx%h,%[exif:orientation]' '/var/folders/v_/pf2bsxnj1y37ccd2pjksv7z80000gn/T/8dc7385648e2164764b72fda6fd9099a20160131-13311-1l40ccn.mp4[0]' 2>/dev/null
[paperclip] An error was received while processing: #<Paperclip::Errors::NotIdentifiedByImageMagickError: Paperclip::Errors::NotIdentifiedByImageMagickError>
Command :: identify -format '%wx%h,%[exif:orientation]' '/var/folders/v_/pf2bsxnj1y37ccd2pjksv7z80000gn/T/8dc7385648e2164764b72fda6fd9099a20160131-13311-1l40ccn.mp4[0]' 2>/dev/null
[paperclip] An error was received while processing: #<Paperclip::Errors::NotIdentifiedByImageMagickError: Paperclip::Errors::NotIdentifiedByImageMagickError>
Command :: identify -format '%wx%h,%[exif:orientation]' '/var/folders/v_/pf2bsxnj1y37ccd2pjksv7z80000gn/T/8dc7385648e2164764b72fda6fd9099a20160131-13311-1l40ccn.mp4[0]' 2>/dev/null
[paperclip] An error was received while processing: #<Paperclip::Errors::NotIdentifiedByImageMagickError: Paperclip::Errors::NotIdentifiedByImageMagickError>
Command :: identify -format '%wx%h,%[exif:orientation]' '/var/folders/v_/pf2bsxnj1y37ccd2pjksv7z80000gn/T/8dc7385648e2164764b72fda6fd9099a20160131-13311-1l40ccn.mp4[0]' 2>/dev/null
[paperclip] An error was received while processing: #<Paperclip::Errors::NotIdentifiedByImageMagickError: Paperclip::Errors::NotIdentifiedByImageMagickError>
Command :: file -b --mime '/var/folders/v_/pf2bsxnj1y37ccd2pjksv7z80000gn/T/f3e2afc957bb9fb2aa3e77e69359c48920160131-13311-kvb5nr.mp4'

The second question is since I'm using AngularJS for the frontend, can I just take advantage of HTML <video> tag to render the video to the user?


Solution

  • Looks like the issue is that ImageMagick is trying to transcode the video, which it cannot.

    The way to handle transcoding of videos within Paperclip is to use the paperclip-av-transcoder gem (formerly paperclip-ffmpeg). I only have experience with the latter:

    #app/models/attachment.rb
    class Attachment < ActiveRecord::Base
        has_attached_file :url, :s3_protocol => :https , 
           styles:  lambda { |a| a.instance.is_image? ?  medium: "300x300>", thumb: "100x100>", big: "1200x1200>", normal: "600x600>" } : {:thumb => { :geometry => "100x100#", :format => 'jpg', :time => 10}, :medium => { :geometry => "300x300#", :format => 'jpg', :time => 10}}}, processors: [:transcoder]
    
        validates_attachment :url,
            content_type: ['video/mp4'],
            message:      "Sorry, right now we only support MP4 video",
            if:           :is_video?
    
        validates_attachment :url,
            content_type: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif'],
            message:      "Different error message",
            if:           :is_image?
    
      private
    
      def is_video?
        url.instance.attachment_content_type =~ %r(video)
      end
    
      def is_image?
        url.instance.attachment_content_type =~ %r(image)
      end
    end
    

    Our old code & ref