some trials to record video

version-1
Marc Wäckerlin 8 years ago
parent 3c87e6585b
commit 7a17c7e3ca
  1. 3
      build-in-docker.conf
  2. 170
      nodejs/public/javascripts/safechat.js
  3. 23
      nodejs/views/index.ejs

@ -20,7 +20,8 @@ if test -n "${ANDROID_HOME}"; then
envs+=("-e ANDROID_HOME=${ANDROID_HOME}") envs+=("-e ANDROID_HOME=${ANDROID_HOME}")
envs+=("-e HOME=${HOME}") envs+=("-e HOME=${HOME}")
envs+=("-e TERM=xterm") envs+=("-e TERM=xterm")
envs+=("-e ANDROID_SDK_HOME=/workdir")
dirs+=("-v ${ANDROID_HOME}:${ANDROID_HOME}:ro") dirs+=("-v ${ANDROID_HOME}:${ANDROID_HOME}:ro")
dirs+=("-v ${HOME}/.gnupg:${HOME}/.gnupg:ro") dirs+=("-v ${HOME}/.gnupg:${HOME}/.gnupg:ro")
dirs+=("-v ${HOME}/.android:${HOME}/.android:ro") #dirs+=("-v ${HOME}/.android:${HOME}/.android")
fi fi

@ -42,6 +42,11 @@ var username = null; ///< username, only used during registration
var filecontent = new Array(); ///< temporary storage for attachments var filecontent = new Array(); ///< temporary storage for attachments
var socket = io.connect(); var socket = io.connect();
/// Padding for numbers in dates
function pad(n) {
return n<10 ? '0'+n : n
}
var reboottimer = null; var reboottimer = null;
/// Show error messsage /// Show error messsage
/** Fades in an error message and logs to console. /** Fades in an error message and logs to console.
@ -177,7 +182,6 @@ function backup() {
var download = document.createElement('a'); var download = document.createElement('a');
download.href = 'data:attachment/text,'+encodeURI(JSON.stringify(localStorage)); download.href = 'data:attachment/text,'+encodeURI(JSON.stringify(localStorage));
download.target = '_blank'; download.target = '_blank';
function pad(n) {return n<10 ? '0'+n : n}
var now = new Date(); var now = new Date();
download.download = download.download =
pad(now.getFullYear())+pad(now.getMonth()+1)+pad(now.getDate())+ pad(now.getFullYear())+pad(now.getMonth()+1)+pad(now.getDate())+
@ -194,7 +198,7 @@ function backup() {
/// Upload Profile Backup /// Upload Profile Backup
function restore(evt) { function restore(evt) {
if (!window.FileReader) if (!window.FileReader)
return error("your browser dows not support file upload", true); return error("your browser does not support file upload", true);
for (var i=0, f; f=evt.target.files[i]; ++i) { for (var i=0, f; f=evt.target.files[i]; ++i) {
var file = f; var file = f;
var reader = new FileReader(); var reader = new FileReader();
@ -327,10 +331,18 @@ function clearmessage() {
$("#message").prop(":disabled", false); $("#message").prop(":disabled", false);
} }
function guessfilename(mimetype, user, date) {
if (!user) user = userid();
if (!date) date = new Date();
var ext = mimetype.replace(/.*\/(x-)?/i, "");
return pad(date.getFullYear())+pad(date.getMonth()+1)+pad(date.getDate())
+"-"+ext+"-"+user+"@"+window.location.hostname+'.'+ext;
}
/// Display Image Attachments /// Display Image Attachments
function attachments(files, id) { function attachments(files, id, from, date) {
if (files) files.forEach(function(file) { if (files) files.forEach(function(file) {
console.log(file); if (!file.name) file.name = guessfilename(file.type, from, date);
var img = document.createElement('img'); var img = document.createElement('img');
img.title = file.name; img.title = file.name;
if (file.type.match('^image/')) { if (file.type.match('^image/')) {
@ -340,12 +352,106 @@ function attachments(files, id) {
} }
var a = document.createElement('a'); var a = document.createElement('a');
a.href = file.content; a.href = file.content;
a.download = file.name;
a.target = '_blank'; a.target = '_blank';
a.appendChild(img); a.appendChild(img);
$(id).append(a); $(id).append(a);
}); });
} }
// function getUserMedia() {
// return navigator.mediaDevices.getUserMedia || navigator.getUserMedia
// || navigator.webkitGetUserMedia || navigator.mozGetUserMedia
// || navigator.msGetUserMedia;
// }
var mediarecorder = null;
var mediastream = null;
function record() {
mediarecorder = mediastream.record();
}
function done() {
mediarecorder.getRecordedData(function(videoblob) {
previewfile(videoblob, "video/webm");
});
mediarecorder = null;
}
function abort() {
mediarecorder = null;
mediastream.getTracks().forEach(function(track) {track.stop()});
mediastream = null;
}
/// Record Video from builtin camera
function recordvideo() {
$("#videorecorder").show();
if (mediastream) {
mediarecorder = mediastream.record();
}
try {
navigator.mediaDevices.getUserMedia({audio: true, video: true})
.then(function(stream) {
console.log(stream);
mediastream = stream;
var video = $("#videorecorder video");
video.attr("src", window.URL.createObjectURL(mediastream));
}).catch(function() {
error("capture video failed", false);
});
} catch (e) {
console.log(e);
error("cannot access camera", true);
}
}
function previewfile(content, type, name) {
if (!name) name = guessfilename(type);
if (type.match('^image/')) {
var img = document.createElement("img");
img.onload = function() { // resize image to maximum 400px
var MAX = 400;
var width = img.width;
var height = img.height;
if (width > MAX) {
height *= MAX / width;
width = MAX;
}
if (height > MAX) {
width *= MAX / height;
height = MAX;
}
var canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
img.onload = function() {
filecontent.push({name: name, type: type, content: img.src});
$("#preview").append(img);
success('image is ready to be sent');
}
img.title = name;
img.src = canvas.toDataURL(file.type);
}
img.src=content;
} else if (type.match('^video/')) {
filecontent.push({name: name, type: type, content: content});
var video = document.createElement("video");
video.setAttribute("controls", "controls");
video.setAttribute("src", content);
video.setAttribute("title", name);
$("#preview").append(video);
} else {
filecontent.push({name: name, type: type, content: content});
var img = document.createElement("img");
img.src = "images/Document_sans_PICOL-PIctorial-COmmunication-Language.svg";
img.title = name;
$("#preview").append(img);
}
}
/// Upload Attachment /// Upload Attachment
/** Prepares attachment to be sent in a message. If the attachment is /** Prepares attachment to be sent in a message. If the attachment is
an image, it resizes the image to 400px on the lager side. an image, it resizes the image to 400px on the lager side.
@ -358,47 +464,12 @@ function fileupload(evt) {
return error("your browser does not support file upload", true); return error("your browser does not support file upload", true);
for (var i=0, f; f=evt.target.files[i]; ++i) { for (var i=0, f; f=evt.target.files[i]; ++i) {
var file = f; var file = f;
console.log(file);
var reader = new FileReader(); var reader = new FileReader();
reader.onload = function(evt) { reader.onload = function(evt) {
if (evt.target.error) return error("error reading file", true); if (evt.target.error) return error("error reading file", true);
if (evt.target.readyState==0) return notice("waiting for data …"); if (evt.target.readyState==0) return notice("waiting for data …");
if (evt.target.readyState==1) return notice("loading data …"); if (evt.target.readyState==1) return notice("loading data …");
if (file.type.match('^image/')) { previewfile(evt.target.result, file.type, file.name);
var img = document.createElement("img");
img.onload = function() {
var MAX = 400;
var width = img.width;
var height = img.height;
if (width > MAX) {
height *= MAX / width;
width = MAX;
}
if (height > MAX) {
width *= MAX / height;
height = MAX;
}
var canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
img.onload = function() {
filecontent.push({name:file.name, type: file.type, content: img.src});
$("#preview").append(img);
success('image of type '+file.type+' is ready to be sent');
}
img.title = file.name;
img.src = canvas.toDataURL(file.type);
}
img.src=evt.target.result;
} else {
filecontent.push({name:file.name, type: file.type, content: evt.target.result});
var img = document.createElement("img");
img.src = "images/Document_sans_PICOL-PIctorial-COmmunication-Language.svg";
img.title = file.name;
$("#preview").append(img);
}
} }
reader.readAsDataURL(file); reader.readAsDataURL(file);
} }
@ -491,13 +562,13 @@ function messages(msgs) {
return setTimeout(function() {emit("messages");}, 1000); // try again later return setTimeout(function() {emit("messages");}, 1000); // try again later
status("allmessages"); status("allmessages");
notice("load messages, please wait …"); notice("load messages, please wait …");
msgs.forEach(function(msg) {message(msg, false);}); msgs.forEach(function(msg) {message(msg, true);});
status("chat"); status("chat");
} }
/// Received a message from server /// Received a message from server
function message(m, signaling=true) { function message(m, internal) {
if (signaling) console.log("rcv-> message("+m.user+")"); if (!internal) console.log("rcv-> message("+m.user+")");
if (!password || !privateKey()) return; if (!password || !privateKey()) return;
var key=openpgp.key.readArmored(m.pubkey); var key=openpgp.key.readArmored(m.pubkey);
if (key.err) return error("key of sender unreadable", true); if (key.err) return error("key of sender unreadable", true);
@ -517,17 +588,19 @@ function message(m, signaling=true) {
'</span><span class="sender">'+ '</span><span class="sender">'+
'<a href="javascript:void(0)" '+ '<a href="javascript:void(0)" '+
'onclick="setreceiver(this.innerHTML)">'+ 'onclick="setreceiver(this.innerHTML)">'+
m.user+ htmlenc(m.user)+
'</a>'+(message.receiver?" → "+message.receiver:"")+ '</a>'+(message.receiver?' → <a href="javascript:void(0)" '+
'onclick="setreceiver(this.innerHTML)">'
+htmlenc(message.receiver)+'</a>':"")+
'</span></div>'+ '</span></div>'+
'<div class="text">'+ '<div class="text">'+
message.text+ htmlenc(message.text)+
'</div></div><div class="clear"/>'); '</div></div><div class="clear"/>');
// show attachments // show attachments
attachments(message.files, '#id'+m.id+' .text'); attachments(message.files, '#id'+m.id+' .text', m.user, new Date(m.time));
// calculate and show emoticons // calculate and show emoticons
$('#id'+m.id).emoticonize(); $('#id'+m.id).emoticonize();
if (signaling) beep(m.user); if (!internal) beep(m.user);
}) })
.catch(function(e) { .catch(function(e) {
// not for me // not for me
@ -593,6 +666,7 @@ function setpw(pwd) {
setpw() continues automatically. No submit is required by the setpw() continues automatically. No submit is required by the
user. */ user. */
function getpwd() { function getpwd() {
if (password) return;
$("#removeKey").show(); $("#removeKey").show();
status("getpwd"); status("getpwd");
} }

