RaspberryPiで高画質ライブ配信

提供: ディーズガレージ wiki
移動先: 案内検索


この記事は古くなっています。
Jessie with PIXEL版に書き直ししました。

最小構成
ガンマイク、アンプ追加構成
LiveBot2インターフェイス

シングルボードコンピュータでエンコードは通常の方法では無理または結構な負荷をかけます。
特にリアルタイムエンコードが必要なライブ配信では満足のいく品質は不可能です。
負荷のかかる処理をハードウェアエンコーダに負担させて高品質ライブ配信を試みます。

ぶっちゃければ、映像業界で働く身、映像技術の可能性、付加価値の開発目的で24時間365日ライブ配信する中、月数千円、年間数万円の電気料がかかっていました。正確に計算してませんが、電力量90%カットとか、いくら放送しても月100円の放送機器とか、超お手軽LiveBot誕生!とかの方がインパクトあると思います。
超低電力・超低負荷・高品質ライブ放送機器を目指してみます。

環境

RaspberryPi2 ModelB H.264/MPEG-4 AVC High Profileハードウェアデコーダ・エンコーダ搭載
OS 2015-05-05-raspbian-wheezy.img
Logicool® HD Pro Webcam C920 H.264/MJPGハードウエアエンコーダ搭載

H.264映像処理をC920のハードウエアエンコーダが負担し、AACオーディオ処理をRaspberryPiハードウエアエンコーダが負担します。
GStreamerにH.264ストリームとAACストリームを取り込みflvでラッピングしてローカルのnginxのrtmpサーバに送信。rtmpサーバがパケットを感知し自動的に外部の各ライブ配信サイトにプッシュします。nginxの仕様上マルチ配信も可能になります。

USTREAM 中目黒桜並木 定点カメラで動作確認しています。
ガンマイク ( + ウインドジャマー ) 、アンプ追加構成です。
USTREAM

LiveBot2 - カメラコントロール・配信機能削除版 - 用意しました。
ご自由にお試しください。

技術メモ

  • 現在の設定でワットチェッカーplusで電気料金測定してみました。86円/月、1048円/年でした。東京電力 従量電灯B 第3段階料金 29円93銭 で計算。
  • nginxを使用せずGStreamerのrtmp配信が正攻法と思いますが、GStreamerから直接外部(WAN)に送信すると異常停止または安定しません。CPUリソースをほとんど食わないので、安定配信できるnginx-rtmp-moduleを通しています。
  • C920固有と思いますがBaselineの場合はconstrained-baseline(Baseline強制)にしないと異常停止します。constrained-baselineの場合Baselineレベル4.0を返してきます。
  • Logicool/LogitechでいうRightLightを有効にするとフレームレートが15fpsに制限されます。
  • C920のマイクは16bit 32kHzです。
  • rtmpのURLとStreamKeyの組でプッシュできる配信サービスは数十種ありますが接続時に毎回変わったり、時間で変わってしまうサービスもあるようです。Ustream、Youtube辺りで24時間365日配信目的で開発進めてましたので個別に対応してません。「FME OBS 自動枠取り」で検索すると事情が見えると思います。FlashMediaLiveEncoder、OpenBroadcasterSoftware辺りで配信できるサイトは比較的簡単に対応できます。
  • 映像送信クライアントにしてnginx-rtmp-moduleのrelay機能を使用すると、保障できる帯域の範囲であれば中央集中管理型の中・大規模カメラネットワークを超破格値で構築することも簡単と思います。
  • カメラの全パラメーターと再起動を遠隔管理でき送信パケットの種類は豊富にあるわけでRICOH THETA Sなどの360度ライブ配信などカメラに近寄れない状況では重宝しそうな予感します。

ファームウェア更新

$ sudo rpi-update

再起動

$ sudo reboot

最新状態にアップデート

$ sudo apt-get update
$ sudo apt-get upgrade

再起動

$ sudo reboot

USB電流供給制限解除

気持ち程度設定します。設定しなくても構わないと思います。
USB電流供給を0.6A制限から1.2Aまで増加できるそうです。

$ sudo leafpad /boot/config.txt

末尾に追加

safe_mode_gpio=4
max_usb_current=1

再起動

$ sudo reboot

マイクセッティング

優先順位をRaspberryPi内臓マイクからUSBマイクに変更

$ sudo leafpad /etc/modprobe.d/alsa-base.conf

変更箇所

#options snd-usb-audio index=-2
options snd-usb-audio index=0

再起動

$ sudo reboot

録音ボリューム

$ alsamixer
F6で0 HD Pro Webcam C920を選びF4でボリューム46程度に設定しEscで設定終了

録音テスト

$ arecord -D plughw:0,0 -f cd test.wav
エラーが出なければOK
Ctrl+Cで停止

GStreamerのインストール

インストールスクリプト新規作成

$ sudo leafpad gst_install

コピーペースト

#!/bin/bash -v         

# Create a log file of the build as well as displaying the build on the tty as it runs
exec > >(tee gst_install.log)
exec 2>&1

# COMPILE GSTREAMER 1.4.5 ###############

# Get the required libraries
sudo aptitude install -y build-essential autotools-dev automake autoconf libtool autopoint libxml2-dev zlib1g-dev libglib2.0-dev pkg-config bison flex python git gtk-doc-tools libasound2-dev libgudev-1.0-dev libxt-dev libvorbis-dev libcdparanoia-dev libpango1.0-dev libtheora-dev libvisual-0.4-dev iso-codes libgtk-3-dev libraw1394-dev libiec61883-dev libavc1394-dev libv4l-dev libcairo2-dev libcaca-dev libspeex-dev libpng-dev libshout3-dev libjpeg-dev libaa1-dev libflac-dev libdv4-dev libtag1-dev libwavpack-dev libpulse-dev libsoup2.4-dev libbz2-dev libcdaudio-dev libdc1394-22-dev ladspa-sdk libass-dev libcurl4-gnutls-dev libdca-dev libdirac-dev libdvdnav-dev libexempi-dev libexif-dev libfaad-dev libgme-dev libgsm1-dev libiptcdata0-dev libkate-dev libmimic-dev libmms-dev libmodplug-dev libmpcdec-dev libofa0-dev libopus-dev librsvg2-dev librtmp-dev libschroedinger-dev libslv2-dev libsndfile1-dev libsoundtouch-dev libspandsp-dev libx11-dev libxvidcore-dev libzbar-dev libzvbi-dev liba52-0.7.4-dev libcdio-dev libdvdread-dev libmad0-dev libmp3lame-dev libmpeg2-4-dev libopencore-amrnb-dev libopencore-amrwb-dev libsidplay1-dev libtwolame-dev libx264-dev

sudo aptitude -y install  python-gobject python-gobject-dev python-pip
sudo aptitude -y install libusb-1.0-0-dev libxv-dev
sudo aptitude -y install libmpg123-dev libsoundtouch0-dev libvo-aacenc-dev
sudo aptitude -y install libavutil-dev
sudo aptitude -y install yasm
sudo aptitude -y install inotify-tools
sudo aptitude -y install python-dev gtk-doc-tools

cd $HOME
mkdir packages
cd packages 
mkdir gstreamer-1.4.5
cd gstreamer-1.4.5

wget http://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.4.5.tar.xz
wget http://gstreamer.freedesktop.org/src/orc/orc-0.4.22.tar.xz
wget http://gstreamer.freedesktop.org/src/gst-plugins-base/gst-plugins-base-1.4.5.tar.xz
wget http://gstreamer.freedesktop.org/src/gst-plugins-good/gst-plugins-good-1.4.5.tar.xz
wget http://gstreamer.freedesktop.org/src/gst-plugins-ugly/gst-plugins-ugly-1.4.5.tar.xz
wget http://gstreamer.freedesktop.org/src/gst-plugins-bad/gst-plugins-bad-1.4.5.tar.xz
wget http://gstreamer.freedesktop.org/src/gst-libav/gst-libav-1.4.5.tar.xz
wget http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.2.0.tar.xz

# unpack
find ./ -name "*.tar.xz" | xargs -n 1 tar -xJf
find ./ -name "*.tar.gz" | xargs -n 1 tar -xzf

cd gstreamer-*
./configure --prefix=/usr/local/
make -j 2
sudo make install
cd ..

cd orc-*
LIBS="$LIBS -L/usr/loca/lib" ./configure --prefix=/usr/local
make -j 2
sudo make install
cd ..

cd gst-plugins-base-*
LIBS="$LIBS -L/usr/loca/lib" ./configure --enable-orc --with-libv4l2 --with-x
make -j 2
sudo make install
cd ..

cd gst-plugins-good-*
LIBS="$LIBS -L/usr/loca/lib" ./configure --prefix=/usr/local
make -j 2
sudo make install
cd ..

cd gst-plugins-ugly-*
LIBS="$LIBS -L/usr/loca/lib" ./configure --prefix=/usr/local
make -j 2
sudo make install
cd ..

cd gst-libav-*
LIBS="$LIBS -L/usr/loca/lib" ./configure --prefix=/usr/local
make -j 2
sudo make install
cd ..

# Install libusb-1.0 to enable uvch264src
sudo apt-get install libusb-1.0

cd gst-plugins-bad-*
LIBS="$LIBS -L/usr/loca/lib" LDFLAGS='-L/opt/vc/lib' CPPFLAGS='-I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux' ./configure  --prefix=/usr/local/
make -j 2
sudo make install
cd ..

cd gst-omx-*
LIBS="$LIBS -L/usr/loca/lib" LDFLAGS='-L/opt/vc/lib' CPPFLAGS='-I/opt/vc/include -I/opt/vc/include/IL -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux' ./autogen.sh --with-omx-target=rpi --prefix=/usr/local
make -j 2
sudo make install

実行権限

$ sudo chmod +x gst_install

実行(インストール)

$ ./gst_install

再起動

$ sudo reboot

nginxのインストール

$ cd packages
$ mkdir nginx-1.8.0
$ cd nginx-1.8.0
$ wget http://nginx.org/download/nginx-1.8.0.tar.gz
$ wget https://github.com/arut/nginx-rtmp-module/archive/v1.1.7.zip
$ tar -zxvf nginx-1.8.0.tar.gz
$ unzip v1.1.7.zip
$ cd nginx-1.8.0
$ ./configure --add-module=/home/pi/packages/nginx-1.8.0/nginx-rtmp-module-1.1.7
$ make -j 2
$ sudo make install
$ cd /usr/local/nginx/conf
$ sudo cp nginx.conf nginx.conf.back
$ sudo leafpad nginx.conf
Ustreamの場合
Youtube Liveの場合

