3

I want to use the Shrine gem to upload video files, transcode, & generate thumbnails from the video.

I am trying to convert Erik Dahlstrand's Shrine-Rails-example from photos to videos. I am having trouble creating the video uploader. I based this code on Video isn't of allowed type (allowed types: video/mp4), Shrine, Rails

require "streamio-ffmpeg"

class VideoUploader < Shrine
  ALLOWED_TYPES = %w[video/mp4 video/quicktime video/x-msvideo video/mpeg]
  plugin :processing
  plugin :versions

  plugin :determine_mime_type
  plugin :cached_attachment_data
  plugin :remove_attachment
  plugin :add_metadata
  plugin :validation_helpers
  plugin :derivation_endpoint, prefix: "derivations/video"

  add_metadata do |io, context|
    movie = Shrine.with_file(io) { |file| FFMPEG::Movie.new(file.path) }

    { "duration"   => movie.duration,
      "bitrate"    => movie.bitrate,
      "resolution" => movie.resolution,
      "frame_rate" => movie.frame_rate }
  end

  movie.screenshot("video_thumb_007.jpg", seek_time: 5, resolution: '320x240')

  metadata_method :duration

  Attacher.validate do
    validate_max_size 100.megabyte, message: "is too large (max is 100 MB)"
    validate_mime_type_inclusion ALLOWED_TYPES
  end
end

I get this error:

/var/folders/mm/_j8x4k2176jcv31zvbc497_c0000gp
    /T/shrine20190607-24438-4f3jz2.m4v: No such file or directory

and in fact, there is no file in that location. So where is the file stored while waiting for upload??

Also, using the demo to upload photos to AWS (production env), the objects are stored in the bucket in a folder called 'photos'. Shrine uses the table name to name the folder apparently. Is possible to create alternative & nested folder names?

Thank you - seems like an amazing gem! Trying to understand it better!

Thx

1 Answers1

2

Further delving into the documentation, I was able to solve this problem with only one remaining question - is it possible to control which folders in the AWS bucket the original and thumbs are uploaded to? Thx

Solution:

require "streamio-ffmpeg"
require "tempfile"

class VideoUploader < ImageUploader
  plugin :add_metadata
  plugin :validation_helpers
  plugin :processing
  plugin :versions
  plugin :delete_raw

  add_metadata do |io, context|
    movie = Shrine.with_file(io) { |file| FFMPEG::Movie.new(file.path) }
    { "duration"   => movie.duration,
      "bitrate"    => movie.bitrate,
      "resolution" => movie.resolution,
      "frame_rate" => movie.frame_rate
    }

  end

  process(:store) do |io, context|
    versions = {original: io}

    io.download do |original|
      screenshot1 = Tempfile.new(["screenshot1", ".jpg"], binmode: true)
      screenshot2 = Tempfile.new(["screenshot2", ".jpg"], binmode: true)
      screenshot3 = Tempfile.new(["screenshot3", ".jpg"], binmode: true)
      screenshot4 = Tempfile.new(["screenshot4", ".jpg"], binmode: true)

      movie = FFMPEG::Movie.new(original.path)
      movie.screenshot(screenshot1.path, seek_time: 5, resolution: '640x480')
      movie.screenshot(screenshot2.path, seek_time: 10, resolution: '640x480')
      movie.screenshot(screenshot3.path, seek_time: 15, resolution: '640x480')
      movie.screenshot(screenshot4.path, seek_time: 20, resolution: '640x480')

      [screenshot1, screenshot2, screenshot3, screenshot4].each(&:open) # refresh file descriptors

      versions.merge!(screenshot1: screenshot1, screenshot2: screenshot2, screenshot3: screenshot3, screenshot4: screenshot4)
    end

    versions
  end

  Attacher.validate do
    validate_max_size 100.megabyte, message: "is too large (max is 100 MB)"
    validate_mime_type_inclusion ALLOWED_TYPES
  end
end