@ -50,10 +50,10 @@
<div id="newuser" style="display: none"> <div id="newuser" style="display: none">
<h2>Register User</h2> <h2>Register User</h2>
<p>All you need to start is a username and a password:</p> <p>All you need to start is a username and a password:</p>
<form id="register"> <form id="register" autocomplete="off">
<input placeholder="username" type="text" id="user"/> <input placeholder="username" autocomplete="off" type="text" id="user"/>
<input placeholder="password" type="password" id="pwd" oninput="checkpwd(this.value, document.getElementById('pwd2').value)"/> <input placeholder="password" autocomplete="off" type="password" id="pwd" oninput="checkpwd(this.value, document.getElementById('pwd2').value)"/>
<input placeholder="repeat password" type="password" id="pwd2" oninput="checkpwd(document.getElementById('pwd').value, this.value)"/> <input placeholder="repeat password" autocomplete="off" type="password" id="pwd2" oninput="checkpwd(document.getElementById('pwd').value, this.value)"/>
<input id="createuser" type="submit" disabled/> <input id="createuser" type="submit" disabled/>
</form> </form>
<script> <script>
@ -102,8 +102,8 @@
<!-- Enter Password --> <!-- Enter Password -->
<div id="getpwd" style="display: none"> <div id="getpwd" style="display: none">
<form> <form autocomplete="off">
<input placeholder="please enter password" id="pwd" oninput="setpw(this.value)" <input placeholder="please enter password" autocomplete="off" id="pwd" oninput="setpw(this.value)"
type="password" /> type="password" />
</form> </form>
</div> </div>
@ -118,11 +118,12 @@
<div class="buttongroup"> <div class="buttongroup">
<span class="toolbutton"> <span class="toolbutton">
<label for="photo"><img src="images/photo.svg"/></label> <label for="photo"><img src="images/photo.svg"/></label>
<input autocomplete="off" type="file" accept="image/*" id="photo" multiple /> <input autocomplete="off" type="file" accept="image/*" id="photo" multiple/>
</span> </span>
<span class="toolbutton"> <span class="toolbutton">
<label for="video"><img src="images/video.svg"/></label> <label for="video"><img src="images/video.svg"/></label>
<input autocomplete="off" type="file" accept="video/*" id="video"/> <input id="video" type="button" onclick="recordvideo()"/>
<!--input autocomplete="off" type="file" accept="video/*" id="video"/-->
</span> </span>
<span class="toolbutton"> <span class="toolbutton">
<label for="audio"><img src="images/audio.svg"/></label> <label for="audio"><img src="images/audio.svg"/></label>
@ -143,6 +144,12 @@
</div> </div>
</form> </form>
<div id="preview"></div> <div id="preview"></div>
<div id="videorecorder" style="display: none">
<video autoplay muted></video>
<button id="record" onclick="record()">record</button>
<button id="done" onclick="done()">done</button>
<button id="abort" onclick="abort()">abort</button>
</div>
</div> </div>
<div id="msgs"></div> <div id="msgs"></div>
<script> <script>

Loading…
Cancel
Save