コピー&ペーストで上書き
利用する配信サイトのコメント(#)を消しXXXXXXXに必要な情報を入力
複数のコメント(#)消す=マルチ配信

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}

rtmp {
    server {
        listen 1935;
        publish_time_fix off;
        chunk_size 4096;

        application live {
            live on;
            record off;

            #Ustream
            #push rtmp://X.XXXXXXXX.fme.ustream.tv app=ustreamVideo/XXXXXXXX playpath=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
            
            #Youtube Live
            #push rtmp://a.rtmp.youtube.com/live2/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
            
        }
    }
}

自動起動設定

$ sudo leafpad /etc/rc.local

末尾のexit 0手前に記入

sudo /usr/local/nginx/sbin/nginx

再起動

$ sudo reboot

liveスクリプト

新規作成

$ sudo leafpad live

コピーペースト

#!/bin/sh

# SETTING ###############################

# VIDEO

WIDTH=1920 # 解像度(幅)
HEIGHT=1080 # 解像度(高)
FRAMERATE=30 # フレームレート(fps)
BITRATE=800000 # ビットレート(bps)
PROFILE="constrained-baseline" # プロファイル constrained-baseline , main , high

PRIORITY=0 # RightLight  0:無効  1:有効(露出・ゲイン自動)  規定値1
EXPO_MODE=3 # 露出モード  0:自動  1:マニュアル  2:シャッター優先  3:絞り優先  規定値3
EXPOSURE=250 # 露出(3-2047)  ステップ1  規定値250
GAIN=255 # ゲイン(0-255)  ステップ1  規定値255

AUTOFOCUS=0 # オートフォーカス  0:無効  1:有効
FOCUS=0 # フォーカス(0-250)  ステップ5  規定値0
ZOOM=100 # ズーム(100-180)  ステップ1  規定値100

BACKLIGHT=0 # 逆光補正  0:有効  1:無効

BRIGHTNESS=128 # 明るさ(0-255)  ステップ1  規定値128
CONTRAST=128 # コントラスト(0-255)  ステップ1  規定値128
SATURATION=128 # 彩度(0-255)  ステップ1  規定値128
SHARPNESS=128 # シャープネス(0-255)  ステップ1  規定値128

WHITE_AUTO=1 # オートホワイトバランス  0:無効  1:有効
WHITE=4955 # ホワイトバランス(2000-6500)

FREQ=2 # アンチフリッカー  0:off  1:PAL-50Hz  2:NTSC-60Hz

LED=0 #カメラのLEDライト 0:OFF 1:ON

# AUDIO サンプルレート32000Hz固定

VOLUME=0.2 #ボリューム(0-1.0)
CHANNEL=2 # チャンネル 1:mono  2:stereo
ABITRATE=96000 # ビットレート(bps)

# EXECUTE ###############################

v4l2-ctl --set-ctrl=exposure_auto_priority=$PRIORITY
v4l2-ctl --set-ctrl=exposure_auto=$EXPO_MODE
#v4l2-ctl --set-ctrl=exposure_absolute=$EXPOSURE
#v4l2-ctl --set-ctrl=gain=$GAIN

v4l2-ctl --set-ctrl=focus_auto=$AUTOFOCUS
v4l2-ctl --set-ctrl=focus_absolute=$FOCUS
v4l2-ctl --set-ctrl=zoom_absolute=$ZOOM

v4l2-ctl --set-ctrl=backlight_compensation=$BACKLIGHT

v4l2-ctl --set-ctrl=brightness=$BRIGHTNESS
v4l2-ctl --set-ctrl=contrast=$CONTRAST
v4l2-ctl --set-ctrl=saturation=$SATURATION
v4l2-ctl --set-ctrl=sharpness=$SHARPNESS

v4l2-ctl --set-ctrl=white_balance_temperature_auto=$WHITE_AUTO
#v4l2-ctl --set-ctrl=white_balance_temperature=$WHITE

v4l2-ctl --set-ctrl=power_line_frequency=$FREQ

#uvcdynctrl -d video0 -s "LED1 Mode" $LED

CMD="/usr/local/bin/gst-launch-1.0 \
uvch264src average-bitrate=$BITRATE iframe-period=3000 fixed-framerate=true entropy=1 device=/dev/video0 name=src auto-start=true src.vidsrc ! \
queue ! \
video/x-h264,width=$WIDTH,height=$HEIGHT,framerate=$FRAMERATE/1,profile=$PROFILE ! \
h264parse ! \
flvmux name=mux streamable=true alsasrc device=hw:0 ! \
queue ! \
volume volume=$VOLUME ! \
audio/x-raw,format=S16LE,rate=32000,channels=$CHANNEL ! \
voaacenc bitrate=$ABITRATE ! \
queue max-size-buffers=600 max-size-time=0 max-size-bytes=0 flush-on-eos=true ! \
mux. mux. ! \
rtmpsink sync=false location='rtmp://localhost/live/stream'"

export LD_LIBRARY_PATH=/usr/local/lib

$CMD

実行権限

$ sudo chmod +x live

配信テストと調整

liveスクリプトを起動すると配信を開始します。
映像とオーディオ各パラメーターの多くがリアルタイム変更できません。停止、パラメーター調整、起動を繰り返し調整することになります。

起動 $ ./live
停止 Ctrl+C または端末を閉じる
配信サイトの設定 $ sudo leafpad /usr/local/nginx/conf/nginx.conf
カメラとマイクの設定 $ sudo leafpad /home/pi/live
マイクの最大音量の設定 $ alsamixer

最低限の動作環境はこれで完了です。
以降はwebインターフェイスを用意して実運用向けに改造します。

webインターフェイスの用意

LiveBot パソコン画面

※外部に公開するwebサーバーでは導入しないでください。非常に危険です。

電源とインターネットがあればどこでも配信できるようにするため固定IPを使わずホスト名でwebインターフェイスに接続できるようにします。

ホスト名

ホスト名変更

$ sudo leafpad /etc/hostname

変更

livebot

ホスト名変更

$ sudo leafpad /etc/hosts

変更

127.0.1.1 livebot

再起動

$ sudo reboot

nginx+php5-fpm

php5-fpmのインストール

$ sudo apt-get install php5-fpm

nginx.confの書き換え

$ sudo leafpad /usr/local/nginx/conf/nginx.conf

上書き

#user  nobody;
worker_processes 1;

#error_log logs/error.log;
#error_log logs/error.log  notice;
#error_log logs/error.log  info;

#pid logs/nginx.pid;

events {
    worker_connections 512;
}

http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    tcp_nopush on;
    keepalive_timeout 65;
    root /usr/local/nginx/html;
    index index.php index.html index.htm;
    
    server {
        listen 80;
        server_name localhost;
        
        error_page 404 /404.html;
        error_page 500 502 503 504 /50x.html;
        
        location ~ \.php$ {
            fastcgi_pass   unix:/var/run/php5-fpm.sock;
            fastcgi_index  index.php;
            include        fastcgi_params;
            fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;
        }
    }
}

rtmp {
    server {
        listen 1935;
        publish_time_fix off;
        chunk_size 8192;
        
        application preview {
            live on;
            record off;
        }
        
        application live {
            live on;
            record off;
            #meta on;
            #wait_key on;
            #wait_video on;
            #publish_notify on;
            #drop_idle_publisher 10s;
            
            #preview push
            push rtmp://localhost/preview/stream;
            
            #Ustream
            #push rtmp://X.XXXXXXXX.fme.ustream.tv app=ustreamVideo/XXXXXXXX playpath=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
            
            #Youtube Live
            #push rtmp://a.rtmp.youtube.com/live2/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
        }
    }
}

パーミッションエラー回避

$ sudo leafpad /etc/php5/fpm/pool.d/www.conf

変更部分

listen.owner = www-data
listen.group = www-data
listen.mode = 0666

index.php

バックアップ

$ sudo mv /usr/local/nginx/html/index.html ~/index.html_bak
$ sudo mv /usr/local/nginx/html/50x.html ~/50x.html_bak

index.phpの新規作成

$ sudo leafpad /usr/local/nginx/html/index.php

上書き

<?php

$file = 'save.txt';
$data = @file($file, FILE_IGNORE_NEW_LINES);

?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="-1">
<title>LiveBot2</title>
<link rel="stylesheet" href="http://vjs.zencdn.net/5.4.6/video-js.css">
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/jquery.switchbutton/1.0/jquery.switchButton.css">
<style>

