diff --git a/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-debug.js b/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-debug.js
index 99deb5de7b1..49291def9df 100644
--- a/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-debug.js
+++ b/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-debug.js
@@ -189,9 +189,31 @@ M.atto_recordrtc.commonmodule = {
}
},
+ getFileExtension: function(type) {
+ if (type === 'audio') {
+ if (window.MediaRecorder.isTypeSupported('audio/webm')) {
+ return 'webm';
+ } else if (window.MediaRecorder.isTypeSupported('audio/ogg')) {
+ return 'ogg';
+ } else if (window.MediaRecorder.isTypeSupported('audio/mp4')) {
+ return 'mp4';
+ }
+ } else {
+ if (window.MediaRecorder.isTypeSupported('audio/webm')) {
+ return 'webm';
+ } else if (window.MediaRecorder.isTypeSupported('audio/mp4')) {
+ return 'mp4';
+ }
+ }
+
+ window.console.warning('Unknown file type for MediaRecorder API');
+ return '';
+ },
+
// Upload recorded audio/video to server.
upload_to_server: function(type, callback) {
var xhr = new window.XMLHttpRequest();
+ var fileExtension = this.getFileExtension(type);
// Get src media of audio/video tag.
xhr.open('GET', cm.player.get('src'), true);
@@ -204,8 +226,8 @@ M.atto_recordrtc.commonmodule = {
// Generate filename with random ID and file extension.
var fileName = (Math.random() * 1000).toString().replace('.', '');
- fileName += (type === 'audio') ? '-audio.ogg'
- : '-video.webm';
+ fileName += (type === 'audio') ? '-audio.' + fileExtension
+ : '-video.' + fileExtension;
// Create FormData to send to PHP filepicker-upload script.
var formData = new window.FormData(),
@@ -471,17 +493,35 @@ M.atto_recordrtc.abstractmodule = {
if (recType === 'audio') {
types = [
+ // Firefox and Chrome both support webm and ogg.
'audio/webm;codecs=opus',
- 'audio/ogg;codecs=opus'
+ 'audio/ogg;codecs=opus',
+
+ // Safari supports mp4.
+ 'audio/mp4;codecs=opus',
+ 'audio/mp4;codecs=wav',
+ 'audio/mp4;codecs=mp3',
];
options = {
audioBitsPerSecond: window.parseInt(cm.editorScope.get('audiobitrate'))
};
} else {
types = [
+ // Support webm as a preference.
+ // This container supports both vp9, and vp8.
+ // It does not support AVC1/h264 at all.
+ // It is supported by Chromium, and Firefox browsers, but not Safari.
'video/webm;codecs=vp9,opus',
- 'video/webm;codecs=h264,opus',
- 'video/webm;codecs=vp8,opus'
+ 'video/webm;codecs=vp8,opus',
+
+ // Fall back to mp4 if webm is not available.
+ // The mp4 container supports v9, and h264 but neither of these are supported for recording on other
+ // browsers.
+ // In addition to this, we can record in v9, but VideoJS does not support an mp4 containern with v9 codec
+ // for playback. We leave it as a final option as a just-in-case.
+ 'video/mp4;codecs=h264,opus',
+ 'video/mp4;codecs=h264,wav',
+ 'video/mp4;codecs=v9,opus',
];
options = {
audioBitsPerSecond: window.parseInt(cm.editorScope.get('audiobitrate')),
@@ -489,7 +529,15 @@ M.atto_recordrtc.abstractmodule = {
};
}
- var compatTypes = types.filter(function(type) {
+ var possibleTypes = types.reduce(function(result, type) {
+ result.push(type);
+ // Safari seems to use codecs: instead of codecs=.
+ // It is safe to add both, so we do, but we want them to remain in order.
+ result.push(type.replace('=', ':'));
+ return result;
+ }, []);
+
+ var compatTypes = possibleTypes.filter(function(type) {
return window.MediaRecorder.isTypeSupported(type);
});
diff --git a/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-min.js b/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-min.js
index 0e1b89f5301..60ff8868aee 100644
--- a/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-min.js
+++ b/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-min.js
@@ -1,2 +1,2 @@
-YUI.add("moodle-atto_recordrtc-recording",function(r,t){var s,n,e;M.atto_recordrtc=M.atto_recordrtc||{},s=M.atto_recordrtc.commonmodule,n=M.atto_recordrtc.abstractmodule,M.atto_recordrtc.commonmodule={editorScope:null,alertWarning:null,alertDanger:null,player:null,playerDOM:null,startStopBtn:null,uploadBtn:null,countdownSeconds:null,countdownTicker:null,recType:null,stream:null,mediaRecorder:null,chunks:null,blobSize:null,maxUploadSize:null,capture_user_media:function(t,e,o){window.navigator.mediaDevices.getUserMedia(t).then(e)["catch"](o)},handle_data_available:function(t){s.chunks.push(t.data),s.blobSize+=t.data.size,s.blobSize>=s.maxUploadSize&&(window.localStorage.getItem("alerted")?window.localStorage.removeItem("alerted"):(window.localStorage.setItem("alerted","true"),s.startStopBtn.simulate("click"),n.show_alert("nearingmaxsize")),s.chunks.pop())},handle_stop:function(){var t=new window.Blob(s.chunks,{type:s.mediaRecorder.mimeType});s.player.set("srcObject",null),s.player.set("src",window.URL.createObjectURL(t)),s.player.set("muted",!1),s.player.set("controls",!0),s.player.ancestor().ancestor().removeClass("hide"),s.uploadBtn.ancestor().ancestor().removeClass("hide"),s.uploadBtn.set("textContent",M.util.get_string("attachrecording","atto_recordrtc")),s.uploadBtn.set("disabled",!1),s.editorScope.getDialogue().centered(),s.uploadBtn.on("click",function(){0===s.chunks.length?n.show_alert("norecordingfound"):(s.uploadBtn.set("disabled",!0),s.upload_to_server(s.recType,function(t,e){"ended"===t?(s.uploadBtn.set("disabled",!1),s.insert_annotation(s.recType,e)):"upload-failed"===t?(s.uploadBtn.set("disabled",!1),s.uploadBtn.set("textContent",M.util.get_string("uploadfailed","atto_recordrtc")+" "+e)):"upload-failed-404"===t?(s.uploadBtn.set("disabled",!1),s.uploadBtn.set("textContent",M.util.get_string("uploadfailed404","atto_recordrtc"))):"upload-aborted"===t?(s.uploadBtn.set("disabled",!1),s.uploadBtn.set("textContent",M.util.get_string("uploadaborted","atto_recordrtc")+" "+e)):s.uploadBtn.set("textContent",t)}))})},start_recording:function(t,e){var o=n.select_rec_options(t);s.mediaRecorder=new window.MediaRecorder(e,o),s.mediaRecorder.ondataavailable=s.handle_data_available,s.mediaRecorder.onstop=s.handle_stop,s.mediaRecorder.start(1e3),s.player.set("muted",!0),s.countdownSeconds="audio"===t?s.editorScope.get("audiotimelimit"):"video"===t?s.editorScope.get("videotimelimit"):s.editorScope.get("defaulttimelimit"),s.countdownSeconds++,e=M.util.get_string("stoprecording","atto_recordrtc"),s.startStopBtn.setHTML(e+=' (:)'),s.set_time(),s.countdownTicker=window.setInterval(s.set_time,1e3),s.startStopBtn.set("disabled",!1)},stop_recording:function(t){var e,o;for(s.mediaRecorder.stop(),e=t.getTracks(),o=0;o":"")},insert_annotation:function(t,e){t=s.create_annotation(t,e);t?s.editorScope.setLink(s.editorScope,t):s.uploadBtn.set("textContent",M.util.get_string("attachrecording","atto_recordrtc"))}},M.atto_recordrtc=M.atto_recordrtc||{},s=M.atto_recordrtc.commonmodule,n=M.atto_recordrtc.abstractmodule,M.atto_recordrtc.compatcheckmodule={check_has_gum:function(){navigator.mediaDevices&&window.MediaRecorder||n.show_alert("nowebrtc",function(){s.editorScope.closeDialogue(s.editorScope)})},check_secure:function(){"https:"===window.location.protocol||-1!==window.location.host.indexOf("localhost")||s.alertDanger.ancestor().ancestor().removeClass("hide")}},M.atto_recordrtc=M.atto_recordrtc||{},s=M.atto_recordrtc.commonmodule,n=M.atto_recordrtc.abstractmodule,M.atto_recordrtc.abstractmodule={show_alert:function(e,o){r.use("moodle-core-notification-alert",function(){var t=new M.core.alert({title:M.util.get_string(e+"_title","atto_recordrtc"),message:M.util.get_string(e,"atto_recordrtc")});o&&t.after("complete",o)})},handle_gum_errors:function(t,e){var o=M.util.get_string("recordingfailed","atto_recordrtc"),r=function(){e.onMediaStopped(o)},t="gum"+t.name.replace("Error","").toLowerCase();"gumsecurity"!=t?n.show_alert(t,r):n.show_alert(t,function(){s.editorScope.closeDialogue(s.editorScope)})},
-select_rec_options:function(t){var t="audio"===t?(e=["audio/webm;codecs=opus","audio/ogg;codecs=opus"],{audioBitsPerSecond:window.parseInt(s.editorScope.get("audiobitrate"))}):(e=["video/webm;codecs=vp9,opus","video/webm;codecs=h264,opus","video/webm;codecs=vp8,opus"],{audioBitsPerSecond:window.parseInt(s.editorScope.get("audiobitrate")),videoBitsPerSecond:window.parseInt(s.editorScope.get("videobitrate"))}),e=e.filter(function(t){return window.MediaRecorder.isTypeSupported(t)});return 0!==e.length&&(t.mimeType=e[0]),t}},M.atto_recordrtc=M.atto_recordrtc||{},s=M.atto_recordrtc.commonmodule,n=M.atto_recordrtc.abstractmodule,e=M.atto_recordrtc.compatcheckmodule,M.atto_recordrtc.audiomodule={init:function(t){s.editorScope=t,s.alertWarning=r.one("div#alert-warning"),s.alertDanger=r.one("div#alert-danger"),s.player=r.one("audio#player"),s.playerDOM=document.querySelector("audio#player"),s.startStopBtn=r.one("button#start-stop"),s.uploadBtn=r.one("button#upload"),s.recType="audio",s.maxUploadSize=t.get("maxrecsize"),e.check_has_gum(),e.check_secure(),s.startStopBtn.on("click",function(){var e;s.startStopBtn.set("disabled",!0),s.startStopBtn.get("textContent")===M.util.get_string("startrecording","atto_recordrtc")||s.startStopBtn.get("textContent")===M.util.get_string("recordagain","atto_recordrtc")||s.startStopBtn.get("textContent")===M.util.get_string("recordingfailed","atto_recordrtc")?(s.player.ancestor().ancestor().addClass("hide"),s.uploadBtn.ancestor().ancestor().addClass("hide"),s.startStopBtn.replaceClass("btn-outline-danger","btn-danger"),s.chunks=[],s.blobSize=0,s.uploadBtn.detach("click"),e={onMediaCaptured:function(t){s.stream=t,s.start_recording(s.recType,s.stream)},onMediaStopped:function(t){s.startStopBtn.set("textContent",t),s.startStopBtn.set("disabled",!1),s.startStopBtn.replaceClass("btn-danger","btn-outline-danger")},onMediaCapturingFailed:function(t){n.handle_gum_errors(t,e)}},M.atto_recordrtc.audiomodule.capture_audio(e)):(window.clearInterval(s.countdownTicker),window.setTimeout(function(){s.startStopBtn.set("disabled",!1)},1e3),s.stop_recording(s.stream),s.startStopBtn.set("textContent",M.util.get_string("recordagain","atto_recordrtc")),s.startStopBtn.replaceClass("btn-danger","btn-outline-danger")),s.editorScope.getDialogue().centered()})},capture_audio:function(e){s.capture_user_media({audio:!0},function(t){s.playerDOM.srcObject=t,e.onMediaCaptured(t)},function(t){e.onMediaCapturingFailed(t)})}},M.atto_recordrtc=M.atto_recordrtc||{},s=M.atto_recordrtc.commonmodule,n=M.atto_recordrtc.abstractmodule,e=M.atto_recordrtc.compatcheckmodule,M.atto_recordrtc.videomodule={init:function(t){s.editorScope=t,s.alertWarning=r.one("div#alert-warning"),s.alertDanger=r.one("div#alert-danger"),s.player=r.one("video#player"),s.playerDOM=document.querySelector("video#player"),s.startStopBtn=r.one("button#start-stop"),s.uploadBtn=r.one("button#upload"),s.recType="video",s.maxUploadSize=t.get("maxrecsize"),e.check_has_gum(),e.check_secure(),s.startStopBtn.on("click",function(){var e;s.startStopBtn.set("disabled",!0),s.startStopBtn.get("textContent")===M.util.get_string("startrecording","atto_recordrtc")||s.startStopBtn.get("textContent")===M.util.get_string("recordagain","atto_recordrtc")||s.startStopBtn.get("textContent")===M.util.get_string("recordingfailed","atto_recordrtc")?(s.uploadBtn.ancestor().ancestor().addClass("hide"),s.startStopBtn.replaceClass("btn-outline-danger","btn-danger"),s.chunks=[],s.blobSize=0,s.uploadBtn.detach("click"),e={onMediaCaptured:function(t){s.stream=t,s.start_recording(s.recType,s.stream)},onMediaStopped:function(t){s.startStopBtn.set("textContent",t),s.startStopBtn.set("disabled",!1),s.startStopBtn.replaceClass("btn-danger","btn-outline-danger")},onMediaCapturingFailed:function(t){n.handle_gum_errors(t,e)}},s.player.ancestor().ancestor().removeClass("hide"),s.player.set("controls",!1),M.atto_recordrtc.videomodule.capture_audio_video(e)):(window.clearInterval(s.countdownTicker),window.setTimeout(function(){s.startStopBtn.set("disabled",!1)},1e3),s.stop_recording(s.stream),s.startStopBtn.set("textContent",M.util.get_string("recordagain","atto_recordrtc")),s.startStopBtn.replaceClass("btn-danger","btn-outline-danger")),s.editorScope.getDialogue().centered()})},capture_audio_video:function(e){s.capture_user_media({audio:!0,video:{width:{ideal:640},height:{ideal:480}}},function(t){s.playerDOM.srcObject=t,s.playerDOM.play(),e.onMediaCaptured(t)},function(t){e.onMediaCapturingFailed(t)})}}},"@VERSION@",{requires:["moodle-atto_recordrtc-button"]});
\ No newline at end of file
+YUI.add("moodle-atto_recordrtc-recording",function(r,t){var l,n,e;M.atto_recordrtc=M.atto_recordrtc||{},l=M.atto_recordrtc.commonmodule,n=M.atto_recordrtc.abstractmodule,M.atto_recordrtc.commonmodule={editorScope:null,alertWarning:null,alertDanger:null,player:null,playerDOM:null,startStopBtn:null,uploadBtn:null,countdownSeconds:null,countdownTicker:null,recType:null,stream:null,mediaRecorder:null,chunks:null,blobSize:null,maxUploadSize:null,capture_user_media:function(t,e,o){window.navigator.mediaDevices.getUserMedia(t).then(e)["catch"](o)},handle_data_available:function(t){l.chunks.push(t.data),l.blobSize+=t.data.size,l.blobSize>=l.maxUploadSize&&(window.localStorage.getItem("alerted")?window.localStorage.removeItem("alerted"):(window.localStorage.setItem("alerted","true"),l.startStopBtn.simulate("click"),n.show_alert("nearingmaxsize")),l.chunks.pop())},handle_stop:function(){var t=new window.Blob(l.chunks,{type:l.mediaRecorder.mimeType});l.player.set("srcObject",null),l.player.set("src",window.URL.createObjectURL(t)),l.player.set("muted",!1),l.player.set("controls",!0),l.player.ancestor().ancestor().removeClass("hide"),l.uploadBtn.ancestor().ancestor().removeClass("hide"),l.uploadBtn.set("textContent",M.util.get_string("attachrecording","atto_recordrtc")),l.uploadBtn.set("disabled",!1),l.editorScope.getDialogue().centered(),l.uploadBtn.on("click",function(){0===l.chunks.length?n.show_alert("norecordingfound"):(l.uploadBtn.set("disabled",!0),l.upload_to_server(l.recType,function(t,e){"ended"===t?(l.uploadBtn.set("disabled",!1),l.insert_annotation(l.recType,e)):"upload-failed"===t?(l.uploadBtn.set("disabled",!1),l.uploadBtn.set("textContent",M.util.get_string("uploadfailed","atto_recordrtc")+" "+e)):"upload-failed-404"===t?(l.uploadBtn.set("disabled",!1),l.uploadBtn.set("textContent",M.util.get_string("uploadfailed404","atto_recordrtc"))):"upload-aborted"===t?(l.uploadBtn.set("disabled",!1),l.uploadBtn.set("textContent",M.util.get_string("uploadaborted","atto_recordrtc")+" "+e)):l.uploadBtn.set("textContent",t)}))})},start_recording:function(t,e){var o=n.select_rec_options(t);l.mediaRecorder=new window.MediaRecorder(e,o),l.mediaRecorder.ondataavailable=l.handle_data_available,l.mediaRecorder.onstop=l.handle_stop,l.mediaRecorder.start(1e3),l.player.set("muted",!0),l.countdownSeconds="audio"===t?l.editorScope.get("audiotimelimit"):"video"===t?l.editorScope.get("videotimelimit"):l.editorScope.get("defaulttimelimit"),l.countdownSeconds++,e=M.util.get_string("stoprecording","atto_recordrtc"),l.startStopBtn.setHTML(e+=' (:)'),l.set_time(),l.countdownTicker=window.setInterval(l.set_time,1e3),l.startStopBtn.set("disabled",!1)},stop_recording:function(t){var e,o;for(l.mediaRecorder.stop(),e=t.getTracks(),o=0;o":"")},insert_annotation:function(t,e){t=l.create_annotation(t,e);t?l.editorScope.setLink(l.editorScope,t):l.uploadBtn.set("textContent",M.util.get_string("attachrecording","atto_recordrtc"))}},M.atto_recordrtc=M.atto_recordrtc||{},l=M.atto_recordrtc.commonmodule,n=M.atto_recordrtc.abstractmodule,M.atto_recordrtc.compatcheckmodule={check_has_gum:function(){navigator.mediaDevices&&window.MediaRecorder||n.show_alert("nowebrtc",function(){l.editorScope.closeDialogue(l.editorScope)})},check_secure:function(){"https:"===window.location.protocol||-1!==window.location.host.indexOf("localhost")||l.alertDanger.ancestor().ancestor().removeClass("hide")}},M.atto_recordrtc=M.atto_recordrtc||{},l=M.atto_recordrtc.commonmodule,n=M.atto_recordrtc.abstractmodule,M.atto_recordrtc.abstractmodule={show_alert:function(e,o){r.use(
+"moodle-core-notification-alert",function(){var t=new M.core.alert({title:M.util.get_string(e+"_title","atto_recordrtc"),message:M.util.get_string(e,"atto_recordrtc")});o&&t.after("complete",o)})},handle_gum_errors:function(t,e){var o=M.util.get_string("recordingfailed","atto_recordrtc"),r=function(){e.onMediaStopped(o)},t="gum"+t.name.replace("Error","").toLowerCase();"gumsecurity"!=t?n.show_alert(t,r):n.show_alert(t,function(){l.editorScope.closeDialogue(l.editorScope)})},select_rec_options:function(t){var t="audio"===t?(e=["audio/webm;codecs=opus","audio/ogg;codecs=opus","audio/mp4;codecs=opus","audio/mp4;codecs=wav","audio/mp4;codecs=mp3"],{audioBitsPerSecond:window.parseInt(l.editorScope.get("audiobitrate"))}):(e=["video/webm;codecs=vp9,opus","video/webm;codecs=vp8,opus","video/mp4;codecs=h264,opus","video/mp4;codecs=h264,wav","video/mp4;codecs=v9,opus"],{audioBitsPerSecond:window.parseInt(l.editorScope.get("audiobitrate")),videoBitsPerSecond:window.parseInt(l.editorScope.get("videobitrate"))}),e=e.reduce(function(t,e){return t.push(e),t.push(e.replace("=",":")),t},[]).filter(function(t){return window.MediaRecorder.isTypeSupported(t)});return 0!==e.length&&(t.mimeType=e[0]),t}},M.atto_recordrtc=M.atto_recordrtc||{},l=M.atto_recordrtc.commonmodule,n=M.atto_recordrtc.abstractmodule,e=M.atto_recordrtc.compatcheckmodule,M.atto_recordrtc.audiomodule={init:function(t){l.editorScope=t,l.alertWarning=r.one("div#alert-warning"),l.alertDanger=r.one("div#alert-danger"),l.player=r.one("audio#player"),l.playerDOM=document.querySelector("audio#player"),l.startStopBtn=r.one("button#start-stop"),l.uploadBtn=r.one("button#upload"),l.recType="audio",l.maxUploadSize=t.get("maxrecsize"),e.check_has_gum(),e.check_secure(),l.startStopBtn.on("click",function(){var e;l.startStopBtn.set("disabled",!0),l.startStopBtn.get("textContent")===M.util.get_string("startrecording","atto_recordrtc")||l.startStopBtn.get("textContent")===M.util.get_string("recordagain","atto_recordrtc")||l.startStopBtn.get("textContent")===M.util.get_string("recordingfailed","atto_recordrtc")?(l.player.ancestor().ancestor().addClass("hide"),l.uploadBtn.ancestor().ancestor().addClass("hide"),l.startStopBtn.replaceClass("btn-outline-danger","btn-danger"),l.chunks=[],l.blobSize=0,l.uploadBtn.detach("click"),e={onMediaCaptured:function(t){l.stream=t,l.start_recording(l.recType,l.stream)},onMediaStopped:function(t){l.startStopBtn.set("textContent",t),l.startStopBtn.set("disabled",!1),l.startStopBtn.replaceClass("btn-danger","btn-outline-danger")},onMediaCapturingFailed:function(t){n.handle_gum_errors(t,e)}},M.atto_recordrtc.audiomodule.capture_audio(e)):(window.clearInterval(l.countdownTicker),window.setTimeout(function(){l.startStopBtn.set("disabled",!1)},1e3),l.stop_recording(l.stream),l.startStopBtn.set("textContent",M.util.get_string("recordagain","atto_recordrtc")),l.startStopBtn.replaceClass("btn-danger","btn-outline-danger")),l.editorScope.getDialogue().centered()})},capture_audio:function(e){l.capture_user_media({audio:!0},function(t){l.playerDOM.srcObject=t,e.onMediaCaptured(t)},function(t){e.onMediaCapturingFailed(t)})}},M.atto_recordrtc=M.atto_recordrtc||{},l=M.atto_recordrtc.commonmodule,n=M.atto_recordrtc.abstractmodule,e=M.atto_recordrtc.compatcheckmodule,M.atto_recordrtc.videomodule={init:function(t){l.editorScope=t,l.alertWarning=r.one("div#alert-warning"),l.alertDanger=r.one("div#alert-danger"),l.player=r.one("video#player"),l.playerDOM=document.querySelector("video#player"),l.startStopBtn=r.one("button#start-stop"),l.uploadBtn=r.one("button#upload"),l.recType="video",l.maxUploadSize=t.get("maxrecsize"),e.check_has_gum(),e.check_secure(),l.startStopBtn.on("click",function(){var e;l.startStopBtn.set("disabled",!0),l.startStopBtn.get("textContent")===M.util.get_string("startrecording","atto_recordrtc")||l.startStopBtn.get("textContent")===M.util.get_string("recordagain","atto_recordrtc")||l.startStopBtn.get("textContent")===M.util.get_string("recordingfailed","atto_recordrtc")?(l.uploadBtn.ancestor().ancestor().addClass("hide"),l.startStopBtn.replaceClass("btn-outline-danger","btn-danger"),l.chunks=[],l.blobSize=0,l.uploadBtn.detach("click"),e={onMediaCaptured:function(t){l.stream=t,l.start_recording(l.recType,l.stream)},onMediaStopped:function(t){l.startStopBtn.set("textContent",t),l.startStopBtn.set("disabled",!1),l.startStopBtn.replaceClass("btn-danger","btn-outline-danger")},onMediaCapturingFailed:function(t){n.handle_gum_errors(t,e)}},l.player.ancestor().ancestor().removeClass("hide"),l.player.set("controls",!1),M.atto_recordrtc.videomodule.capture_audio_video(e)):(window.clearInterval(l.countdownTicker),window.setTimeout(function(){l.startStopBtn.set("disabled",!1)},1e3),l.stop_recording(l.stream),l.startStopBtn.set("textContent",M.util.get_string("recordagain","atto_recordrtc")),l.startStopBtn.replaceClass("btn-danger","btn-outline-danger")),l.editorScope.getDialogue().centered()})},capture_audio_video:function(e){l.capture_user_media({audio:!0,video:{width:{ideal:640},height:{ideal:480}}},function(t){l.playerDOM.srcObject=t,l.playerDOM.play(),e.onMediaCaptured(t)},function(t){e.onMediaCapturingFailed(t)})}}},"@VERSION@",{requires:["moodle-atto_recordrtc-button"]});
\ No newline at end of file
diff --git a/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording.js b/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording.js
index 99deb5de7b1..49291def9df 100644
--- a/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording.js
+++ b/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording.js
@@ -189,9 +189,31 @@ M.atto_recordrtc.commonmodule = {
}
},
+ getFileExtension: function(type) {
+ if (type === 'audio') {
+ if (window.MediaRecorder.isTypeSupported('audio/webm')) {
+ return 'webm';
+ } else if (window.MediaRecorder.isTypeSupported('audio/ogg')) {
+ return 'ogg';
+ } else if (window.MediaRecorder.isTypeSupported('audio/mp4')) {
+ return 'mp4';
+ }
+ } else {
+ if (window.MediaRecorder.isTypeSupported('audio/webm')) {
+ return 'webm';
+ } else if (window.MediaRecorder.isTypeSupported('audio/mp4')) {
+ return 'mp4';
+ }
+ }
+
+ window.console.warning('Unknown file type for MediaRecorder API');
+ return '';
+ },
+
// Upload recorded audio/video to server.
upload_to_server: function(type, callback) {
var xhr = new window.XMLHttpRequest();
+ var fileExtension = this.getFileExtension(type);
// Get src media of audio/video tag.
xhr.open('GET', cm.player.get('src'), true);
@@ -204,8 +226,8 @@ M.atto_recordrtc.commonmodule = {
// Generate filename with random ID and file extension.
var fileName = (Math.random() * 1000).toString().replace('.', '');
- fileName += (type === 'audio') ? '-audio.ogg'
- : '-video.webm';
+ fileName += (type === 'audio') ? '-audio.' + fileExtension
+ : '-video.' + fileExtension;
// Create FormData to send to PHP filepicker-upload script.
var formData = new window.FormData(),
@@ -471,17 +493,35 @@ M.atto_recordrtc.abstractmodule = {
if (recType === 'audio') {
types = [
+ // Firefox and Chrome both support webm and ogg.
'audio/webm;codecs=opus',
- 'audio/ogg;codecs=opus'
+ 'audio/ogg;codecs=opus',
+
+ // Safari supports mp4.
+ 'audio/mp4;codecs=opus',
+ 'audio/mp4;codecs=wav',
+ 'audio/mp4;codecs=mp3',
];
options = {
audioBitsPerSecond: window.parseInt(cm.editorScope.get('audiobitrate'))
};
} else {
types = [
+ // Support webm as a preference.
+ // This container supports both vp9, and vp8.
+ // It does not support AVC1/h264 at all.
+ // It is supported by Chromium, and Firefox browsers, but not Safari.
'video/webm;codecs=vp9,opus',
- 'video/webm;codecs=h264,opus',
- 'video/webm;codecs=vp8,opus'
+ 'video/webm;codecs=vp8,opus',
+
+ // Fall back to mp4 if webm is not available.
+ // The mp4 container supports v9, and h264 but neither of these are supported for recording on other
+ // browsers.
+ // In addition to this, we can record in v9, but VideoJS does not support an mp4 containern with v9 codec
+ // for playback. We leave it as a final option as a just-in-case.
+ 'video/mp4;codecs=h264,opus',
+ 'video/mp4;codecs=h264,wav',
+ 'video/mp4;codecs=v9,opus',
];
options = {
audioBitsPerSecond: window.parseInt(cm.editorScope.get('audiobitrate')),
@@ -489,7 +529,15 @@ M.atto_recordrtc.abstractmodule = {
};
}
- var compatTypes = types.filter(function(type) {
+ var possibleTypes = types.reduce(function(result, type) {
+ result.push(type);
+ // Safari seems to use codecs: instead of codecs=.
+ // It is safe to add both, so we do, but we want them to remain in order.
+ result.push(type.replace('=', ':'));
+ return result;
+ }, []);
+
+ var compatTypes = possibleTypes.filter(function(type) {
return window.MediaRecorder.isTypeSupported(type);
});
diff --git a/lib/editor/atto/plugins/recordrtc/yui/src/recording/js/abstractmodule.js b/lib/editor/atto/plugins/recordrtc/yui/src/recording/js/abstractmodule.js
index a90fa2a79b9..a3210dde66e 100644
--- a/lib/editor/atto/plugins/recordrtc/yui/src/recording/js/abstractmodule.js
+++ b/lib/editor/atto/plugins/recordrtc/yui/src/recording/js/abstractmodule.js
@@ -80,17 +80,35 @@ M.atto_recordrtc.abstractmodule = {
if (recType === 'audio') {
types = [
+ // Firefox and Chrome both support webm and ogg.
'audio/webm;codecs=opus',
- 'audio/ogg;codecs=opus'
+ 'audio/ogg;codecs=opus',
+
+ // Safari supports mp4.
+ 'audio/mp4;codecs=opus',
+ 'audio/mp4;codecs=wav',
+ 'audio/mp4;codecs=mp3',
];
options = {
audioBitsPerSecond: window.parseInt(cm.editorScope.get('audiobitrate'))
};
} else {
types = [
+ // Support webm as a preference.
+ // This container supports both vp9, and vp8.
+ // It does not support AVC1/h264 at all.
+ // It is supported by Chromium, and Firefox browsers, but not Safari.
'video/webm;codecs=vp9,opus',
- 'video/webm;codecs=h264,opus',
- 'video/webm;codecs=vp8,opus'
+ 'video/webm;codecs=vp8,opus',
+
+ // Fall back to mp4 if webm is not available.
+ // The mp4 container supports v9, and h264 but neither of these are supported for recording on other
+ // browsers.
+ // In addition to this, we can record in v9, but VideoJS does not support an mp4 containern with v9 codec
+ // for playback. We leave it as a final option as a just-in-case.
+ 'video/mp4;codecs=h264,opus',
+ 'video/mp4;codecs=h264,wav',
+ 'video/mp4;codecs=v9,opus',
];
options = {
audioBitsPerSecond: window.parseInt(cm.editorScope.get('audiobitrate')),
@@ -98,7 +116,15 @@ M.atto_recordrtc.abstractmodule = {
};
}
- var compatTypes = types.filter(function(type) {
+ var possibleTypes = types.reduce(function(result, type) {
+ result.push(type);
+ // Safari seems to use codecs: instead of codecs=.
+ // It is safe to add both, so we do, but we want them to remain in order.
+ result.push(type.replace('=', ':'));
+ return result;
+ }, []);
+
+ var compatTypes = possibleTypes.filter(function(type) {
return window.MediaRecorder.isTypeSupported(type);
});
diff --git a/lib/editor/atto/plugins/recordrtc/yui/src/recording/js/commonmodule.js b/lib/editor/atto/plugins/recordrtc/yui/src/recording/js/commonmodule.js
index e14b0692e73..f7e03211f3a 100644
--- a/lib/editor/atto/plugins/recordrtc/yui/src/recording/js/commonmodule.js
+++ b/lib/editor/atto/plugins/recordrtc/yui/src/recording/js/commonmodule.js
@@ -187,9 +187,31 @@ M.atto_recordrtc.commonmodule = {
}
},
+ getFileExtension: function(type) {
+ if (type === 'audio') {
+ if (window.MediaRecorder.isTypeSupported('audio/webm')) {
+ return 'webm';
+ } else if (window.MediaRecorder.isTypeSupported('audio/ogg')) {
+ return 'ogg';
+ } else if (window.MediaRecorder.isTypeSupported('audio/mp4')) {
+ return 'mp4';
+ }
+ } else {
+ if (window.MediaRecorder.isTypeSupported('audio/webm')) {
+ return 'webm';
+ } else if (window.MediaRecorder.isTypeSupported('audio/mp4')) {
+ return 'mp4';
+ }
+ }
+
+ window.console.warning('Unknown file type for MediaRecorder API');
+ return '';
+ },
+
// Upload recorded audio/video to server.
upload_to_server: function(type, callback) {
var xhr = new window.XMLHttpRequest();
+ var fileExtension = this.getFileExtension(type);
// Get src media of audio/video tag.
xhr.open('GET', cm.player.get('src'), true);
@@ -202,8 +224,8 @@ M.atto_recordrtc.commonmodule = {
// Generate filename with random ID and file extension.
var fileName = (Math.random() * 1000).toString().replace('.', '');
- fileName += (type === 'audio') ? '-audio.ogg'
- : '-video.webm';
+ fileName += (type === 'audio') ? '-audio.' + fileExtension
+ : '-video.' + fileExtension;
// Create FormData to send to PHP filepicker-upload script.
var formData = new window.FormData(),