Leon's Blogging

Coding blogging for hackers.

用 Carrierwave + FFMPEG 影片轉檔 (Mediainfo檔案資訊)

| Comments

若是上傳的檔案是影片,並且要對影片做其他處理,就可以使用 FFMPRG 來處理。

電腦先安裝ffmpeg

1
brew install ffmpeg

Gem

1
2
gem 'carrierwave'
gem 'streamio-ffmpeg'

設定

application.rb

1
require 'carrierwave'

lib/carrierwave/ffmpeg.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
require 'streamio-ffmpeg'
module CarrierWave
  module FFMPEG
    module ClassMethods
      def resample(bitrate)
        process :resample => bitrate
      end
    end

    def resample(bitrate)
      directory = File.dirname(current_path)
      tmpfile = File.join(directory, "tmpfile")

      FileUtils.mv( current_path, tmpfile )

      file = ::FFMPEG::Movie.new(tmpfile)
      file.transcode(current_path, video_bitrate: bitrate)

      File.delete(tmpfile)
    end
  end
end

app/uploaders/video_uploader.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
require File.join(Rails.root, "lib", "carrierwave", "ffmpeg")

class VideoUploader < CarrierWave::Uploader::Base
  include CarrierWave::FFMPEG

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def extension_white_list
    %w(mp4 flv)
  end

  version :bitrate_800k do
    process :resample => "800k"
  end

  version :bitrate_500k, from_version: :bitrate_800k do
    process :resample => "500k"
  end

end

FFMPEG

也可以用 ruby 直接下 ffmpef 的指令

1
ffmpeg -y -i #{input_path} -vf "scale=ceil(oh*a):480" -vcodec libx264 -preset:v slow -pix_fmt yuv420p -profile:v baseline -level 3.0 -b #{bitrate} -r 29.97 -acodec libvo_aacenc -ac 2 -ar 44100 -ab 64k -movflags faststart #{output_path}

縮圖

1
ffmpeg -i #{input} -ss 00:00:05 -vframes 1 #{thumbnil}

Mediainfo

mediainfo 也是可以用來知道檔案的資訊,也蠻好用的

1
`mediainfo '--Inform=Video;%Width%' #{input}`

看有什麼參數可用

1
mediainfo --Info-Parameters

Calling shell commands from Ruby

  1. Kernel#`, commonly called backticks – cmd

Returns the result of the shell command.

1
2
value = `echo 'hi'`
value = `#{cmd}`
  1. Built-in syntax, %x( cmd )

Returns the result of the shell command, just like the backticks.

1
2
value = %x( echo 'hi' )
value = %x[ #{cmd} ]
  1. Kernel# system

Return: true if the command was found and ran successfully, false otherwise

1
2
wasGood = system( "echo 'hi'" )
wasGood = system( cmd )
  1. Kernel#exec

Return: none, the current process is replaced and never continues

1
2
exec( "echo 'hi'" )
exec( cmd ) # Note: this will never be reached because of the line above

官方文件:
carrierwave
streamio-ffmpeg
FFMPEG
Kernel

參考文件:
Create FFMPEG processor for Carrierwave in Rails 3
CarrierWave - basic video conversion
Running command line commands within Ruby script
Calling shell commands from Ruby
6 Ways to Run Shell Commands in Ruby Tuesday

Comments