html {
	height: 100%;
	display: table;
	font-family: 'Lucida Grande', 'Hiragino Kaku Gothic ProN', 'ヒラギノ角ゴ ProN W3', Meiryo, メイリオ, sans-serif;
	font-size: 10px;
	background: #262626;
	color: #e2e2e2;
	margin: 0 auto;
	padding: 0;
}
body {
	display: table-cell;
	vertical-align: middle;
	margin: 0 auto;
	padding: 0;
}
p,
span {
	margin: 0;
	padding: 0;
}
select,
input {
	font-size: 11px;
}
#wrapper {
	width: 840px;
	line-height: 23px;
	background: #484848;
	opacity: 0;
}
#header {
	margin-bottom: 4px;
	padding-top: 2px;
	font-size: 11px;
	font-weight: 700;
	text-align: center;
}
#footer {
	margin-top: 4px;
	padding-top: 2px;
	text-align: center;
}
#control1 {
	float: left;
	width: 196px;
}
#control2 {
	float: left;
	width: 196px;
	margin-left: 4px;
}
#container {
	position: relative;
	float: right;
	width: 440px;
	height: 420px;
	margin-left: 4px;
}
#regulation {
	position: relative;
	height: 470px;
	padding: 6px;
}
#video {
	position: relative;
	height: 196px;
	padding: 6px;
}
#audio {
	position: relative;
	height: 212px;
	margin-top: 4px;
	padding: 6px;
}
#url {
	position: relative;
	height: 170px;
	margin-top: 4px;
	line-height: 24px;
	padding: 10px 6px 6px;
}
#set {
	float: right;
	margin-top: 4px;
	width: 626px;
	height: 26px;
	margin-left: 4px;
	padding: 6px;
}
#reset_image,
#reset_video,
#save {
	margin-right: 12px;
}
#my-video {
	width: 440px;
	height: 248px;
}
#header,
#footer,
#regulation,
#video,
#audio,
#url,
#set,
#my-video {
	background: #595959;
	border: 1px solid #737373;
	box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2);
}
/*#my-video {
	pointer-events: none;
}*/
.question {
	position: absolute;
	right: 6px;
	top: 6px;
}
.question img {
	cursor: pointer;
}
.clear {
	clear: both;
}
input[type=text],
select {
	border-radius: 3px;
	height: 19px;
}
input[type=text] {
	border: 1px solid #737373;
}
input[type=button] {
	font-weight: 700;
	padding: 2px 10px;
}
input[type=checkbox] {
	margin-top: 4px;
}
#url input[type=text] {
	margin-top: 2px;
}
#url p,
input[type=checkbox] {
	float: left;
}
select {
	height: 22px;
	color: #e2e2e2;
	background: #595959;
	border: 1px solid #737373;
}
#range01,
#range02,
#range03 {
	width: 110px;
	height: 10px;
	margin-top: 6px;
	margin-left: 8px;
	float: left;
}
#range04,
#range05,
#range06,
#range07,
#range08,
#range09,
#range10 {
	width: 110px;
	height: 10px;
	margin-top: 6px;
	margin-left: 8px;
	float: left;
}
#range01value,
#range02value,
#range03value,
#range04value,
#range05value,
#range06value,
#range07value,
#range08value,
#range09value,
#range10value {
	width: 40px;
	float: right;
	text-align: center;
	background: #595959;
	border: 1px solid #737373;
	color: #e2e2e2;
}
#url .switch-button-label.on {
	color: red;
}
#control1 .switch-button-background {
	float: right;
	margin-top: 6px;
	margin-right: 1px;
}
#control1 .switch-button-label {
	float: right;
	margin-top: 5px;
	margin-right: 5px;
}
#livestop {
	position: absolute;
	width: 438px;
	height: 26px;
	left: 0;
	top: 0;
	z-index: 10;
	text-align: center;
	background: rgba(0, 0, 0, 0.4);
	margin: 1px 2px 0 1px;
}
#livestart {
	position: absolute;
	width: 438px;
	height: 48px;
	left: 0;
	top: 0;
	z-index: 10;
	text-align: center;
	background: rgba(255, 0, 0, 0.4);
	margin: 1px 2px 0 1px;
}
.ui-widget {
	font-family: 'Lucida Grande', 'Hiragino Kaku Gothic ProN', 'ヒラギノ角ゴ ProN W3', Meiryo, メイリオ, sans-serif;
}
.ui-button {
	background: #737373 !important;
	border: 1px solid #737373 !important;
	color: #eee;
	font-weight: normal !important;
}
.ui-button:hover {
	background: #838383 !important;
	border: 1px solid #838383 !important;
}
.ui-widget-content {
	background: #484848;
	border: 0;
}
.url_text {
	width: 335px;
	background: #484848;
	color: #e2e2e2;
	float: right;
	padding-left: 6px;
}
.url_label {
	float: right;
	padding-right: 4px;
}
.ui-dialog-titlebar-close {
	display: none;
}
.ui-slider .ui-slider-handle {
	cursor: pointer;
	height: 10px !important;
	width: 10px !important;
}
.ui-corner-all,
.ui-corner-left,
.ui-corner-bl,
.ui-slider .ui-slider-handle {
	border-radius: 2px !important;
}
.ui-slider-horizontal .ui-slider-handle {
	top: -1px;
}
.ui-widget-overlay {
	opacity: 0.5px !important;
	background-color: #000 !important;
}
.ui-dialog-title {
	font-size: 12px !important;
}
.switch-button-background {
	height: 10px !important;
	margin-left: 0;
	margin-right: 5px;
	background: #484848;
	border: 1px solid #484848;
	border-radius: 2px;
}
.switch-button-button {
	width: 12px !important;
	height: 12px !important;
	border-radius: 2px;
	background: #dadada;
	border: 0;
}
.switch-button-label {
	height: 0;
	padding-top: 8px;
	line-height: 0;
	font-size: 10px;
}
#set input,
#set div,
.ctl_select {
	float: right;
	margin-top: 2px;
}
#resolution-button,
#profile-button {
	float: right;
	height: 22px !important;
	width: 100px !important;
	background: #595959 none repeat scroll 0 0;
	border: 1px solid #737373;
	border-radius: 3px !important;
	color: #e2e2e2;
}
#framerate-button,
#channel-button,
#bitrate-button {
	float: right;
	height: 22px !important;
	width: 70px !important;
	background: #595959 none repeat scroll 0 0;
	border: 1px solid #737373;
	border-radius: 3px !important;
	color: #e2e2e2;
}
#flicker-button {
	float: right;
	height: 22px !important;
	width: 96px !important;
	background: #595959 none repeat scroll 0 0;
	border: 1px solid #737373;
	border-radius: 3px !important;
	color: #e2e2e2;
}
input[type=checkbox],
input[type=button],
select,
.ui-slider {
	cursor: pointer;
}
#regulation .switch-button-label.on,
.ui-button-text {
	color: #e2e2e2;
}
.vjs-paused .vjs-big-play-button { display: none; }
</style>
<!-- If you'd like to support IE8 -->
<script src="http://vjs.zencdn.net/ie8/1.1.1/videojs-ie8.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.switchbutton/1.0/jquery.switchButton.min.js"></script>
<script>
$(window).on("load", function() {
	//初期設定
	var saveData = new Array();
	$("input[type=button]").button();
	$("input[type=checkbox]").switchButton({
		labels_placement: "right"
	});
	
	/*setTimeout(function() {
	if (<?php echo $data[24] ; ?>) {
		$("#range10").slider({ disabled: "true" });
		$("#range10 span").css({ cursor: "default" });
		$("#range10value").prop("disabled", true);
		$("#range10value").css({ color: "#adadad" });
	}
	}, 1000);*/
	
	$( "#resolution, #framerate, #profile, #channel, #bitrate, #flicker" ).selectmenu();
	
	//各パラメーター//////////////////////////////////////////////////
	//VIDEO///////////////////////////////////////////////////////////
	//ビットレート
	$("#range01").slider({
		min: 400,
		max: 6000,
		step: 100,
		value: <?php echo $data[3] ; ?>,
		animate: true,
		change: function(e, ui) {
			$("#range01value").val(ui.value);
		},
		slide: function(e, ui) {
			$("#range01value").val(ui.value);
		},
		create: function(e, ui) {
			$("#range01value").val($(this).slider('option', 'value'));
		}
	});
	$("input[name=range01value]").change(function() {
		$("#range01").slider("value", $(this).val());
	});
	//AUDIO///////////////////////////////////////////////////////////
	//マスターボリューム
	$("#range02").slider({
		min: 0,
		max: 100,
		step: 1,
		value: <?php echo $data[4] ; ?>,
		animate: true,
		change: function(e, ui) {
			$("#range02value").val(ui.value);
		},
		slide: function(e, ui) {
			$("#range02value").val(ui.value);
		},
		create: function(e, ui) {
			$("#range02value").val($(this).slider('option', 'value'));
		}
	});
	$("input[name=range02value]").change(function() {
		$("#range02").slider("value", $(this).val());
	});
	//ボリューム
	$("#range03").slider({
		min: 0,
		max: 1,
		step: 0.1,
		value: <?php echo $data[5] ; ?>,
		animate: true,
		change: function(e, ui) {
			$("#range03value").val(ui.value);
		},
		slide: function(e, ui) {
			$("#range03value").val(ui.value);
		},
		create: function(e, ui) {
			$("#range03value").val($(this).slider('option', 'value'));
		}
	});
	$("input[name=range03value]").change(function() {
		$("#range03").slider("value", $(this).val());
	});
	//IMAGE///////////////////////////////////////////////////////////
	//フォーカス
	$("#range04").slider({
		min: 0,
		max: 250,
		step: 5,
		value: <?php echo $data[17] ; ?>,
		animate: true,
		change: function(e, ui) {
			$("#range04value").val(ui.value);
			saveData[15] = "focus_absolute";
			saveData[16] = $("input[name=range04value]").val();
			setImage();
		},
		slide: function(e, ui) {
			$("#range04value").val(ui.value);
		},
		create: function(e, ui) {
			$("#range04value").val($(this).slider('option', 'value'));
		}
	});
	$("input[name=range04value]").change(function() {
		$("#range04").slider("value", $(this).val());
	});
	//ズーム
	$("#range05").slider({
		min: 100,
		max: 180,
		step: 1,
		value: <?php echo $data[18] ; ?>,
		animate: true,
		change: function(e, ui) {
			$("#range05value").val(ui.value);
			saveData[15] = "zoom_absolute";
			saveData[16] = $("input[name=range05value]").val();
			setImage();
		},
		slide: function(e, ui) {
			$("#range05value").val(ui.value);
		},
		create: function(e, ui) {
			$("#range05value").val($(this).slider('option', 'value'));
		}
	});
	$("input[name=range05value]").change(function() {
		$("#range05").slider("value", $(this).val());
	});
	//逆光補正
	$("#checkbox03").change(function() {
		saveData[15] = "backlight_compensation";
		if ($("#checkbox03").prop('checked')) {
			saveData[16] = "0";
		} else {
			saveData[16] = "1";
		}
		setImage();
	});
	//明るさ
	$("#range06").slider({
		min: 0,
		max: 255,
		step: 1,
		value: <?php echo $data[20] ; ?>,
		animate: true,
		change: function(e, ui) {
			$("#range06value").val(ui.value);
			saveData[15] = "brightness";
			saveData[16] = $("input[name=range06value]").val();
			setImage();
		},
		slide: function(e, ui) {
			$("#range06value").val(ui.value);
		},
		create: function(e, ui) {
			$("#range06value").val($(this).slider('option', 'value'));
		}
	});
	$("input[name=range06value]").change(function() {
		$("#range06").slider("value", $(this).val());
	});
	//コントラスト
	$("#range07").slider({
		min: 0,
		max: 255,
		step: 1,
		value: <?php echo $data[21] ; ?>,
		animate: true,
		change: function(e, ui) {
			$("#range07value").val(ui.value);
			saveData[15] = "contrast";
			saveData[16] = $("input[name=range07value]").val();
			setImage();
		},
		slide: function(e, ui) {
			$("#range07value").val(ui.value);
		},
		create: function(e, ui) {
			$("#range07value").val($(this).slider('option', 'value'));
		}
	});
	$("input[name=range07value]").change(function() {
		$("#range07").slider("value", $(this).val());
	});
	//彩度
	$("#range08").slider({
		min: 0,
		max: 255,
		step: 1,
		value: <?php echo $data[22] ; ?>,
		animate: true,
		change: function(e, ui) {
			$("#range08value").val(ui.value);
			saveData[15] = "saturation";
			saveData[16] = $("input[name=range08value]").val();
			setImage();
		},
		slide: function(e, ui) {
			$("#range08value").val(ui.value);
		},
		create: function(e, ui) {
			$("#range08value").val($(this).slider('option', 'value'));
		}
	});
	$("input[name=range08value]").change(function() {
		$("#range08").slider("value", $(this).val());
	});
	//シャープネス
	$("#range09").slider({
		min: 0,
		max: 255,
		step: 1,
		value: <?php echo $data[23] ; ?>,
		animate: true,
		change: function(e, ui) {
			$("#range09value").val(ui.value);
			saveData[15] = "sharpness";
			saveData[16] = $("input[name=range09value]").val();
			setImage();
		},
		slide: function(e, ui) {
			$("#range09value").val(ui.value);
		},
		create: function(e, ui) {
			$("#range09value").val($(this).slider('option', 'value'));
		}
	});
	$("input[name=range09value]").change(function() {
		$("#range09").slider("value", $(this).val());
	});
	//オートホワイトバランス
	$("#checkbox04").change(function() {
		saveData[15] = "white_balance_temperature_auto";
		if ($("#checkbox04").prop('checked')) {
			saveData[16] = "1";
			$("#range10").slider("option", "disabled", true);
			$("#range10 span").css({ cursor: "default" });
			$("#range10value").prop("disabled", true);
			$("#range10value").css({ color: "#adadad" });
		} else {
			saveData[16] = "0";
			$("#range10").slider("option", "disabled", false);
			$("#range10 span").css({ cursor: "pointer" });
			$("#range10value").prop("disabled", false);
			$("#range10value").css({ color: "#fff" });
		}
		setImage();
	});
	//ホワイトバランス
	$("#range10").slider({
		min: 2000,
		max: 6500,
		step: 1,
		value: <?php echo $data[25] ; ?>,
		animate: true,
		change: function(e, ui) {
			$("#range10value").val(ui.value);
			saveData[15] = "white_balance_temperature";
			saveData[16] = $("input[name=range10value]").val();
			setImage();
		},
		slide: function(e, ui) {
			$("#range10value").val(ui.value);
		},
		create: function(e, ui) {
			$("#range10value").val($(this).slider('option', 'value'));
			//初期化
			if ($("#checkbox04").prop('checked')) {
				$("#range10").slider({ disabled: "true" });
				$("#range10 span").css({ cursor: "default" });
				$("#range10value").prop("disabled", true);
				$("#range10value").css({ color: "#adadad" });
			}
		}
	});
	$("input[name=range10value]").change(function() {
		$("#range10").slider("value", $(this).val());
	});
	//アンチフリッカー
	$("#flicker").change(function() {
		saveData[15] = "power_line_frequency";
		if ($("#flicker").val() == "OFF") {
			saveData[16] = "0";
		} else if ($("#flicker").val() == "PAL-50Hz") {
			saveData[16] = "1";
		} else {
			saveData[16] = "2";
		}
		setImage();
	});
	//カメラのLEDライト
	/*$("#checkbox05").change(function() {
		saveData[15] = "LED";
		if ($("#checkbox05").prop('checked')) {
			saveData[16] = "1";
		} else {
			saveData[16] = "0";
		}
		setImage();
	});*/
	
	//ダイアログ//////////////////////////////////////////////////////
	//IMAGE リセット
	$("#reset_image").click(function() {
		$("#dialog01").dialog("open");
	});
	$("#dialog01").dialog({
		autoOpen: false,
		width: 320,
		title: "IMAGE リセット",
		modal: true,
		resizable: false,
		buttons: {
			"Ok": function() {
				//初期化
				saveData[14] = "resetImage";
				saveData[15] = "null";
				saveData[16] = "null";
				$("input[name=range04value]").val("0");
				$("#range04").slider("value", "0");
				$("input[name=range05value]").val("100");
				$("#range05").slider("value", "100");
				if (!$("#checkbox03").prop('checked')) {
					$("#checkbox03").switchButton({
						checked: true
					});
				}
				$("input[name=range06value]").val("128");
				$("#range06").slider("value", "128");
				$("input[name=range07value]").val("128");
				$("#range07").slider("value", "128");
				$("input[name=range08value]").val("128");
				$("#range08").slider("value", "128");
				$("input[name=range09value]").val("128");
				$("#range09").slider("value", "128");
				if (!$("#checkbox04").prop('checked')) {
					$("#checkbox04").switchButton({
						checked: true
					});
				}
				$("input[name=range10value]").val("5000");
				$("#range10").slider("value", "5000");
				$("#flicker").val("NTSC-60Hz");
				/*if ($("#checkbox05").prop('checked')) {
					$("#checkbox05").switchButton({
						checked: false
					});
				}*/
				//PHPへJSON
				get_value();
				send_data = JSON.stringify(saveData);
				$.ajax({
					url: "save.php",
					type: "POST",
					contentType: "Content-Type: application/json; charset=UTF-8",
					dataType: 'json',
					data: send_data
				});
				saveData[14] = "setImage";
				$(this).dialog("close");
			},
			"Cancel": function() {
				$(this).dialog("close");
			}
		},
		open: function(event, ui) {
			$("body").css({
				overflow: "hidden"
			});
			$(".ui-widget-overlay").css({
				background: "rgb(0 ,0 ,0)",
				opacity: ".50 !important",
				filter: "Alpha(Opacity=50)",
			});
		},
		beforeClose: function(event, ui) {
			$("body").css({
				overflow: "inherit"
			})
		}
	});
	//VIDEO・AUDIO リセット
	$("#reset_video").click(function() {
		$("#dialog02").dialog("open");
	});
	$("#dialog02").dialog({
		autoOpen: false,
		width: 320,
		title: "VIDEO・AUDIO リセット",
		modal: true,
		resizable: false,
		buttons: {
			"Ok": function() {
				//初期化
				saveData[14] = "resetVideo";
				saveData[15] = "null";
				saveData[16] = "null";
				$("#resolution").val("1280x720");
				$("#framerate").val("15");
				$("#profile").val("high");
				$("input[name=range01value]").val("800");
				$("#range01").slider("value", "800");
				$("input[name=range02value]").val("50");
				$("#range02").slider("value", "50");
				$("input[name=range03value]").val("0.5");
				$("#range03").slider("value", "0.5");
				$("#channel").val("stereo");
				$("#bitrate").val("128");
				//PHPへJSON
				get_value();
				send_data = JSON.stringify(saveData);
				$.ajax({
					url: "save.php",
					type: "POST",
					contentType: "Content-Type: application/json; charset=UTF-8",
					dataType: 'json',
					data: send_data
				});
				$(this).dialog("close");
			},
			"Cancel": function() {
				$(this).dialog("close");
			}
		},
		open: function(event, ui) {
			$("body").css({
				overflow: "hidden"
			});
			$(".ui-widget-overlay").css({
				background: "rgb(0 ,0 ,0)",
				opacity: ".50 !important",
				filter: "Alpha(Opacity=50)",
			});
		},
		beforeClose: function(event, ui) {
			$("body").css({
				overflow: "inherit"
			})
		}
	});
	//設定保存・再起動
	$("#save").click(function() {
		$("#dialog03").dialog("open");
	});
	$("#dialog03").dialog({
		autoOpen: false,
		width: 320,
		title: "設定保存・再起動",
		modal: true,
		resizable: false,
		buttons: [{
			text: 'Ok',
			class: 'btn-ok',
			click: function() {
				//PHPへJSON
				saveData[14] = "reboot";
				saveData[15] = "null";
				saveData[16] = "null";
				get_value();
				send_data = JSON.stringify(saveData);
				$.ajax({
					url: "save.php",
					type: "POST",
					contentType: "Content-Type: application/json; charset=UTF-8",
					dataType: 'json',
					data: send_data
				});
				$(this).dialog("close");
			}
		}, {
			text: 'Cancel',
			click: function() {
				$(this).dialog("close");
			}
		}],
		open: function(event, ui) {
			$("body").css({
				overflow: "hidden"
			});
			$(".ui-widget-overlay").css({
				background: "rgb(0 ,0 ,0)",
				opacity: ".50 !important",
				filter: "Alpha(Opacity=50)",
			});
		},
		beforeClose: function(event, ui) {
			$("body").css({
				overflow: "inherit"
			})
		}
	});
	//IMAGE について
	$("#qbutton01").click(function() {
		$("#dialog04").dialog("open");
	});
	$("#dialog04").dialog({
		autoOpen: false,
		width: 320,
		title: "IMAGE について",
		modal: true,
		resizable: false,
		buttons: {
			"Ok": function() {
				$(this).dialog("close");
			}
		},
		open: function(event, ui) {
			$("body").css({
				overflow: "hidden"
			});
			$(".ui-widget-overlay").css({
				background: "rgb(0 ,0 ,0)",
				opacity: ".50 !important",
				filter: "Alpha(Opacity=50)",
			});
		},
		beforeClose: function(event, ui) {
			$("body").css({
				overflow: "inherit"
			})
		}
	});
	//VIDEO・AUDIO・URL について
	$("#qbutton02, #qbutton03, #qbutton04").click(function() {
		$("#dialog05").dialog("open");
	});
	$("#dialog05").dialog({
		autoOpen: false,
		width: 320,
		title: "VIDEO・AUDIO・URL について",
		modal: true,
		resizable: false,
		buttons: {
			"Ok": function() {
				$(this).dialog("close");
			}
		},
		open: function(event, ui) {
			$("body").css({
				overflow: "hidden"
			});
			$(".ui-widget-overlay").css({
				background: "rgb(0 ,0 ,0)",
				opacity: ".50 !important",
				filter: "Alpha(Opacity=50)",
			});
		},
		beforeClose: function(event, ui) {
			$("body").css({
				overflow: "inherit"
			})
		}
	});
	
	//value値収集/////////////////////////////////////////////////////
	function get_value() {
		saveData[0] = $("#resolution").val();
		saveData[1] = $("#framerate").val();
		saveData[2] = $("#profile").val();
		saveData[3] = $("input[name=range01value]").val();
		saveData[4] = $("input[name=range02value]").val();
		saveData[5] = $("input[name=range03value]").val();
		saveData[6] = $("#channel").val();
		saveData[7] = $("#bitrate").val();
		if ($("#checkbox01").prop('checked')) {
			saveData[8] = "ON";
		} else {
			saveData[8] = "OFF";
		}
		saveData[9] = $("input[name=url01]").val();
		saveData[10] = $("input[name=url02]").val();
		if ($("#checkbox02").prop('checked')) {
			saveData[11] = "ON";
		} else {
			saveData[11] = "OFF";
		}
		saveData[12] = $("input[name=url03]").val();
		saveData[13] = $("input[name=url04]").val();
		saveData[17] = $("input[name=range04value]").val();
		saveData[18] = $("input[name=range05value]").val();
		if ($("#checkbox03").prop('checked')) {
			saveData[19] = "0";
		} else {
			saveData[19] = "1";
		}
		saveData[20] = $("input[name=range06value]").val();
		saveData[21] = $("input[name=range07value]").val();
		saveData[22] = $("input[name=range08value]").val();
		saveData[23] = $("input[name=range09value]").val();
		if ($("#checkbox04").prop('checked')) {
			saveData[24] = "1";
		} else {
			saveData[24] = "0";
		}
		saveData[25] = $("input[name=range10value]").val();
		if ($("#flicker").val() == "OFF") {
			saveData[26] = "0";
		} else if ($("#flicker").val() == "PAL-50Hz") {
			saveData[26] = "1";
		} else {
			saveData[26] = "2";
		}
		/*if ($("#checkbox05").prop('checked')) {
			saveData[26] = "ON";
		} else {
			saveData[26] = "OFF";
		}*/
	};
	
	//v4l2-ctl操作////////////////////////////////////////////////////
	function setImage() {
		if (saveData[14] == "resetImage") {
			return;
		} else {
			saveData[14] = "setImage";
			get_value();
			send_data = JSON.stringify(saveData);
			$.ajax({
				url: "save.php",
				type: "POST",
				contentType: "Content-Type: application/json; charset=UTF-8",
				dataType: 'json',
				data: send_data
			});
		}
	};
	
	//PLAYER//////////////////////////////////////////////////////////
	//再生ボタン非表示(機能してない模様)
	//$(".vjs-big-play-button").remove();
	//読み込み時のステータス切り替え
	status01 = "<?php echo $data[8] ; ?>";
	status02 = "<?php echo $data[11] ; ?>";
	if (status01 == "ON" || status02 == "ON") {
		$("#livestop").hide();
	} else {
		$("#livestart").hide();
	}
	
	//GUI/////////////////////////////////////////////////////////////
	//表示
	$("#wrapper").animate({
		opacity: "1.0"
	}, 1600);
	//非表示
	$(".btn-ok").click(function() {
		$("#wrapper").animate({
			opacity: '0',
		}, {
			duration: '3200',
			complete: function() {
				$("#wrapper").remove();
				var div = $('<div style="display: table-cell;vertical-align: middle;font-size: 13px;color: #e2e2e2;"><p>再起動中です。再度設定画面を開く場合は1分程度待ってから再読み込みしてください。</p></div>');
				$("body").append(div);
			}
		});
	});
});
</script>
</head>
<body>
<div id="wrapper">
	<div id="header">
		<p>LiveBot2</p>
	</div>
	<div id="control1">
		<div id="regulation">
			<div class="question" id="qbutton01">
				<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAAKTWlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVN3WJP3Fj7f92UPVkLY8LGXbIEAIiOsCMgQWaIQkgBhhBASQMWFiApWFBURnEhVxILVCkidiOKgKLhnQYqIWotVXDjuH9yntX167+3t+9f7vOec5/zOec8PgBESJpHmomoAOVKFPDrYH49PSMTJvYACFUjgBCAQ5svCZwXFAADwA3l4fnSwP/wBr28AAgBw1S4kEsfh/4O6UCZXACCRAOAiEucLAZBSAMguVMgUAMgYALBTs2QKAJQAAGx5fEIiAKoNAOz0ST4FANipk9wXANiiHKkIAI0BAJkoRyQCQLsAYFWBUiwCwMIAoKxAIi4EwK4BgFm2MkcCgL0FAHaOWJAPQGAAgJlCLMwAIDgCAEMeE80DIEwDoDDSv+CpX3CFuEgBAMDLlc2XS9IzFLiV0Bp38vDg4iHiwmyxQmEXKRBmCeQinJebIxNI5wNMzgwAABr50cH+OD+Q5+bk4eZm52zv9MWi/mvwbyI+IfHf/ryMAgQAEE7P79pf5eXWA3DHAbB1v2upWwDaVgBo3/ldM9sJoFoK0Hr5i3k4/EAenqFQyDwdHAoLC+0lYqG9MOOLPv8z4W/gi372/EAe/tt68ABxmkCZrcCjg/1xYW52rlKO58sEQjFu9+cj/seFf/2OKdHiNLFcLBWK8ViJuFAiTcd5uVKRRCHJleIS6X8y8R+W/QmTdw0ArIZPwE62B7XLbMB+7gECiw5Y0nYAQH7zLYwaC5EAEGc0Mnn3AACTv/mPQCsBAM2XpOMAALzoGFyolBdMxggAAESggSqwQQcMwRSswA6cwR28wBcCYQZEQAwkwDwQQgbkgBwKoRiWQRlUwDrYBLWwAxqgEZrhELTBMTgN5+ASXIHrcBcGYBiewhi8hgkEQcgIE2EhOogRYo7YIs4IF5mOBCJhSDSSgKQg6YgUUSLFyHKkAqlCapFdSCPyLXIUOY1cQPqQ28ggMor8irxHMZSBslED1AJ1QLmoHxqKxqBz0XQ0D12AlqJr0Rq0Hj2AtqKn0UvodXQAfYqOY4DRMQ5mjNlhXIyHRWCJWBomxxZj5Vg1Vo81Yx1YN3YVG8CeYe8IJAKLgBPsCF6EEMJsgpCQR1hMWEOoJewjtBK6CFcJg4Qxwicik6hPtCV6EvnEeGI6sZBYRqwm7iEeIZ4lXicOE1+TSCQOyZLkTgohJZAySQtJa0jbSC2kU6Q+0hBpnEwm65Btyd7kCLKArCCXkbeQD5BPkvvJw+S3FDrFiOJMCaIkUqSUEko1ZT/lBKWfMkKZoKpRzame1AiqiDqfWkltoHZQL1OHqRM0dZolzZsWQ8ukLaPV0JppZ2n3aC/pdLoJ3YMeRZfQl9Jr6Afp5+mD9HcMDYYNg8dIYigZaxl7GacYtxkvmUymBdOXmchUMNcyG5lnmA+Yb1VYKvYqfBWRyhKVOpVWlX6V56pUVXNVP9V5qgtUq1UPq15WfaZGVbNQ46kJ1Bar1akdVbupNq7OUndSj1DPUV+jvl/9gvpjDbKGhUaghkijVGO3xhmNIRbGMmXxWELWclYD6yxrmE1iW7L57Ex2Bfsbdi97TFNDc6pmrGaRZp3mcc0BDsax4PA52ZxKziHODc57LQMtPy2x1mqtZq1+rTfaetq+2mLtcu0W7eva73VwnUCdLJ31Om0693UJuja6UbqFutt1z+o+02PreekJ9cr1Dund0Uf1bfSj9Rfq79bv0R83MDQINpAZbDE4Y/DMkGPoa5hpuNHwhOGoEctoupHEaKPRSaMnuCbuh2fjNXgXPmasbxxirDTeZdxrPGFiaTLbpMSkxeS+Kc2Ua5pmutG003TMzMgs3KzYrMnsjjnVnGueYb7ZvNv8jYWlRZzFSos2i8eW2pZ8ywWWTZb3rJhWPlZ5VvVW16xJ1lzrLOtt1ldsUBtXmwybOpvLtqitm63Edptt3xTiFI8p0in1U27aMez87ArsmuwG7Tn2YfYl9m32zx3MHBId1jt0O3xydHXMdmxwvOuk4TTDqcSpw+lXZxtnoXOd8zUXpkuQyxKXdpcXU22niqdun3rLleUa7rrStdP1o5u7m9yt2W3U3cw9xX2r+00umxvJXcM970H08PdY4nHM452nm6fC85DnL152Xlle+70eT7OcJp7WMG3I28Rb4L3Le2A6Pj1l+s7pAz7GPgKfep+Hvqa+It89viN+1n6Zfgf8nvs7+sv9j/i/4XnyFvFOBWABwQHlAb2BGoGzA2sDHwSZBKUHNQWNBbsGLww+FUIMCQ1ZH3KTb8AX8hv5YzPcZyya0RXKCJ0VWhv6MMwmTB7WEY6GzwjfEH5vpvlM6cy2CIjgR2yIuB9pGZkX+X0UKSoyqi7qUbRTdHF09yzWrORZ+2e9jvGPqYy5O9tqtnJ2Z6xqbFJsY+ybuIC4qriBeIf4RfGXEnQTJAntieTE2MQ9ieNzAudsmjOc5JpUlnRjruXcorkX5unOy553PFk1WZB8OIWYEpeyP+WDIEJQLxhP5aduTR0T8oSbhU9FvqKNolGxt7hKPJLmnVaV9jjdO31D+miGT0Z1xjMJT1IreZEZkrkj801WRNberM/ZcdktOZSclJyjUg1plrQr1zC3KLdPZisrkw3keeZtyhuTh8r35CP5c/PbFWyFTNGjtFKuUA4WTC+oK3hbGFt4uEi9SFrUM99m/ur5IwuCFny9kLBQuLCz2Lh4WfHgIr9FuxYji1MXdy4xXVK6ZHhp8NJ9y2jLspb9UOJYUlXyannc8o5Sg9KlpUMrglc0lamUycturvRauWMVYZVkVe9ql9VbVn8qF5VfrHCsqK74sEa45uJXTl/VfPV5bdra3kq3yu3rSOuk626s91m/r0q9akHV0IbwDa0b8Y3lG19tSt50oXpq9Y7NtM3KzQM1YTXtW8y2rNvyoTaj9nqdf13LVv2tq7e+2Sba1r/dd3vzDoMdFTve75TsvLUreFdrvUV99W7S7oLdjxpiG7q/5n7duEd3T8Wej3ulewf2Re/ranRvbNyvv7+yCW1SNo0eSDpw5ZuAb9qb7Zp3tXBaKg7CQeXBJ9+mfHvjUOihzsPcw83fmX+39QjrSHkr0jq/dawto22gPaG97+iMo50dXh1Hvrf/fu8x42N1xzWPV56gnSg98fnkgpPjp2Snnp1OPz3Umdx590z8mWtdUV29Z0PPnj8XdO5Mt1/3yfPe549d8Lxw9CL3Ytslt0utPa49R35w/eFIr1tv62X3y+1XPK509E3rO9Hv03/6asDVc9f41y5dn3m978bsG7duJt0cuCW69fh29u0XdwruTNxdeo94r/y+2v3qB/oP6n+0/rFlwG3g+GDAYM/DWQ/vDgmHnv6U/9OH4dJHzEfVI0YjjY+dHx8bDRq98mTOk+GnsqcTz8p+Vv9563Or59/94vtLz1j82PAL+YvPv655qfNy76uprzrHI8cfvM55PfGm/K3O233vuO+638e9H5ko/ED+UPPR+mPHp9BP9z7nfP78L/eE8/sl0p8zAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAEkSURBVHjapNQxSgNREMbxn2uwEsQiNnZaK4IeIYI38AamEVLkgR7AQuQ12+YGimgrmM5OzAEEsbUQtLEVbUaQJTHZ9YNl3857/Gfmzc7M9ft9oR720FZfjyhzzvetMJxhESVeGwA3cJdS2mxhAYdYwUddUs4ZRimlJRwXkeJbE1hFT2i3MI/P6m6v1/v92Yn3CO9QluVYajHF6wEeAriN27BNVOuPvW2cYv0nKgzCwRDPdSNcRvcXTKzfsdYkwuEY21E4GjYBVqO9iPXOXweLGYGnkepu5QoaAztRkKmaFTiYVNWmwNG0VOsCb+O/nKqJVa601tysDV3EYFiNnv6P2ngtYspc4iRmYm2llLawj/OfO+xGlC/4qvOklL5wheuc8833AJ5XSvrURAcuAAAAAElFTkSuQmCC">
			</div>
			<p style="font-weight: bold;margin-bottom: 2px;">IMAGE - Realtime Setting -</p>
			<div>
				<label>フォーカス</label>
				<br />
				<div id="range04"></div>
				<input type="text" id="range04value" name="range04value" value="" autocomplete="OFF">
			</div>
			<div class="clear"></div>
			<div>
				<label>ズーム</label>
				<br />
				<div id="range05"></div>
				<input type="text" id="range05value" name="range05value" value="" autocomplete="OFF">
			</div>
			<div class="clear" style="height: 6px;"></div>
			<div>
				<label>逆光補正</label>
				<input type="checkbox" id="checkbox03" <?php if ($data[19] == '0' ) echo 'checked' ; ?> autocomplete="OFF" style="float: right;">
			</div>
			<div class="clear"></div>
			<div>
				<label>明るさ</label>
				<br />
				<div id="range06"></div>
				<input type="text" id="range06value" name="range06value" value="" autocomplete="OFF">
			</div>
			<div class="clear"></div>
			<div>
				<label>コントラスト</label>
				<br />
				<div id="range07"></div>
				<input type="text" id="range07value" name="range07value" value="" autocomplete="OFF">
			</div>
			<div class="clear"></div>
			<div>
				<label>彩度</label>
				<br />
				<div id="range08"></div>
				<input type="text" id="range08value" name="range08value" value="" autocomplete="OFF">
			</div>
			<div class="clear"></div>
			<div>
				<label>シャープネス</label>
				<br />
				<div id="range09"></div>
				<input type="text" id="range09value" name="range09value" value="" autocomplete="OFF">
			</div>
			<div class="clear" style="height: 6px;"></div>
			<div>
				<label>オートホワイトバランス</label>
				<input type="checkbox" id="checkbox04" <?php if ($data[24] == '1' ) echo 'checked' ; ?> autocomplete="OFF" style="float: right;">
			</div>
			<div class="clear"></div>
			<div>
				<label>ホワイトバランス</label>
				<br />
				<div id="range10"></div>
				<input type="text" id="range10value" name="range10value" value="" autocomplete="OFF">
			</div>
			<div class="clear" style="height: 10px;"></div>
			<div>
				<label>アンチフリッカー</label>
				<select id="flicker" class="ctl_select" autocomplete="OFF">
					<option <?php if ($data[26] == '0' ) echo 'selected' ; ?> value="OFF">OFF</option>
					<option <?php if ($data[26] == '1' ) echo 'selected' ; ?> value="PAL-50Hz">PAL-50Hz</option>
					<option <?php if ($data[26] == '2' ) echo 'selected' ; ?> value="NTSC-60Hz">NTSC-60Hz</option>
				</select>
			</div>
			<!--<div class="clear" style="height: 6px;"></div>
			<div>
				<label>カメラのLEDライト</label>
				<input type="checkbox" id="checkbox05" <?php if ($data[26] == 'ON' ) echo 'checked' ; ?> autocomplete="OFF" style="float: right;">
			</div>-->
		</div>
	</div>
	<div id="control2">
		<div id="video">
			<div class="question" id="qbutton02">
				<img src="data:image/png;base64,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">
			</div>
			<p style="font-weight: bold;margin-bottom: 2px;">VIDEO</p>
			<div>
				<label>解像度</label>
				<select id="resolution" class="ctl_select" autocomplete="OFF">
					<option <?php if ($data[0] == '1920x1080' ) echo 'selected' ; ?> value="1920x1080">1920x1080</option>
					<option <?php if ($data[0] == '1280x720' ) echo 'selected' ; ?> value="1280x720">1280x720</option>
					<option <?php if ($data[0] == '1024x576' ) echo 'selected' ; ?> value="1024x576">1024x576</option>
					<option <?php if ($data[0] == '864x480' ) echo 'selected' ; ?> value="864x480">864x480</option>
					<option <?php if ($data[0] == '640x360' ) echo 'selected' ; ?> value="640x360">640x360</option>
				</select>
			</div>
			<div class="clear" style="height: 6px;"></div>
			<div>
				<label>フレームレート (fps)</label>
				<select id="framerate" class="ctl_select" autocomplete="OFF">
					<option disabled="disabled" <?php if ($data[1] == '30' ) echo 'selected' ; ?> value="30">30</option>
					<option disabled="disabled" <?php if ($data[1] == '24' ) echo 'selected' ; ?> value="24">24</option>
					<option disabled="disabled" <?php if ($data[1] == '20' ) echo 'selected' ; ?> value="20">20</option>
					<option <?php if ($data[1] == '15' ) echo 'selected' ; ?> value="15">15</option>
					<option disabled="disabled" <?php if ($data[1] == '10' ) echo 'selected' ; ?> value="10">10</option>
					<option disabled="disabled" <?php if ($data[1] == '5' ) echo 'selected' ; ?> value="5">5</option>
				</select>
			</div>
			<div class="clear" style="height: 6px;"></div>
			<div>
				<label>プロファイル</label>
				<select id="profile" class="ctl_select" autocomplete="OFF">
					<option <?php if ($data[2] == 'high' ) echo 'selected' ; ?> value="high">high</option>
					<option <?php if ($data[2] == 'main' ) echo 'selected' ; ?> value="main">main</option>
					<option <?php if ($data[2] == 'constrained-baseline' ) echo 'selected' ; ?> value="constrained-baseline">baseline</option>
				</select>
			</div>
			<div class="clear"></div>
			<div>
				<label>ビットレート (kbps)</label>
				<br />
				<div id="range01"></div>
				<input type="text" id="range01value" name="range01value" value="" autocomplete="OFF">
				<div class="clear"></div>
			</div>
		</div>
		<div id="audio">
			<div class="question" id="qbutton03">
				<img src="data:image/png;base64,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">
			</div>
			<p style="font-weight: bold;margin-bottom: 2px;">AUDIO</p>
			<div>
				<label>マスターボリューム</label>
				<br />
				<div id="range02"></div>
				<input type="text" id="range02value" name="range02value" value="" autocomplete="OFF">
			</div>
			<div class="clear"></div>
			<div>
				<label>ボリューム</label>
				<br />
				<div id="range03"></div>
				<input type="text" id="range03value" name="range03value" value="" autocomplete="OFF">
			</div>
			<div class="clear" style="height: 8px;"></div>
			<div>
				<label>チャンネル</label>
				<select id="channel" class="ctl_select" autocomplete="OFF">
					<option <?php if ($data[6] == 'stereo' ) echo 'selected' ; ?> value="stereo">stereo</option>
					<option disabled="disabled" <?php if ($data[6] == 'mono' ) echo 'selected' ; ?> value="mono">mono</option>
				</select>
			</div>
			<div class="clear" style="height: 6px;"></div>
			<div>
				<label>ビットレート (kbps)</label>
				<select id="bitrate" class="ctl_select" autocomplete="OFF">
					<option <?php if ($data[7] == '128' ) echo 'selected' ; ?> value="128">128</option>
					<option <?php if ($data[7] == '96' ) echo 'selected' ; ?> value="96">96</option>
					<option <?php if ($data[7] == '64' ) echo 'selected' ; ?> value="64">64</option>
				</select>
			</div>
		</div>
	</div>
	<div id="container">
		<div id="livestop">
			<p>ステータス:放送停止中</p>
		</div>
		<div id="livestart">
			<p>ステータス:放送中</p>
			<p>送信映像安定化のためプレビュー停止 (暫定対策)</p>
		</div>
		<video id="my-video" class="video-js" controls autoplay="true" preload="auto" data-setup="{}">
			<source src="rtmp://livebot.local/preview/stream" type='rtmp/mp4'>
		</video>
		<div id="url">
			<div class="question" id="qbutton04">
				<img src="data:image/png;base64,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">
			</div>
			<input type="checkbox" id="checkbox01" <?php if ($data[8] == 'ON' ) echo 'checked' ; ?> autocomplete="OFF" style="float: left;">
			<div class="clear" style="height: 4px;"></div>
			<p style="float: left;">Ustream</p>
			<input type="text" name="url01" class="url_text" value="<?php echo $data[9] ; ?>" autocomplete="OFF"><label class="url_label"> URL </label><br />
			<input type="text" name="url02" class="url_text" value="<?php echo $data[10] ; ?>" autocomplete="OFF"><label class="url_label" style="width: 72px;"> ストリームキー </label>
			<div class="clear" style="height: 10px;"></div>
			<input type="checkbox" id="checkbox02" <?php if ($data[11] == 'ON' ) echo 'checked' ; ?> autocomplete="OFF" style="float: left;">
			<div class="clear" style="height: 4px;"></div>
			<p>Youtube</p>
			<input type="text" name="url03" class="url_text" value="<?php echo $data[12] ; ?>" autocomplete="OFF"><label class="url_label"> URL </label><br />
			<input type="text" name="url04" class="url_text" value="<?php echo $data[13] ; ?>" autocomplete="OFF"><label class="url_label" style="width: 72px;"> ストリームキー </label>
			<div class="clear"></div>
		</div>
	</div>
	<div id="set">
		<input type="button" id="save" value=" 設定保存・再起動 " style="margin-right: 25px;">
		<div style="background-color: gray;	width: 1px;	height: 23px;margin-left: 15px;margin-right: 33px;"></div>
		<input type="button" id="reset_video" value="VIDEO・AUDIO リセット">
		<input type="button" id="reset_image" value="IMAGE リセット" style="margin-right: 27px;">
	</div>
	<div id="dialog01" style="font-size: 11px;color: #e2e2e2;">
		<br />
		<p>IMAGEの設定をデフォルト値に戻します。</p>
	</div>
	<div id="dialog02" style="font-size: 11px;color: #e2e2e2;">
		<br />
		<p>VIDEOとAUDIOの設定をデフォルト値に戻します。</p>
	</div>
	<div id="dialog03" style="font-size: 11px;color: #e2e2e2;">
		<br />
		<p>設定を保存し再起動します。</p>
	</div>
	<div id="dialog04" style="font-size: 11px;color: #e2e2e2;">
		<br />
		<p>カメラの設定ができます。</p>
		<p>配信中でもリアルタイムに調整ができます。</p>
	</div>
	<div id="dialog05" style="font-size: 11px;color: #e2e2e2;">
		<br />
		<p>リアルタイムの設定はできません。</p>
		<p>設定保存し、再起動後設定が反映されます。</p>
		<p>配信にはURLのトグルボタンをONにする必要があります。</p>
	</div>
	<div class="clear"></div>
	<div id="footer">
		<p>Live Streaming System, gstreamer and nginx, @shogooda. 
	</div>
