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('' + fileData.thumbBox + '');
}
if (ticket) {
document.getElementById('record-rtc-ticket').value = ticket;
}
recorder.destroy();
recorder = null;
} else {
$('#btn-upload-recording').show();
$('#record-download span').html('
Something went wrong when uploading this file. Please try again.
'); } } }); } } /** * 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 = ''; 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()); });