2015/07/25

予約レコード周りのその他こまごましたところ

大筋の機能は何とかイメージ通りに実装できたのですが、細かいところでも知らないがゆえに
引っかかりながらの実装となった点をまとめておく。

flashメッセージ表示

予約成功!、予約失敗などを表示するのをflashメッセージを使ってやろうとしたんだけれど、
bootstrapの場合、Rails標準のflashタイプじゃなくてbootstrap後に変換が必要なことを知らず
ちょっとはまってしまった。

通常 redirect_to うにゃうにゃ, notice: "成功!" ってやると思うんだけれど
この"notice"をbootstrap的にはclass "alert alert-success"とかに変換しないと出ない。
その辺りの記事は沢山あった。よくあるパターンとしては
notice => alert-info、alert => alert-warning、error => alert-danger とかに対応させている。
この通りやるのだが、メッセージが表示されない。もしくは無色で表示される。
違う。バックが青とか赤で囲われて欲しいのだよ。結局自分の場合、

notice => alert-success、alert => alert-danger とした。
バックカラーが、successがグリーン、dangerが赤で表示されるから。それ以外は白?だった。
それに、redirect_toのオプションで付けられるのは、notice、alert、flash => {ゴニョゴニョ} の3つ。
noticeとalertだけなら簡単だし。

予約時間の重複チェック

チューナー1つしか無いので、予約しようとした時間帯に引っかかる予約済みレコード確認をして、引っかかっしまう場合はエラーにしたいわけです。
検索としては、既存レコードの開始時間がその時間帯内である もしくは 終了時間がその時間帯内にある場合は・・・です。ということは ”OR” でつなげるわけです。
Program.where(ゴニョゴニョ)で一気に書こうとするとSQL文をなが~く書かないとならない。
嫌なので、"OR"はRubyでやることで全体コードをシンプルにした。

video_on = Program.where.not(video_id: nil)
start_on = video_on.where(start_at: (@program.start_at..@program.end_at))
end_on = video_on.where(end_at: (@program.start_at..@program.end_at))
if start_on.present? or end_on.present?
  redirect_to program_url, alert: 'Reserved violation another videos'
return
end
こんな感じ。BETWEEN生成はwhereに任せ、面倒なORはRubyで。
連続しているものは許したいので実際にはstat,endは微妙に調整する。

録画ジョブ開始タイミングは番組時間の30秒前

ActiveJobのperformが開始されて実際の録画を開始するまでには結構時間がかかる。
なのでJenkins処理でやっていた時のように、少し早めにスタートさせて sleep でタイミング調整
をするようにしている。
recfsusb2n自体にも--waitで待つ機能があるようだけど正確に働かない感じだったので
スクリプト内のsleepで待つようにした。

録画時間は15秒前終了

重なってはいないけど録画時間が連続している場合、多少のギャップを作ってチューナー
を空けておかないと録画開始時にデバイスエラーになってしまうので、若干短めにしておく。


とまあ、細かいところだけれど、録画失敗してがっかりとならないようにやっておかないとね。
で実際の録画ジョブコードは以下のとおり。
  def perform(video)
    if video
      # write path
      path = video.program.start_at.strftime("%Y%m")
      fdir = "#{VIDEO_ROOT}/#{path}"
      Dir.mkdir(fdir, 0777) unless Dir.exist?(fdir)

      fname = "#{path}/#{video.id}"
      fpath = "#{VIDEO_ROOT}/#{fname}"

      # recording
      channel = video.program.channel.ch
      duration = video.program.duration - 15
      wait = (video.program.start_at - Time.now).to_i

      sleep wait if wait>0

      p "------recording start: #{fname}"
      begin
        `tvoff`
        # recode
        `recfsusb2n -b -i hd #{channel} #{duration} #{fpath}.ts`
        `tvon`
        # encode
        p `ffmpeg -loglevel 8 -y -i #{fpath}.ts -c:v libx264 -c:a libfaac -preset superfast -f\
 mp4 -threads 2 -b:v 2000k #{fpath}.mp4`
        # poster
        p `ffmpeg -loglevel 8 -i #{fpath}.mp4 -ss 12 -vframes 1 -an -s 320x180 #{fpath}.jpg`
        # successed
        video.update_attributes(status_id: 2, filename: "#{fname}") # successfully.
        File.delete("#{fpath}.ts")

      rescue => e
        p e.message
        video.update_attributes(status_id: 3) # recording job failed.
      end
      p "------recording end: #{fpath}"
    end
  end

録画の前後でtvon、tvoffっていうのを実行するようになっていますが、これは自分が適当に
作ったシェルスクリプトでして、以下の様なシロモノです。
tvon
#!/bin/bash
recfsusb2n -b -i hd -H 8888 1>/dev/null 2>/dev/null
tvoff
#!/bin/bash
PID=`pidof recfsusb2n`
if test "$PID" != "" ; then
    kill -9 $PID
fi
録画していない時はリアルタイム視聴できる状態にスタンバイさせておこうというものです。
朝方とか結構重宝します。家族食事中は子供にTVを見せないポリシーなもんで。

0 件のコメント:

コメントを投稿