</div>
<script src="http://vjs.zencdn.net/5.4.6/video.js"></script>
</body>
</html>

save.php

save.phpの新規作成

$ sudo leafpad /usr/local/nginx/html/save.php

コピーペースト

<?php

$json = file_get_contents("php://input");
$data01 = json_decode($json);

$file_name02 = "/usr/local/nginx/conf/nginx.conf";
$data02 = file($file_name02);

######################################

$prs = parse_url($data01[9]);

if (strpos($prs[host] ,"XXXXX") !== false){
    $data01[8] = "OFF";
};
if (strpos($data01[13] ,"XXXXX") !== false){
    $data01[11] = "OFF";
};

if ($data01[8] == "ON") {
    $prs[path] = ltrim($prs[path], '/');
    $ustream = "            push " . $prs[scheme] . "://" . $prs[host] . " app=" . $prs[path] . " playpath=" . $data01[10] . ";\n";
} else {
    $ustream = "            #\n";
};
if ($data01[11] == "ON") {
    $youtube = "            push " . $data01[12] . "/" . $data01[13] . ";\n";
} else {
    $youtube = "            #\n";
};

$data02[62] = $ustream;
$data02[65] = $youtube;

if ($data01[8] == "ON" || $data01[11] == "ON") {
    $data02[59] = "            #push rtmp://localhost/preview/stream;\n";
} else {
    $data02[59] = "            push rtmp://localhost/preview/stream;\n";
};

