2015年6月21日日曜日

Wii Uに動画を表示させようと四苦八苦した件

Wii Uは自分で持ってるMP4動画とか画像とかをSDカードやらDVDやらDLNA使って読み込むことが
でき
ない。
私が思うにWiiU用アプリやらWebアプリやらがもっと作られるといいな~と想定されていたのだと思うがそうはならなかったようだ。
開発ライセンス必要だしね。
というわけで、Railsで単純な動画アップローダーを作った。
例によってソースのみ。
herokuにもデプロイしてあるんだけど個人用みたいな扱いにしたいからBasic認証掛けてある。アップロードしたかった方は申し訳ない。
Githubからソース落として自力でデプロイしてくれたまえ。
後学の為に苦労した点とかまとめます。
  1. BASIC認証
    これは思ったより簡単だった。ApplicationControllerにちょっと書き加えるだけ。
    class ApplicationController < ActionController::Base
      # Prevent CSRF attacks by raising an exception.
      # For APIs, you may want to use :null_session instead.
      protect_from_forgery with: :exception
      before_filter :basic
      private
      def basic
        upass = ENV["USER_PASS"]
        u = upass.split(":")[0]
        p = upass.split(":")[1]
    
        authenticate_or_request_with_http_basic do |user, pass|
          user == u && pass == p
        end
      end
    end
    環境変数はめんどいからコロン区切りにしてある。
  2. ファイル暗号化
    アップロードしたファイルは暗号化してDBへぶち込むようにしてある。
    Herokuの規約上、暗号化したほうが安全だと判断しました。
    これもmodelにちょっと書き足すだけ。
class Video < ActiveRecord::Base
  def encryptor
    secret = ENV["ENC_KEY"]
    ::ActiveSupport::MessageEncryptor.new(secret)
  end

  def video_data=(val)
    encryptor = self.encryptor
    write_attribute("video_data",encryptor.encrypt_and_sign(val))
  end

  def video_data
    encryptor = self.encryptor
    encryptor.decrypt_and_verify(read_attribute("video_data"))
  end
end
3 . DBへのぶち込み方
最初はテーブルにbinary列を追加してそこにぶち込もうとしたが、全件検索した際にメモリいっぱいになって落ちることが判明。
各列遅延評価してると思ってたけど、そうではないらしい。
結局テーブル分割したから保存部分がめんどくさくなった。
     @user = User.new(user_params)
     @user.filename = file.original_filename
     video = Video.create
     video.video_data = file.read
     video.save
     @user.video_id = video.id
     @user.icon_content_type = file.content_type
     @user.save
4. 動画再生
最初はsend_dataでRailsからデータ送ってたんだけど、それだとvideoタグでの再生がうまくいかんかった。なんでや。GifとかJpegならうまくいったのに…
結局、publicフォルダ以下に直接出力し、後で消すと言う方法をとった。
Dyno死ぬときにpublicフォルダ以下内容も死ぬけど一応トップに戻る際にも消してる。
 def show
    #ファイル出力
    @user = User.find(params[:id])
    File.binwrite(Rails.public_path.join(@user.icon_path), Video.find(@user.video_id).video_data)
  end
MP4への変換とかはHandbrakeなりなんなりでローカルでエンコードしていたから問題なかった。
あと、WebM形式も試したけどうまくいかんかった。
Wii Uで再生可能な動画形式は以下。こうして仕様を公開してくれているのは助かる。
これでそことなく動画をアップロードして再生できるようになったがまだ課題が山積み。
課題はGithubのissueを参照してください(宣伝)

ちなみに今回の投稿はKobitoで書いてからはっつけました。
Windows版Kobito優秀。