自宅の日記用Railsアプリに「YouTubeのような動画投稿機能をつけて欲しい」と唯一の利用者から要望が出てきました。いつも、ご飯を作ってもらっているので頭が上がりません。仕方がないのでちょっと試してみました。

画像ファイルのアップロードでattachment_fuを使っているので、動画もそのまま乗っけてしまう手抜き大作戦です。サーバー側ではflvファイルで保管しておきたいので、アップロード後からサーバーに保存するまでの間に元の動画ファイル(mpegとか)と変換後のflvを差し替えてしまえば良いでしょう。

ということでやっつけで動かしたのが以下

  def create
    uploaded_data = params[:photo][:uploaded_data]
    if uploaded_data.content_type =~ /\Avideo\//
      converted_file = Tempfile.new('HogeVideo')
      converted_file.instance_variable_set(
        :@original_filename,
        File.basename(uploaded_data.original_filename, '.*') + '.flv'
      )
      class << converted_file
        def original_filename; @original_filename end
        def content_type; 'video/x-flv' end
      end
      converted_file.close

      pid, stdin, stdout, stderr = Open4::popen4 "sh"
      stdin.puts "ffmpeg -i #{uploaded_data.path} -f flv -y #{converted_file.path}"
      stdin.close
      ignored, status = Process::waitpid2 pid
      uploaded_data.close(true)
      raise "ffmpeg error: #{stderr.read}" unless status.exitstatus.zero?

      converted_file.open
      params[:photo][:uploaded_data] = converted_file
    end
    @photo = Photo.new(params[:photo])

    if @photo.save
         :

まず、動画のくせに堂々とPhotoクラスを使っているのが男らしいですね。仕事では一緒に組みたくない感じを醸し出しています。

「@photo = Photo.new〜」の前までがflv変換のため今回差し込んだコードです。アップロードされたファイルがTempfileっぽい気がしたので、ffmpegで変換したflvファイルもTempfileにして差し替えています。そうかと思えばoriginal_filenameとかcontent_typeとかのメソッドが無いと怒られるので、特異メソッドで適当に逃げています。

あと、attachment_fuのアップロードファイルサイズの上限値がデフォルト1Mなので、has_attachmentのオプションで変更しておかないと多分エラーになるはず。


で、上のコードでサーバーに格納した後、View側ではJW FLV Player辺りで適当に再生してあげれば良いでしょう。

とここまでやってみて、プレビュー画像を作り忘れていることに気がつきました。再生前の画面が真っ黒だ…

もう寝よう。