$MIC = $data01[4] . "%";

######################################

if ($data01[14] == "setImage") {
    #カメラコントロール
    if ($data01[15] == "white_balance_temperature_auto" && $data01[16] == "0") {
        $cmd1 = "sudo v4l2-ctl --set-ctrl=" . $data01[15] . "=" . $data01[16];
        shell_exec($cmd1);
        $cmd2 = "sudo v4l2-ctl --set-ctrl=white_balance_temperature=" . $data01[25];
        shell_exec($cmd2);
    } else {
        $cmd1 = "sudo v4l2-ctl --set-ctrl=" . $data01[15] . "=" . $data01[16];
        shell_exec($cmd1);
    }
    $string01 = implode("\n", $data01);
    $file_name01 = "save.txt";
    $file01 = fopen($file_name01, "w") or die("OPEN error $file_name01");
    flock($file01, LOCK_EX);
    fputs($file01, $string01."\n");
    flock($file01, LOCK_UN);
    fclose($file01);
} else if ($data01[14] == "resetImage") {
    #IMAGE リセット
    shell_exec("sudo v4l2-ctl --set-ctrl=focus_absolute=0");
    shell_exec("sudo v4l2-ctl --set-ctrl=zoom_absolute=100");
    shell_exec("sudo v4l2-ctl --set-ctrl=backlight_compensation=0");
    shell_exec("sudo v4l2-ctl --set-ctrl=brightness=128");
    shell_exec("sudo v4l2-ctl --set-ctrl=contrast=128");
    shell_exec("sudo v4l2-ctl --set-ctrl=saturation=128");
    shell_exec("sudo v4l2-ctl --set-ctrl=sharpness=128");
    shell_exec("sudo v4l2-ctl --set-ctrl=white_balance_temperature=5000");
    shell_exec("sudo v4l2-ctl --set-ctrl=white_balance_temperature_auto=1");
    shell_exec("sudo v4l2-ctl --set-ctrl=power_line_frequency=2");
    
    $string01 = implode("\n", $data01);
    $file_name01 = "save.txt";
    $file01 = fopen($file_name01, "w") or die("OPEN error $file_name01");
    flock($file01, LOCK_EX);
    fputs($file01, $string01."\n");
    flock($file01, LOCK_UN);
    fclose($file01);
} else if ($data01[14] == "resetVideo") {
    #VIDEO・AUDIO リセット
    $string01 = implode("\n", $data01);
    $file_name01 = "save.txt";
    $file01 = fopen($file_name01, "w") or die("OPEN error $file_name01");
    flock($file01, LOCK_EX);
    fputs($file01, $string01."\n");
    flock($file01, LOCK_UN);
    fclose($file01);
} else {
    #設定保存・再起動
    $string01 = implode("\n", $data01);
    $file_name01 = "save.txt";
    $file01 = fopen($file_name01, "w") or die("OPEN error $file_name01");
    flock($file01, LOCK_EX);
    fputs($file01, $string01."\n");
    flock($file01, LOCK_UN);
    fclose($file01);
    
    $string02 = implode("", $data02);
    $file02 = fopen($file_name02, "w") or die("OPEN error $file_name02");
    flock($file02, LOCK_EX);
    fputs($file02, $string02."\n");
    flock($file02, LOCK_UN);
    fclose($file02);
    
    shell_exec("sudo amixer set Mic $MIC -c 0");
    sleep(2);
    shell_exec("sudo shutdown -r now");
};

