Add a Record button to SLP
Posted: Wed Jun 10, 2020 8:09 pm
Add a Record button to SLP
Recording a video is rather complicated in SLP 0.2.4, 06-12 correction:0.2.3, latest image.
Next steps must be performed to start/stop recording:
There are quite a numer of changes to make. Maybe there are better and more structured ways but this implementation works.
Basically the solution consists of replacing the stereopi logo with a new button, linked to a new javascript function "toggle_recording()" (copied for a great deal from "make_photo()". I removed the stereopi logo so it can not accidentally be hit if we toggle recording state.
toggle_recording calls /var/www/html/toggle_recording.php.
Added two images to /var/www/html/imgs: record0.png and record1.png as inactive/active state image.
and
To get consistent information aboute recording state after a refesh op the main web page a link to /run/record.png is used, loop-record.sh copies active or inactive button image here depending on recording state.
The solution presented here incorporates "Unreadeable recorded video in SLP" viewtopic.php?f=10&t=965
Step-by-step instruction (mount filesystems rw first):
step1: dowload record0.png and record1.png (from the links above), place them in /var/www/html/imgs
step2: copy record0.png to /run (via ssh in live SLP system or else you will not find /run)
step3: rename /run/record0.png to /run/record.png
step4: via ssh in live SLP cd to /var/www/html/imgs and create a symlink to record0.png: ln -s record.png /run/
step5: create new file /var/www/html/toggle_recording.php with following content:step6: open /var/www/html/index.php
step7: add after following lines:(around line 58) the following:
step8: comment-out logo_icon (around line 69)
step9: I added two addition fps rates in video_fps around line 213, included here to keep line numbers in this description consistent
step10: after
(around line 525) add:
step11: after function make_photo()
(around line 607) add:
step12: save index.php
step13: open \opt\StereoPi\scripts\loop-record.sh in your favorite editor
step13: afteradd (line 7)
after
(line 27) add
add BEFORE!
(line 44) add BEFORE!
change filesink location in next block so it reads:
Step 14: save loop_record.sh
Done! reboot your StereoPi and enjoy your record button.
[*]Allthough I double-checked the correct inclusion of all changed code I think you should test it out on a copy of your SD-card. At least until I get confirmation that this description indeed works and thus is complete
From here I include all changed files, instead of copying you can also overwrite them if you trust me (or diff them with the originals) (:
/var/www/html/toggle_recording.php contents
file /var/www/html/index.php
\opt\StereoPi\scripts\loop-record.sh
Recording a video is rather complicated in SLP 0.2.4, 06-12 correction:0.2.3, latest image.
Next steps must be performed to start/stop recording:
- open settings menu
(sometimes) scroll to "Recording" checkbox
click checkbox
scroll to "Save" button
click button
click screen to dismiss settings menu
- click "Video Records" button
(sometimes) scroll to last recording
click recorded file name
- click "back"
click "back"
There are quite a numer of changes to make. Maybe there are better and more structured ways but this implementation works.
Basically the solution consists of replacing the stereopi logo with a new button, linked to a new javascript function "toggle_recording()" (copied for a great deal from "make_photo()". I removed the stereopi logo so it can not accidentally be hit if we toggle recording state.
toggle_recording calls /var/www/html/toggle_recording.php.
Added two images to /var/www/html/imgs: record0.png and record1.png as inactive/active state image.
and
To get consistent information aboute recording state after a refesh op the main web page a link to /run/record.png is used, loop-record.sh copies active or inactive button image here depending on recording state.
The solution presented here incorporates "Unreadeable recorded video in SLP" viewtopic.php?f=10&t=965
Step-by-step instruction (mount filesystems rw first):
step1: dowload record0.png and record1.png (from the links above), place them in /var/www/html/imgs
step2: copy record0.png to /run (via ssh in live SLP system or else you will not find /run)
step3: rename /run/record0.png to /run/record.png
step4: via ssh in live SLP cd to /var/www/html/imgs and create a symlink to record0.png: ln -s record.png /run/
step5: create new file /var/www/html/toggle_recording.php with following content:
Code: Select all
<?php
$path = '/media/DCIM/';
$filename = file('/run/RECFILE');
/// Load config file
$config_strings = file('/opt/StereoPi/config.conf');
/// Parse config file
$config = array();
foreach ($config_strings as $k => $v) {
$tmp = explode("=", trim($v));
$config[$tmp[0]] = $tmp[1];
/// shell_exec("echo $tmp[0] $tmp[1] >> /media/message");
}
if ($config['record_enabled'] == "0") {
$config['record_enabled'] = "1";
system("sudo cp imgs/record1.png imgs/record.png >> /dev/null 2>&1 &");
} else {
$config['record_enabled'] = "0";
system("sudo cp imgs/record0.png imgs/record.png >> /dev/null 2>&1 &");
}
$config_string = "";
foreach ($config as $k => $v ) {
$config_string = $config_string . $k . "=" . $v . "\n";
}
system("sudo killall -q sleep >> /dev/null 2>&1 &");
system("sudo killall -q rtsp-server >> /dev/null 2>&1 &");
system("sudo killall -q splitter >> /dev/null 2>&1 &");
system("sudo killall -q raspivid >> /dev/null 2>&1 &");
system("sudo killall -q gst-launch-1.0 >> /dev/null 2>&1 &");
system("sudo killall -q nodejs index.js >> /dev/null 2>&1 &");
$file = fopen('/opt/StereoPi/config.conf',"w");
fwrite($file , $config_string);
fclose($file);
$res['status'] = $config['record_enabled'];
///$res['filename'] = $filename;
$res['filename'] = $filename;
echo json_encode($res);
?>
step7: add after following lines:
Code: Select all
<body>
<canvas id="video_canvas"></canvas>
Code: Select all
<!-- JV : add record button -->
<img style="position:absolute;right:20px;top:20px;z-index:500;display:block;" id="record_icon" alt="" src="imgs/record.png" width="50" title="Toggle recording"
onclick="toggle_recording()" />
Code: Select all
<!-- JV : remove logo icon, too much chanche to hit it accidentally if we want to toggle recording
<div class="fw_hide" id="logo_icon"><a href="http://stereopi.com" target="_blank"><img src="imgs/stereopi_logo1.png" width="50" title="StereoPi site"></a></div>
JV -->
Code: Select all
<option>24</option>
<option>25</option>
Code: Select all
$('#save_button').on('click', function() {
.....
var record_time = $("#record_time").val();
Code: Select all
// JV : manage recording button state
///window.alert(document.getElementById("record_icon").src);
if (record_enabled == "0") {
document.getElementById("record_icon").src = "imgs/record0.png";
} else {
document.getElementById("record_icon").src = "imgs/record1.png";
}
Code: Select all
function make_photo() {
show_status_message('making a photo...');
. . . . .
} else {
show_status_message('failed');
}
});
}
Code: Select all
// JV : toggle recording function, most stolen from make_photo;)
function toggle_recording() {
//window.alert(document.getElementById("record_icon").src.slice(-5));
//show_status_message('toggle recording...');
$.post("toggle_recording.php", {
} , function(data) {
var json;
try {
json = JSON.parse(data);
} catch (e) {
show_status_message('failed');
return;
}
///page_reload();
if (json.status == 0) {
document.getElementById("record_icon").src = "imgs/record0.png"
show_status_message('<a href="/records/' + json.filename + '" target="_blank">' + json.filename + '</a>');
} else {
document.getElementById("record_icon").src = "imgs/record1.png"
}
})
}
step13: open \opt\StereoPi\scripts\loop-record.sh in your favorite editor
step13: after
Code: Select all
mkdir -p $RECPATH
Code: Select all
#JV create /run/record.png at startup
if [ -f ./config.conf ] ; then
. ./config.conf
fi
#JV create /run/record.png at startup
if [ "$record_enabled" = "1" ] ; then
cp /var/www/html/imgs/record1.png /run/record.png
else
cp /var/www/html/imgs/record0.png /run/record.png
fi
Code: Select all
if [ "$record_enabled" = "1" ] ; then
Code: Select all
#JV manage record button
cp /var/www/html/imgs/record1.png /run/record.png
Code: Select all
if [ "$audio_enabled" = "1" ] ; then
Code: Select all
#JV do signal here
killall -q -INT recorder
sleep 2
#JV save last vid id
RECFILE="record-`date +%Y%m%d-%H%M%S`.mp4"
echo -n $RECFILE > /run/RECFILE
echo "RECFILE = " $RECPATH/`echo -n $RECFILE`
Code: Select all
if [ "$audio_enabled" = "1" ] ; then
echo "Recording with audio"
amixer -D hw:1 set "Auto Gain Control" off
amixer -D hw:1 set "Mic" 100
#JV filesink location
#./bin/recorder -e udpsrc port=3003 buffer-size=200000 ! h264parse ! queue ! mux.video_0 alsasrc device=plughw:1,0 ! "audio/x-raw,channels=1,depth=16,width=16,rate=44100" ! voaacenc bitrate=128000 ! aacparse ! queue ! mux.audio_0 qtmux name=mux ! filesink location="$RECPATH/record-`date +%Y%m%d-%H%M%S`.mp4" sync=true
./bin/recorder -e udpsrc port=3003 buffer-size=200000 ! h264parse ! queue ! mux.video_0 alsasrc device=plughw:1,0 ! "audio/x-raw,channels=1,depth=16,width=16,rate=44100" ! voaacenc bitrate=128000 ! aacparse ! queue ! mux.audio_0 qtmux name=mux ! filesink location="$RECPATH/$RECFILE" sync=true
else
echo "Recording without audio"
#JV filesink location
#./bin/recorder -e udpsrc port=3003 buffer-size=200000 ! h264parse ! queue ! qtmux ! filesink location="$RECPATH/record-`date +%Y%m%d-%H%M%S`.mp4" sync=true
./bin/recorder -e udpsrc port=3003 buffer-size=200000 ! h264parse ! queue ! qtmux ! filesink location="$RECPATH/$RECFILE" sync=true
fi
Done! reboot your StereoPi and enjoy your record button.
[*]Allthough I double-checked the correct inclusion of all changed code I think you should test it out on a copy of your SD-card. At least until I get confirmation that this description indeed works and thus is complete
From here I include all changed files, instead of copying you can also overwrite them if you trust me (or diff them with the originals) (:
/var/www/html/toggle_recording.php contents
Code: Select all
<?php
$path = '/media/DCIM/';
$filename = file('/run/RECFILE');
/// Load config file
$config_strings = file('/opt/StereoPi/config.conf');
/// Parse config file
$config = array();
foreach ($config_strings as $k => $v) {
$tmp = explode("=", trim($v));
$config[$tmp[0]] = $tmp[1];
/// shell_exec("echo $tmp[0] $tmp[1] >> /media/message");
}
if ($config['record_enabled'] == "0") {
$config['record_enabled'] = "1";
system("sudo cp imgs/record1.png imgs/record.png >> /dev/null 2>&1 &");
} else {
$config['record_enabled'] = "0";
system("sudo cp imgs/record0.png imgs/record.png >> /dev/null 2>&1 &");
}
$config_string = "";
foreach ($config as $k => $v ) {
$config_string = $config_string . $k . "=" . $v . "\n";
}
system("sudo killall -q sleep >> /dev/null 2>&1 &");
system("sudo killall -q rtsp-server >> /dev/null 2>&1 &");
system("sudo killall -q splitter >> /dev/null 2>&1 &");
system("sudo killall -q raspivid >> /dev/null 2>&1 &");
system("sudo killall -q gst-launch-1.0 >> /dev/null 2>&1 &");
system("sudo killall -q nodejs index.js >> /dev/null 2>&1 &");
/// $file = fopen('/media/config.conf',"w");
$file = fopen('/opt/StereoPi/config.conf',"w");
fwrite($file , $config_string);
fclose($file);
//JV
//sleep (3);
//system("sudo killall -q -INT recorder >> /dev/null 2>&1 &");
$res['status'] = $config['record_enabled'];
///$res['filename'] = $filename;
$res['filename'] = $filename;
echo json_encode($res);
?>
Code: Select all
<html>
<head>
<title>StereoPi : <?php echo $_SERVER['SERVER_ADDR']; ?></title>
<link rel="apple-touch-icon" sizes="57x57" href="/icons/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/icons/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/icons/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/icons/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/icons/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/icons/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/icons/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/icons/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="/icons/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/icons/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/icons/favicon-16x16.png">
<link rel="manifest" href="/icons/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/icons/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
</head>
<style>
html,body {background-color:white; padding:0; margin:0; width:100%; height:100%; font-family:Arial; -webkit-user-select: none; -moz-user-select: -moz-none; -ms-user-select: none; user-select: none;}
#version_block { position:absolute; bottom:10px; left:10px; font-color:black; font-family:Arial;}
#video_canvas {width:100%; height:100%; background-image:url(imgs/stereopi_bg2.jpg); background-repeat:no-repeat; background-size:contain; background-position: 50% 50%;}
#settings_window { position:absolute; left:0px; top:0px; bottom:0px; width:0px; background-color:black; display:block; overflow:hidden; color:white; z-index:510 }
#toggle_settings { position:absolute;left:20px;top:20px;z-index:500;display:block; }
#photo_icon { position:absolute;left:25px;top:100px;z-index:500;display:block; }
#records_icon { position:absolute;left:25px;top:180px;z-index:500;display:block; }
#filemanager_icon { position:absolute;left:25px;top:260px;z-index:500;display:block; }
#console_icon { position:absolute;left:25px;top:340px;z-index:500;display:block; }
#fwupdate_icon { position:absolute;left:25px;top:420px;z-index:500;display:block; }
#logo_icon { position:absolute;right:20px;top:20px;z-index:500;display:block; }
.input_box { padding:4px 10px 4px 4px;}
input, select { padding:4px 10px 4px 4px; }
#hellomessage { position:absolute; top:10%; left:30%; right:30%; width:auto; height:auto; margin:0; padding:10px; text-align:center; color:white; background-color:gray; font-size:1.4em; display:none; }
#status_message { position:absolute; top:20px; left:220px; padding:5px; display:none; color:white; background-color:black; }
#status_message a { color:white; }
::-webkit-scrollbar {
width: 0px; /* remove scrollbar space */
background: transparent; /* optional: just make scrollbar invisible */
}
/* optional: show position indicator in red */
::-webkit-scrollbar-thumb {
background: #FF0000;
}
</style>
<body>
<canvas id="video_canvas"></canvas>
<!-- JV : add record button -->
<img style="position:absolute;right:20px;top:20px;z-index:500;display:block;" id="record_icon" alt="" src="imgs/record.png" width="50" title="Toggle recording"
onclick="toggle_recording()" />
<div class="fw_hide" id="version_block">
<?php
echo 'version ' . file_get_contents('/opt/StereoPi/version');
?>
</div>
<!-- JV : remove logo icon, too much chanche to hit it accidentally if we want to toggle recording
<div class="fw_hide" id="logo_icon"><a href="http://stereopi.com" target="_blank"><img src="imgs/stereopi_logo1.png" width="50" title="StereoPi site"></a></div>
JV -->
<input class="fw_hide" id="toggle_settings" type="image" src="imgs/settings1.png" width="50" title="Settings"/>
<div class="fw_hide" id="photo_icon"><a href="#" onclick="make_photo(); return false;"><img src="imgs/photo1.png" width="50" title="Make a photo"></a></div>
<div class="fw_hide" id="records_icon"><a href="/records"><img src="imgs/files1.png" width="50" title="Video records"></a></div>
<div class="fw_hide" id="filemanager_icon"><a href="/files"><img src="imgs/filemanager1.png" width="50" title="File manager"></a></div>
<div class="fw_hide" id="console_icon"><a href="/console"><img src="imgs/console1.png" width="50" title="Console"></a></div>
<div class="fw_hide" id="fwupdate_icon"><a href="/update.html"><img src="imgs/firmware_update1.png" width="50" title="Firmware update"></a></div>
<div class="fw_hide" id="status_message"></div>
<div id="settings_window">
<div style="height:100%; padding:20px; overflow:auto; y-scroll:hidden;">
<p>
Image mode
<select id="video_mode" style="width:100%;">
<option>2D</option>
<option>3D</option>
</select>
</p>
<p>
<input type="checkbox" id="updown_enabled"><label for="updown_enabled">Upside/down</label>
</p>
<p>
<input type="checkbox" id="swapcams_enabled"><label for="swapcams_enabled">Swap cams</label>
</p>
<p>
Photo resolution
<select id="photo_resolution" style="width:100%;">
<option>default</option>
<option>V1-full-size</option>
<option>V2-full-size</option>
</select>
</p>
<p>
Video resolution
<select id="video_resolution" style="width:100%;">
<option>640x480</option>
<option>1280x600</option>
<option>1280x720</option>
<option>1280x800</option>
<option>1280x960</option>
<option>1640x922</option>
<option>1920x1080</option>
</select>
</p>
<p> </p>
<hr />
<p style="color:yellow;">Rec settings</p>
<p>
<input type="checkbox" id="record_enabled"><label for="record_enabled">Recording</label>
</p>
<p>
Max rec duration
<select id="record_time" style="width:100%;">
<option value="30">30 sec</option>
<option value="60">1 min</option>
<option value="300">5 min</option>
<option value="600">10 min</option>
<option value="1200">20 min</option>
<option value="1800">30 min</option>
</select>
</p>
<p> </p>
<hr />
<p style="color:yellow;">Stream settings</p>
<p>
<input type="checkbox" id="ws_enabled"><label for="ws_enabled">Browser stream</label>
</p>
<p>
<input type="checkbox" id="udp_enabled"><label for="udp_enabled">Stream UDP</label>
</p>
<p>
UDP clients
<input type="text" id="udp_clients" class="input_box" style="width:100%;"/>
</p>
<p>
<input type="checkbox" id="usb_enabled"><label for="usb_enabled">USB enabled</label>
</p>
<p>
<input type="checkbox" id="rtmp_enabled"><label for="rtmp_enabled">RTMP enabled</label>
</p>
<p>
<input type="checkbox" id="audio_switch"><label for="audio_switch">Audio enabled</label>
</p>
<p>
RTMP URL
<input type="text" id="rtmp_url" class="input_box" style="width:100%;"/>
</p>
<p>
<input type="checkbox" id="mpegts_enabled"><label for="mpegts_enabled">MPEG-TS enabled</label>
</p>
<p>
MPEG-TS clients
<input type="text" id="mpegts_clients" class="input_box" style="width:100%;"/>
</p>
<p>
<input type="checkbox" id="rtsp_enabled"><label for="rtsp_enabled">RTSP enabled</label> <br>
<p style="color:gray;">All other streams disabled when RTSP enabled!</p>
<p><a href="rtsp://<?php echo $_SERVER['SERVER_ADDR'];?>:554/h264" target="_blank">RTSP link</a></p>
</p>
<p> </p>
<hr />
<p style="color:yellow;">Video settings</p>
<p>
<input type="checkbox" id="dec_enabled"><label for="dec_enabled">Decimation</label>
</p>
<p>
FPS
<select id="video_fps" style="width:100%;">
<option>10</option>
<option>20</option>
<option>24</option>
<option>25</option>
<option>30</option>
<option>40</option>
<option>42</option>
<option>48</option>
<option>60</option>
<option>90</option>
</select>
</p>
<p>
Bitrate
<select id="video_bitrate" style="width:100%;">
<option>500000</option>
<option>1000000</option>
<option>2000000</option>
<option>3000000</option>
<option>4000000</option>
<option>5000000</option>
<option>6000000</option>
<option>7000000</option>
<option>8000000</option>
<option>9000000</option>
<option>10000000</option>
</select>
</p>
<p>
Profile
<select id="video_profile" style="width:100%;">
<option>baseline</option>
<option>main</option>
<option>high</option>
</select>
</p>
<p>
White balance
<select id="video_wb" style="width:100%;">
<option>off</option>
<option>auto</option>
<option>sun</option>
<option>cloud</option>
<option>shade</option>
<option>tungsten</option>
<option>fluorescent</option>
<option>incandescent</option>
<option>flash</option>
<option>horizon</option>
</select>
</p>
<p>
Exposure
<select id="exposure" style="width:100%;">
<option>off</option>
<option>auto</option>
<option>night</option>
<option>nightpreview</option>
<option>backlight</option>
<option>spotlight</option>
<option>sports</option>
<option>snow</option>
<option>beach</option>
<option>verylong</option>
<option>fixedfps</option>
<option>antishake</option>
<option>fireworks</option>
</select>
</p>
<p>
Contrast
<select id="contrast" style="width:100%;">
<option>100</option>
<option>90</option>
<option>80</option>
<option>70</option>
<option>60</option>
<option>50</option>
<option>40</option>
<option>30</option>
<option>20</option>
<option>15</option>
<option>10</option>
<option>5</option>
<option>0</option>
<option>-5</option>
<option>-10</option>
<option>-15</option>
<option>-20</option>
<option>-30</option>
<option>-40</option>
<option>-50</option>
<option>-60</option>
<option>-70</option>
<option>-80</option>
<option>-90</option>
<option>-100</option>
</select>
</p>
<p>
Sharpness
<select id="sharpness" style="width:100%;">
<option>100</option>
<option>90</option>
<option>80</option>
<option>70</option>
<option>60</option>
<option>50</option>
<option>40</option>
<option>30</option>
<option>20</option>
<option>15</option>
<option>10</option>
<option>5</option>
<option>0</option>
<option>-5</option>
<option>-10</option>
<option>-15</option>
<option>-20</option>
<option>-30</option>
<option>-40</option>
<option>-50</option>
<option>-60</option>
<option>-70</option>
<option>-80</option>
<option>-90</option>
<option>-100</option>
</select>
</p>
<p>
Digital gain
<select id="digitalgain" style="width:100%;">
<option>10.0</option>
<option>9.0</option>
<option>8.0</option>
<option>7.0</option>
<option>6.0</option>
<option>5.0</option>
<option>4.0</option>
<option>3.0</option>
<option>2.0</option>
<option>1.5</option>
<option>1.0</option>
<option>0.5</option>
<option>0.0</option>
<option>-0.5</option>
<option>-1.0</option>
<option>-1.5</option>
<option>-2.0</option>
<option>-3.0</option>
<option>-4.0</option>
<option>-5.0</option>
<option>-6.0</option>
<option>-7.0</option>
<option>-8.0</option>
<option>-9.0</option>
<option>-10.0</option>
</select>
</p>
<p> </p>
<hr/>
<p style="color:yellow;">Wi-Fi settings</p>
<p>
Wi-Fi interface
<select id="wifi_iface" style="width:100%;">
<option></option>
<option>wifi0</option>
<option>wlan0</option>
<option>wlan1</option>
</select>
</p>
<p>
Wi-Fi SSID
<input type="text" id="wifi_ssid" class="input_box" style="width:100%;"/>
</p>
<p>
Wi-Fi password
<input type="password" id="wifi_psk" class="input_box" style="width:100%;"/>
</p>
<p> </p>
<hr />
<p>
<input type="button" id="save_button" value="Save" style="width:100%;background-color:lightgreen;">
</p>
<p> </p>
<p> </p>
</div>
</div>
<div id="hellomessage">Double tap for fullsreen toggle</div>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/http-live-player.js">;</script>
<script type="text/javascript" src="js/player.js">;</script>
<script type="text/javascript" src="js/screen.js">;</script>
<script type="text/javascript">
$('#toggle_settings').on('click', function(){
toggle_settings_window();
});
function is_settings_opened() {
var state = $("#settings_window").css("width") == "0px" ? false : true;
return state;
}
function toggle_settings_window() {
if (!is_settings_opened()) {
load_config();
$('#toggle_settings').css("display","none");
$("#settings_window").animate({width:"200px"}, 100);
} else {
$("#settings_window").animate({width:"0px"}, 100);
$('#toggle_settings').css("display","block");
}
}
function load_config() {
$.post("getconfig.php", function( data ) {
parse_config(data);
});
}
function parse_config(data) {
var json;
try {
json = JSON.parse(data);
} catch (e) { return; }
$("#photo_resolution").val(json.photo_resolution);
$("#video_resolution").val(json.video_width + "x" + json.video_height);
$("#video_mode").val(json.video_mode);
$("#video_fps").val(json.video_fps);
$("#video_bitrate").val(json.video_bitrate);
$("#video_profile").val(json.video_profile);
$("#rtmp_url").val(json.rtmp_url);
$("#audio_switch").prop( "checked", json.audio_enabled == "1" ? true : false);
$("#rtmp_enabled").prop( "checked", json.rtmp_enabled == "1" ? true : false);
$("#mpegts_enabled").prop( "checked", json.mpegts_enabled == "1" ? true : false);
$("#mpegts_clients").val(json.mpegts_clients);
$("#rtsp_enabled").prop( "checked", json.rtsp_enabled == "1" ? true : false);
$("#usb_enabled").prop( "checked", json.usb_enabled == "1" ? true : false);
$("#video_wb").val(json.video_wb);
$("#exposure").val(json.exposure);
$("#sharpness").val(json.sharpness);
$("#contrast").val(json.contrast);
$("#digitalgain").val(json.digitalgain);
$("#wifi_iface").val(json.wifi_iface);
$("#wifi_ssid").val(json.wifi_ssid);
$("#wifi_psk").val(json.wifi_psk);
$("#record_enabled").prop( "checked", json.record_enabled == "1" ? true : false);
$("#dec_enabled").prop( "checked", json.dec_enabled == "1" ? true : false);
$("#updown_enabled").prop( "checked", json.up_down == "1" ? true : false);
$("#swapcams_enabled").prop( "checked", json.swapcams == "1" ? true : false);
$("#udp_enabled").prop( "checked", json.udp_enabled == "1" ? true : false);
$("#ws_enabled").prop( "checked", json.ws_enabled == "1" ? true : false);
$("#udp_clients").val(json.udp_clients);
$("#record_time").val(json.record_time);
}
$('#save_button').on('click', function() {
var photo_resolution = $("#photo_resolution").val();
var video_resolution = $("#video_resolution").val();
var video_mode = $("#video_mode").val();
var video_width = video_resolution.split('x')[0];
var video_height = video_resolution.split('x')[1];
var video_fps = $("#video_fps").val();
var video_bitrate = $("#video_bitrate").val();
var video_profile = $("#video_profile").val();
var rtmp_url = $("#rtmp_url").val();
var audio_enabled = $("#audio_switch").prop("checked") ? "1" : "0";
var rtmp_enabled = $("#rtmp_enabled").prop("checked") ? "1" : "0";
var mpegts_clients = $("#mpegts_clients").val();
var mpegts_enabled = $("#mpegts_enabled").prop("checked") ? "1" : "0";
var rtsp_enabled = $("#rtsp_enabled").prop("checked") ? "1" : "0";
var usb_enabled = $("#usb_enabled").prop("checked") ? "1" : "0";
var video_wb = $("#video_wb").val();
var exposure = $("#exposure").val();
var contrast = $("#contrast").val();
var sharpness = $("#sharpness").val();
var digitalgain = $("#digitalgain").val();
var wifi_iface = $("#wifi_iface").val();
var wifi_ssid = $("#wifi_ssid").val();
var wifi_psk = $("#wifi_psk").val();
var record_enabled = $("#record_enabled").prop("checked") ? "1" : "0";
var dec_enabled = $("#dec_enabled").prop("checked") ? "1" : "0";
var updown_enabled = $("#updown_enabled").prop("checked") ? "1" : "0";
var swapcams_enabled = $("#swapcams_enabled").prop("checked") ? "1" : "0";
var udp_enabled = $("#udp_enabled").prop("checked") ? "1" : "0";
var ws_enabled = $("#ws_enabled").prop("checked") ? "1" : "0";
var udp_clients = $("#udp_clients").val();
var record_time = $("#record_time").val();
// JV : manage recording button state
///window.alert(document.getElementById("record_icon").src);
if (record_enabled == "0") {
document.getElementById("record_icon").src = "imgs/record0.png";
} else {
document.getElementById("record_icon").src = "imgs/record1.png";
}
/// Only baseline profile available if WebSockets enabled
if (ws_enabled == "1") {
if (video_profile != "baseline") {
alert('Only "baseline" profile allowed if "Browser stream" enabled');
return;
}
}
$.post("saveconfig.php", {
photo_resolution:photo_resolution,
video_width:video_width,
video_mode:video_mode,
video_height:video_height,
video_fps:video_fps,
video_bitrate:video_bitrate,
video_profile:video_profile,
rtmp_url:rtmp_url,
rtmp_enabled:rtmp_enabled,
mpegts_clients:mpegts_clients,
mpegts_enabled:mpegts_enabled,
rtsp_enabled:rtsp_enabled,
usb_enabled:usb_enabled,
audio_enabled:audio_enabled,
video_wb:video_wb,
exposure:exposure,
contrast:contrast,
sharpness:sharpness,
digitalgain:digitalgain,
wifi_iface:wifi_iface,
wifi_ssid:wifi_ssid,
wifi_psk:wifi_psk,
record_enabled:record_enabled,
record_time:record_time,
dec_enabled:dec_enabled,
up_down:updown_enabled,
swapcams:swapcams_enabled,
udp_clients:udp_clients,
udp_enabled:udp_enabled,
ws_enabled:ws_enabled
} , function(data) {
if (data != "") alert(data);
});
});
function page_reload() {
location.reload();
}
function make_photo() {
show_status_message('making a photo...');
$.post("make_photo.php", {
} , function(data) {
var json;
try {
json = JSON.parse(data);
} catch (e) {
show_status_message('failed');
return;
}
if (json.status == 0) {
show_status_message('<a href="/records/' + json.filename + '" target="_blank">' + json.filename + '</a>');
} else {
show_status_message('failed');
}
});
}
// JV : toggle recording function, most stolen from make_photo;)
function toggle_recording() {
//window.alert(document.getElementById("record_icon").src.slice(-5));
//show_status_message('toggle recording...');
$.post("toggle_recording.php", {
} , function(data) {
var json;
try {
json = JSON.parse(data);
} catch (e) {
show_status_message('failed');
return;
}
///page_reload();
if (json.status == 0) {
document.getElementById("record_icon").src = "imgs/record0.png"
show_status_message('<a href="/records/' + json.filename + '" target="_blank">' + json.filename + '</a>');
} else {
document.getElementById("record_icon").src = "imgs/record1.png"
}
})
}
function show_status_message(message) {
if (message != null) {
$('#status_message').css('display', 'block');
$('#status_message').html(message);
} else {
$('#status_message').css('display', 'none');
$('#status_message').html('');
}
}
</script>
</body>
</html>
Code: Select all
#!/bin/sh
RECPATH=/media/DCIM
mkdir -p $RECPATH
#JV create /run/record.png at startup
if [ -f ./config.conf ] ; then
. ./config.conf
fi
if [ "$record_enabled" = "1" ] ; then
cp /var/www/html/imgs/record1.png /run/record.png
else
cp /var/www/html/imgs/record0.png /run/record.png
fi
while [ 1 ] ; do
if [ -f ./config.conf ] ; then
. ./config.conf
else
sleep 1
continue
fi
if [ "$record_enabled" = "1" ] ; then
#JV manage record button
cp /var/www/html/imgs/record1.png /run/record.png
echo "Recording enabled"
else
sleep 1
continue
fi
#JV do signal here
killall -q -INT recorder
sleep 2
#JV save last vid id
RECFILE="record-`date +%Y%m%d-%H%M%S`.mp4"
echo -n $RECFILE > /run/RECFILE
echo "RECFILE = " $RECPATH/`echo -n $RECFILE`
if [ "$audio_enabled" = "1" ] ; then
echo "Recording with audio"
amixer -D hw:1 set "Auto Gain Control" off
amixer -D hw:1 set "Mic" 100
#JV filesink location
#./bin/recorder -e udpsrc port=3003 buffer-size=200000 ! h264parse ! queue ! mux.video_0 alsasrc device=plughw:1,0 ! "audio/x-raw,channels=1,depth=16,width=16,rate=44100" ! voaacenc bitrate=128000 ! aacparse ! queue ! mux.audio_0 qtmux name=mux ! filesink location="$RECPATH/record-`date +%Y%m%d-%H%M%S`.mp4" sync=true
./bin/recorder -e udpsrc port=3003 buffer-size=200000 ! h264parse ! queue ! mux.video_0 alsasrc device=plughw:1,0 ! "audio/x-raw,channels=1,depth=16,width=16,rate=44100" ! voaacenc bitrate=128000 ! aacparse ! queue ! mux.audio_0 qtmux name=mux ! filesink location="$RECPATH/$RECFILE" sync=true
else
echo "Recording without audio"
#JV filesink location
#./bin/recorder -e udpsrc port=3003 buffer-size=200000 ! h264parse ! queue ! qtmux ! filesink location="$RECPATH/record-`date +%Y%m%d-%H%M%S`.mp4" sync=true
./bin/recorder -e udpsrc port=3003 buffer-size=200000 ! h264parse ! queue ! qtmux ! filesink location="$RECPATH/$RECFILE" sync=true
fi
echo "Recording stopped"
sleep 1
done