You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

506 lines
15 KiB

var video = document.querySelector('video');
var audio = document.querySelector('audio');
if(!navigator.getDisplayMedia && !navigator.mediaDevices.getDisplayMedia) {
var error = tr('Recording WebRTC not supported in this browser.');
$('.box-recordrtc .card-body').html(error);
throw new Error(error);
}
var isEdge = navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob);
var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
const VIDEO_STREAM_CONSTRAINTS = {
video: true,
};
const AUDIO_STREAM_CONSTRAINTS = {
audio: isEdge ? true : {
echoCancellation: false
}
};
const VIDEO_AND_AUDIO_STREAM_CONSTRAINTS = {
...AUDIO_STREAM_CONSTRAINTS,
...VIDEO_STREAM_CONSTRAINTS
};
// globally accessible
var recorder;
var microphone;
var recordingInstance;
var listOfFilesUploaded = [];
function uploadToServer(recordRTC, callback) {
var blob = recordRTC instanceof Blob ? recordRTC : recordRTC.blob;
var fileType = blob.type.split('/')[0] || 'audio';
var fileName = moment().format('YYYYMMDDhmmss');
var upload_url = document.getElementById('record-rtc-url').value;
var ticket = document.getElementById('record-rtc-ticket').value;
var customFileName = document.getElementById('record-name').value;
if (fileType === 'audio') {
fileName = customFileName ? customFileName : 'audio_record_' + fileName;
fileName += '.' + (!!navigator.mozGetUserMedia ? 'ogg' : 'wav');
} else {
fileName = customFileName ? customFileName : 'video_record_' + fileName;
fileName += '.webm';
}
// create FormData
var formData = new FormData();
formData.append(fileType + 'filename', fileName);
formData.append(fileType + 'blob', blob);
formData.append('ticket', ticket);
callback('Uploading ' + fileType + ' recording to server.');
makeXMLHttpRequest(upload_url, formData, function(progress, response) {
if (progress !== 'upload-ended') {
callback(progress);
return;
}
if (!!response) {
response = JSON.parse(response);
var fileId = response.fileId;
var thumbBox = '';
var fileUrl = '';
var nextTicket = '';
if (fileId) {
thumbBox = '{mediaplayer src="display' + fileId + '"}';
fileUrl = 'tiki-download_file.php?fileId=' + fileId;
nextTicket = response.nextTicket;
}
}
var fileData = {
'thumbBox': thumbBox,
'fileUrl': fileUrl,
'fileName': fileName,
'ticket': nextTicket
};
callback('ended', fileData, nextTicket);
// to make sure we can delete as soon as visitor leaves
listOfFilesUploaded.push(fileName);
});
}
function makeXMLHttpRequest(url, data, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState == 4) {
callback('upload-ended', request.response);
}
};
request.upload.onloadstart = function() {
callback('Upload started...');
};
request.upload.onprogress = function(event) {
callback('Upload progress ' + Math.round(event.loaded / event.total * 100) + "%");
};
request.upload.onload = function() {
callback('Upload finished');
};
request.upload.onerror = function(error) {
callback('Failed to upload to server');
console.error('XMLHttpRequest failed', error);
};
request.upload.onabort = function(error) {
callback('Upload aborted.');
console.error('XMLHttpRequest aborted', error);
};
request.open('POST', url);
request.send(data);
}
function addStreamStopListener(stream, callback) {
stream.addEventListener('ended', function() {
callback();
callback = function() {};
}, false);
stream.addEventListener('inactive', function() {
callback();
callback = function() {};
}, false);
stream.getTracks().forEach(function(track) {
track.addEventListener('ended', function() {
callback();
callback = function() {};
}, false);
track.addEventListener('inactive', function() {
callback();
callback = function() {};
}, false);
});
}
function startUpload() {
if (recorder) {
var $feedback = $('#upload-feedback span').text('Uploading... Please wait.').show();
var autoUpload = $('#record-rtc-auto-upload');
autoUpload.removeAttr('checked');
uploadToServer(recorder, function(progress, fileData, ticket) {
if(progress === 'ended') {
if (fileData.fileUrl && fileData.fileName) {
let extension = fileData.fileName.split('.').pop();
$('#record-download a').attr('href', fileData.fileUrl).text(fileData.fileName);
$('#record-download span').text('Upload finished ');
if (fileData.thumbBox) {
$('#record-download').append('<br/><code>' + fileData.thumbBox + '</code>');
}
if (ticket) {
document.getElementById('record-rtc-ticket').value = ticket;
}
recorder.destroy();
recorder = null;
} else {
$('#btn-upload-recording').show();
$('#record-download span').html('<p>Something went wrong when uploading this file. Please try again.</p>');
}
}
});
}
}
/**
* Request permissions for specific constraints related with the display.
* @param constraints
* @param onSuccess
* @param onFailure
*/
function getDisplayMedia(constraints, onSuccess, onFailure) {
if(navigator.mediaDevices.getDisplayMedia) {
navigator.mediaDevices.getDisplayMedia(constraints).then(onSuccess).catch(onFailure);
}
else {
navigator.getDisplayMedia(constraints).then(onSuccess).catch(onFailure);
}
}
/**
* Request permissions for specific constraints associated with the media input.
* @param constraints
* @param onSuccess
* @param onFailure
*/
function getUserMedia(constraints, onSuccess, onFailure) {
if(navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia(constraints).then(onSuccess).catch(onFailure);
}
else {
navigator.getUserMedia(constraints).then(onSuccess).catch(onFailure);
}
}
/**
* Show recording feedback based on currently recorded blob type
* @return void
*/
function showRecordingFeedback(recordingType) {
const blob = recorder.getBlob();
const fileType = blob.type.split('/')[0] || 'audio';
const src = URL.createObjectURL(blob);
var html = '<div>';
if (fileType === 'audio') {
html += '<br/><audio style="width: 100%; max-width: 500px" src="' + src + '" controls=""></audio>';
} else {
html += '<br/><video style="width: 100%; max-width: 500px" src="' + src + '" controls=""></video>';
}
html += '<br/><div id="record-download">' +
'<span></span>' +
'<a target="_blank" href=""></a>' +
'</div>';
html += '</div>';
var $feedback = $('#upload-feedback').show();
$feedback.html(html);
}
class RecordMicrophone {
constructor() {
if (!microphone) {
this.requestPermissions(function(mic) {
microphone = mic;
if(isSafari) {
replaceAudio();
alert('Please click startRecording button again. First time we tried to access your microphone. Now we will record it.');
}
var options = {
type: 'audio',
numberOfAudioChannels: isEdge ? 1 : 2,
checkForInactiveTracks: true,
bufferSize: 16384
};
if(isSafari || isEdge) {
options.recorderType = StereoAudioRecorder;
}
if(navigator.platform && navigator.platform.toString().toLowerCase().indexOf('win') === -1) {
options.sampleRate = 48000; // or 44100 or remove this line for default
}
if(isSafari) {
options.sampleRate = 44100;
options.bufferSize = 4096;
options.numberOfAudioChannels = 2;
}
if(recorder) {
recorder.destroy();
recorder = null;
}
recorder = RecordRTC(microphone, options);
recorder.startRecording();
$('#btn-start-recording').hide().prop('disabled', false);
$('#btn-stop-recording').show();
});
}
}
stopRecording() {
if (recorder && typeof recorder.stopRecording === "function") {
recorder.stopRecording(function() {
showRecordingFeedback();
var autoUpload = $('#record-rtc-auto-upload').is(':checked');
if (autoUpload == true) {
startUpload();
} else {
$('#btn-upload-recording').show();
}
$('#btn-start-recording').show();
$('#btn-stop-recording').hide();
microphone.stop();
microphone = null;
});
}
}
requestPermissions(callback) {
getUserMedia(AUDIO_STREAM_CONSTRAINTS, function(mic) {
callback(mic);
}, function(error) {
alert('Unable to capture your microphone. Please check console logs.');
console.error(error);
});
}
}
class RecordCameraAndAudio {
constructor() {
getUserMedia(VIDEO_AND_AUDIO_STREAM_CONSTRAINTS, function(camera) {
recorder = RecordRTC(camera, {
type: 'video'
});
recorder.startRecording();
recorder.camera = camera;
$('#btn-start-recording').hide().prop('disabled', false);
$('#btn-stop-recording').show();
}, function(error) {
alert('Unable to capture your camera. Please check console logs.');
console.error(error);
});
}
stopRecording() {
if (recorder && typeof recorder.stopRecording === "function") {
recorder.camera.stop();
recorder.stopRecording(function() {
showRecordingFeedback();
var autoUpload = $('#record-rtc-auto-upload').is(':checked');
if (autoUpload == true) {
startUpload();
} else {
$('#btn-upload-recording').show();
}
$('#btn-start-recording').show();
$('#btn-stop-recording').hide();
});
}
}
}
class RecordScreen {
constructor() {
this.requestPermissions(function (screen) {
recorder = RecordRTC(screen, {
type: 'video'
});
recorder.startRecording();
// release screen on stopRecording
recorder.screen = screen;
$('#btn-start-recording').hide().prop('disabled', false);
$('#btn-stop-recording').show();
});
}
stopRecording() {
if (recorder && typeof recorder.stopRecording === "function") {
recorder.screen.stop();
recorder.stopRecording(function() {
showRecordingFeedback();
var autoUpload = $('#record-rtc-auto-upload').is(':checked');
if (autoUpload == true) {
startUpload();
} else {
$('#btn-upload-recording').show();
}
$('#btn-start-recording').show();
$('#btn-stop-recording').hide();
});
}
}
requestPermissions(callback) {
getDisplayMedia(VIDEO_STREAM_CONSTRAINTS, function(screen) {
addStreamStopListener(screen, function() {
$('#btn-stop-recording').click();
});
callback(screen);
}, function(error) {
console.error(error);
alert('Unable to capture your screen. \n' + error);
$('#btn-start-recording').show().prop('disabled', false);
});
}
}
class RecordScreenAndMicrophone {
constructor() {
this.requestPermissions(function (screen) {
recorder = RecordRTC(screen, {
type: 'video'
});
recorder.startRecording();
// release screen on stopRecording
recorder.screen = screen;
$('#btn-start-recording').hide().prop('disabled', false);
$('#btn-stop-recording').show();
});
}
stopRecording() {
recorder.screen.stop();
if (recorder && typeof recorder.stopRecording === "function") {
recorder.stopRecording(function() {
showRecordingFeedback();
var autoUpload = $('#record-rtc-auto-upload').is(':checked');
if (autoUpload == true) {
startUpload();
} else {
$('#btn-upload-recording').show();
}
$('#btn-start-recording').show();
$('#btn-stop-recording').hide();
recorder.screen = null;
});
}
}
requestPermissions(callback) {
getDisplayMedia(VIDEO_STREAM_CONSTRAINTS, function(screen) {
getUserMedia(AUDIO_STREAM_CONSTRAINTS, function(mic) {
screen.addTrack(mic.getTracks()[0]);
addStreamStopListener(screen, function() {
$('#btn-stop-recording').click();
});
callback(screen);
});
}, function(error) {
console.error(error);
alert('Unable to capture your screen. \n' + error);
$('#btn-start-recording').show().prop('disabled', false);
});
}
}
$('#btn-start-recording').on('click', function () {
$(this).prop('disabled', true);
$('#upload-feedback').hide();
switch ($('#mod_record_rtc_recording_type').val()) {
case 'screen':
recordingInstance = new RecordScreen();
break;
case 'microphone':
recordingInstance = new RecordMicrophone();
break;
case 'screen,microphone':
recordingInstance = new RecordScreenAndMicrophone();
break;
case 'camera,microphone':
recordingInstance = new RecordCameraAndAudio();
break;
default:
console.error('Recording type not implemented.');
}
});
$('#btn-stop-recording').on('click', function(e) {
e.preventDefault();
recordingInstance.stopRecording();
});
$('#btn-upload-recording').on('click', function(e) {
e.preventDefault();
$('#btn-upload-recording').hide();
startUpload();
});
$('#mod_record_rtc_recording_type').on('change', function(e) {
$('#btn-start-recording').prop('disabled', !$(this).val());
});