?>

パーミッション変更

$ sudo chmod 0666 /usr/local/nginx/conf/nginx.conf

save.txt

save.txtの新規作成

$ sudo leafpad /usr/local/nginx/html/save.txt

コピーペースト

1280x720
15
high
800
50
0.5
stereo
128
OFF
rtmp://X.XXXXXXXX.fme.ustream.tv/ustreamVideo/XXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
OFF
rtmp://a.rtmp.youtube.com/live2
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
null
null
null
0
100
0
128
128
128
128
1
5000
2

パーミッション変更

$ sudo chmod 0666 /usr/local/nginx/html/save.txt

sudoers

phpからv4l2-ctlとamixerと再起動ができるように設定

$ sudo leafpad /etc/sudoers

末尾に追記

www-data ALL=(ALL) NOPASSWD: /usr/bin/v4l2-ctl, NOPASSWD: /usr/bin/amixer, NOPASSWD: /sbin/shutdown

liveスクリプト

liveスクリプト書き換え

$ sudo leafpad live

上書き

#!/bin/sh

# ARRAY #################################

IFS_BACKUP=$IFS
IFS=$'\n'
ARY=()
i=0
for L in `cat /usr/local/nginx/html/save.txt`
do
  i=`expr $i + 1`
  ARY=("${ARY[@]}" "$L")
done

IFS=$IFS_BACKUP

# 解像度
IFS=$'x'
ARY2=()
i=0
for L in ${ARY[0]}
do
  i=`expr $i + 1`
  ARY2=("${ARY2[@]}" "$L")
done

IFS=$IFS_BACKUP

# Videoビットレート
ARY3=()
unset ARY3[@]
ARY3=${ARY[3]}000

# Audioビットレート
ARY4=()
unset ARY4[@]
ARY4=${ARY[7]}000

# チャンネル
ARY5=()
unset ARY5[@]
if [ ${ARY[6]} = "stereo" ]; then
  ARY5="2"
else
  ARY5="1"
fi

# SETTING ###############################

# IMAGE

PRIORITY=1 # RightLight  0:無効  1:有効(露出・ゲイン自動)  規定値1
EXPO_MODE=0 # 露出モード  0:自動  1:マニュアル  2:シャッター優先  3:絞り優先  規定値3
EXPOSURE=250 # 露出(3-2047)  ステップ1  規定値250
GAIN=255 # ゲイン(0-255)  ステップ1  規定値255
AUTOFOCUS=0 # オートフォーカス  0:無効  1:有効
FOCUS=${ARY[17]} # フォーカス(0-250)  ステップ5  規定値0
ZOOM=${ARY[18]} # ズーム(100-180)  ステップ1  規定値100
BACKLIGHT=${ARY[19]} # 逆光補正  0:有効  1:無効
BRIGHTNESS=${ARY[20]} # 明るさ(0-255)  ステップ1  規定値128
CONTRAST=${ARY[21]} # コントラスト(0-255)  ステップ1  規定値128
SATURATION=${ARY[22]} # 彩度(0-255)  ステップ1  規定値128
SHARPNESS=${ARY[23]} # シャープネス(0-255)  ステップ1  規定値128
WHITE_AUTO=${ARY[24]} # オートホワイトバランス  0:無効  1:有効
WHITE=${ARY[25]} # ホワイトバランス(2000-6500)
FREQ=${ARY[26]} # アンチフリッカー  0:off  1:PAL-50Hz  2:NTSC-60Hz
LED=0 #カメラのLEDライト 0:OFF 1:ON

# VIDEO

WIDTH=${ARY2[0]} # 解像度(幅)
HEIGHT=${ARY2[1]} # 解像度(高)
FRAMERATE=${ARY[1]} # フレームレート(fps)
BITRATE=${ARY3[0]} # ビットレート(bps)
PROFILE="${ARY[2]}" # プロファイル constrained-baseline , main , high

# AUDIO サンプルレート32000Hz固定

VOLUME=${ARY[5]} # ボリューム(0-1.0)
CHANNEL=${ARY5[0]} # チャンネル 1:mono  2:stereo
ABITRATE=${ARY4[0]} # ビットレート(bps)

# EXECUTE ###############################

v4l2-ctl --set-ctrl=exposure_auto_priority=$PRIORITY
#v4l2-ctl --set-ctrl=exposure_auto=$EXPO_MODE
#v4l2-ctl --set-ctrl=exposure_absolute=$EXPOSURE
#v4l2-ctl --set-ctrl=gain=$GAIN
v4l2-ctl --set-ctrl=focus_auto=$AUTOFOCUS
v4l2-ctl --set-ctrl=focus_absolute=$FOCUS
v4l2-ctl --set-ctrl=zoom_absolute=$ZOOM
v4l2-ctl --set-ctrl=backlight_compensation=$BACKLIGHT
v4l2-ctl --set-ctrl=brightness=$BRIGHTNESS
v4l2-ctl --set-ctrl=contrast=$CONTRAST
v4l2-ctl --set-ctrl=saturation=$SATURATION
v4l2-ctl --set-ctrl=sharpness=$SHARPNESS
if [ ${ARY[24]} = "1" ]; then
  v4l2-ctl --set-ctrl=white_balance_temperature_auto=$WHITE_AUTO
else
  v4l2-ctl --set-ctrl=white_balance_temperature_auto=$WHITE_AUTO
  v4l2-ctl --set-ctrl=white_balance_temperature=$WHITE
fi
v4l2-ctl --set-ctrl=power_line_frequency=$FREQ
#uvcdynctrl -d video0 -s "LED1 Mode" $LED

CMD="/usr/local/bin/gst-launch-1.0 \
uvch264src average-bitrate=$BITRATE iframe-period=3000 fixed-framerate=true entropy=1 device=/dev/video0 name=src auto-start=true src.vidsrc ! \
queue ! \
video/x-h264,width=$WIDTH,height=$HEIGHT,framerate=$FRAMERATE/1,profile=$PROFILE ! \
h264parse ! \
flvmux name=mux streamable=true alsasrc device=hw:0 ! \
queue ! \
volume volume=$VOLUME ! \
audio/x-raw,format=S16LE,rate=32000,channels=$CHANNEL ! \
voaacenc bitrate=$ABITRATE ! \
queue max-size-buffers=600 max-size-time=0 max-size-bytes=0 flush-on-eos=true ! \
mux. mux. ! \
rtmpsink sync=false location='rtmp://localhost/live/stream'"

export LD_LIBRARY_PATH=/usr/local/lib

$CMD

liveスクリプト自動起動設定

$ sudo leafpad /etc/rc.local

末尾のexit 0手前、nginx起動を書き換え

#sudo /usr/local/nginx/sbin/nginx
sudo /usr/local/nginx/sbin/nginx;sleep 5;bash /home/pi/live

crontab

24~48時間配信してると映像が不安定になります。タイムスタンプがずれ過ぎなのかもしれません。
24時間に一回RaspberryPi自身を再起動する設定です。

$ sudo leafpad /etc/crontab

末尾に追記(分 時 日 月 曜日 コマンドの順。この場合は毎日6:00に再起動。)

0 6 * * * root shutdown -r now

再起動

$ sudo reboot

動作確認

RaspberryPi以外のパソコンから接続してみる
ブラウザに入力

http://livebot.local

パソコンにはavahiかBonjourがインストールされている必要があります。
Windowsパソコンだけ問題になりやすく、簡単な方法はiTunesをインストールすることです。
ネット検索で「Raspberry avahi Bonjour」辺りで調べると詳しい事情が出てきます。

webインターフェイスのメモ

全般

  • ブラウザのadblockプラグインを有効にしているとYoutube Liveが閲覧できないようです。ご注意。
  • 配信時の再起動は無駄と思います。gstreamerの停止が簡単に出来なかったためです。システムサービスに登録すべきと思います。
  • 再起動設定してるため、まれにmicroSDカードの接触不良と思われるOS起動エラーがありました。接点改質剤 SETTEN CI-S100塗布で安定しています。
  • rtmpをwebインターフェイスに流用してるためスマホ・タブレットで映像を見ながらの設定ができません。
  • 補足。C920はvideo/x-h264とvideo/x-rawの2チャンネル同時出力できるのでvideo/x-rawをハードウエアエンコーダomxh264encでH.264変換しvideoタグでスマホ・タブレット対応試してみましたが遅延が激しくリアルタイム調整には向きませんでした。MotionJPEGであれば遅延を抑えて全デバイス対応できそうな気がします。
  • v4l2-ctl、uvcdynctrlで確認できるズーム値は100-500ですが180までしか動きません(固有値かもしれませんが)。関係する部分は180までに制限しています。
  • 数個のC920で確認した範囲ではカメラのLEDライトON/OFF切り替えに個体差がありました。機能停止しています。
  • liveスクリプトのAUDIOチャンネルmonoがC920のマイクの場合機能しないようです。index.phpでmonoが選択できないようにしています。
  • 30fpsは安定しないよう感じます。liveスクリプトでRightLightを有効にしフレームレート15fpsにindex.phpで制限しています。
  • 映像と音声の同期がずれます。/live/streamまでは問題見当たらず、nginxから先に問題があるように見えます。
以下のようなコメントがネットから拾えます。

Note that there is a firmware bug in this camera that cause the timestamp to be wrong. You may need to enable do-timestamp=1 on the source (v4l2src) (or use development version of GStreamer). 

このカメラにはファームウェアのバグがあることに注意してください。タイムスタンプが間違っています。 あなたはソース(v4l2src)上のdo-timestamp=1を有効にする必要があります。(またはGStreamerの開発版を使用します)。

The preview is not smooth with uvch264src for c920 camera.I found that the timestamp from uvch264src increase about 30ms at normal condition, but sometimes this timestamp increase about 1200ms, and sometimes some timestamp arrive early.I thinks this is problom of dedicated camera.

C920のuvch264srcを使ったプレビューはスムーズでありません。私はノーマル状態で約30ミリ秒増えるuvch264srcのタイムスタンプを見つけました。しかし、ときどきこのタイムスタンプは1200ミリ秒増えます。そして、ときどき早く到着します。私は、これはカメラの問題であると考えています。
望ましい?uvch264srcの設定プロパティー
固定ビットレート(CBR) rate-control=1 固定フレームレート(CFR) fixed-framerate=true
望ましくない?uvch264srcの設定プロパティー
可変ビットレート(VBR) rate-control=2 可変フレームレート(VFR) fixed-framerate=false
  • ウィキベディアのH.264
ベースラインプロファイル (Baseline Profile): I, Pフレームのみ、エントロピー符号化はCAVLC+UVLCのみ
メインプロファイル (Main Profile): ベースラインプロファイルにBフレーム、CABAC、重み付け予測などを追加
ハイプロファイル (High Profile): メインプロファイルに8×8画素整数変換、量子化マトリックス等を加えたもの。

とありuvch264srcのプロパティーentropyに関係すると思われます。
プロファイルconstrained-baselineの場合はentropy=0、mainとhighの場合はentropy=1と思います。
  • nginx.conf
GStreamerからliveディレクトリにstreamというパケットを流してるので普通ならこのパケットをプレビュー用と外部サイトpush用で兼用したいところなんですが成功しません。previewに再pushしプレーヤーをpreview/streamにすると見ることが出来ます。

liveディレクトリから配信サイトにpushせずpreviewから配信サイトにpushするとタイムスタンプ同期問題が何故か解決できるのですがパケットが数分毎に途切れる問題が発生します。
  • www.confのlisten.mode = 0666
php5 (5.4.4-14+deb7u9) stable; urgency=medium
The default PHP FPM socket permission has been changed from 0666 to 0660 to mitigate security vulnerability (CVE-2014-0185) in PHP FPM that allowed any local user to run a PHP code under the active user of FPM process via crafted FastCGI client.

The default Debian setup now correctly sets the listen.owner and listen.group to www-data:www-data in default php-fpm.conf.  If you have more FPM instances or a webserver not running under www-data user you need to adjust the configuration of FPM pools in /etc/php5/fpm/pool.d/ so the accessing process has rights to access the socket.

Youtube Live

  • uvch264srcのiframe-period=3000はYoutube Liveの「4 秒以下のキーフレーム間隔を使用してください。」に影響します。iframe-periodはミリ秒単位なので4000以下にする必要があります。省略するとデフォルト値の10秒で動いてしまいYoutube Liveでエラーが発生します。
  • webインターフェイスのデフォルト値でYoutube Liveに配信すると、ライブ ダッシュボードにいくつか警告が出ます。
動画の解像度を確認してください。現在の解像度(864x480)は最適ではありません。

C920のバイトストリームをエンコードせずそのまま配信する手法でCPU使用率を下げているのでC920が吐き出しできる解像度に限定されるのが原因です。

現在のサンプルレートは 32000 です。推奨サンプルレートは 44.1kHz と 48kHz です。

C920が吐き出せるサンプルレートの限界は32000です。これを回避する方法はGStreamerでaudioresampleすることです。ただし、CPU使用率が10数パーセントに増加します。

liveスクリプトを書き換える場合
flvmux name=mux streamable=true alsasrc device=hw:0 ! \
volume volume=$VOLUME ! \
audioresample ! \
audio/x-raw,rate=44100,channels=$CHANNEL ! \
voaacenc bitrate=$ABITRATE ! \
  • Youtube Liveが推奨する解像度ごとのビットレートはこちら

その他参考


機能拡張

遠隔操作

RealVNC® Enterprise Edition の場合

※外部に公開するwebサーバーでは導入しないでください。非常に危険です。

電源、カメラ、LAN以外取り外しても遠隔で調整できるよう実運用向けにしてみます。 TightVNCなどではroot(管理者権限)が難しい作りになっています。モニターに表示するX-Windowそのままを表示してくれるx11vncを使用します。

x11vncのインストール

$ sudo apt-get install x11vnc
$ x11vnc -storepasswd
パスワードの入力
保存していいか聞かれるので「y」を選択

起動

$ x11vnc -usepw -forever

Ctrl+Cで一旦停止

自動起動設定

$ cd /home/pi/.config
$ mkdir autostart
$ cd autostart

新規作成

$ sudo leafpad x11vnc.desktop
[Desktop Entry]
Encoding=UTF-8
Type=Application
Name=X11VNC
Comment=
Exec=x11vnc -forever -display :0 -ultrafilexfer
StartupNotify=false
Terminal=false
Hidden=false

スクリーン解像度を変更する場合

$ sudo leafpad /boot/config.txt

コメントを削除して有効化

framebuffer_width=1440
framebuffer_height=900

Desktopを使用してない場合

$ sudo raspi-config
3 Enable Boot to Desktop/Scratchを選択 Desktop Login … を選択

シャットダウン

$ sudo shutdown

電源、LAN、USBカメラ以外取り外して電源入れ直し

VNCクライアントから接続してみる
クライアントパソコンにはavahiかBonjourがインストールされている必要があります。
Windowsパソコンだけ問題になりやすく、簡単な方法はiTunesをインストールすることです。
ネット検索で「Raspberry avahi Bonjour」辺りで調べると詳しい事情が出てきます。

変更履歴

  • 2016.08.02 備忘録 追記
  • 2016.01.31 オートホワイトバランス機能搭載しました。
  • 2016.01.29 LiveBot2 - 配信機能制限版 - 用意しました。
  • 2016.01.28 LiveBot2公開。v4l2-ctlをwebインターフェイスからコントロールできるようにしました。
  • 2015.12.03 タイムスタンプ同期に対応した内容に記事全体書き換えました。
  • 2015.11.19 30、24、20fpsに対応した内容に記事全体書き換えました。
  • 2015.11.13 webインターフェイスのメモ 更新
  • 2015.10.18 webインターフェイスの用意
  • 2015.10.02 VNC遠隔操作 追記
  • 2015.10.01 公開

参考

Using the Logitech C920 webcam with Gstreamer 1.2
GStreamer
nginx
nginx-rtmp-module