diff --git a/libraries/script-engine/src/RecordingScriptingInterface.cpp b/libraries/script-engine/src/RecordingScriptingInterface.cpp
index 98838441d2..7583f562e6 100644
--- a/libraries/script-engine/src/RecordingScriptingInterface.cpp
+++ b/libraries/script-engine/src/RecordingScriptingInterface.cpp
@@ -8,9 +8,17 @@
 
 #include "RecordingScriptingInterface.h"
 
+#include <QStandardPaths>
 #include <QtCore/QThread>
+#include <QtCore/QUrl>
+#include <QtScript/QScriptValue>
+#include <QtWidgets/QFileDialog>
 
+#include <AssetClient.h>
+#include <AssetUpload.h>
+#include <BuildInfo.h>
 #include <NumericalConstants.h>
+#include <PathUtils.h>
 #include <Transform.h>
 #include <recording/Deck.h>
 #include <recording/Recorder.h>
@@ -18,13 +26,6 @@
 #include <recording/Frame.h>
 #include <recording/ClipCache.h>
 
-
-#include <QtScript/QScriptValue>
-#include <AssetClient.h>
-#include <AssetUpload.h>
-#include <QtCore/QUrl>
-#include <QtWidgets/QFileDialog>
-
 #include "ScriptEngineLogging.h"
 
 using namespace recording;
@@ -188,6 +189,14 @@ void RecordingScriptingInterface::stopRecording() {
     _lastClip->seek(0);
 }
 
+QString RecordingScriptingInterface::getDefaultRecordingSaveDirectory() {
+    QString directory = PathUtils::getAppLocalDataPath() + "Avatar Recordings/";
+    if (!QDir(directory).exists()) {
+        QDir().mkdir(directory);
+    }
+    return directory;
+}
+
 void RecordingScriptingInterface::saveRecording(const QString& filename) {
     if (QThread::currentThread() != thread()) {
         QMetaObject::invokeMethod(this, "saveRecording", Qt::BlockingQueuedConnection,
diff --git a/libraries/script-engine/src/RecordingScriptingInterface.h b/libraries/script-engine/src/RecordingScriptingInterface.h
index a9fdf1deb4..c4220958a2 100644
--- a/libraries/script-engine/src/RecordingScriptingInterface.h
+++ b/libraries/script-engine/src/RecordingScriptingInterface.h
@@ -65,6 +65,7 @@ public slots:
 
     float recorderElapsed() const;
 
+    QString getDefaultRecordingSaveDirectory();
     void saveRecording(const QString& filename);
     bool saveRecordingToAsset(QScriptValue getClipAtpUrl);
     void loadLastRecording();
diff --git a/scripts/developer/EZrecord.js b/scripts/developer/EZrecord.js
index f8dd7bc26e..382633f4f2 100644
--- a/scripts/developer/EZrecord.js
+++ b/scripts/developer/EZrecord.js
@@ -136,9 +136,7 @@
                     log("Start recording");
                     Script.setTimeout(function () {
                         // Delay start so that start beep is not included in recorded sound.
-
-                        // TODO
-
+                        Recording.startRecording();
                         RecordingIndicator.show();
                     }, START_RECORDING_SOUND_DURATION);
                     recordingState = RECORDING;
@@ -155,21 +153,21 @@
             if (recordingState === COUNTING_DOWN) {
                 Script.clearInterval(countdownTimer);
             } else {
-
-                // TODO
-
+                Recording.stopRecording();
                 RecordingIndicator.hide();
             }
             recordingState = IDLE;
         }
 
         function finishRecording() {
-            log("Finish recording");
             playSound(finishRecordingSound);
-
-            // TODO
-
+            Recording.stopRecording();
             RecordingIndicator.hide();
+            var filename = (new Date()).toISOString();  // yyyy-mm-ddThh:mm:ss.sssZ
+            filename = filename.replace(/[\-:]|\.\d*Z$/g, "").replace("T", "-") + ".hfr";  // yyyymmmdd-hhmmss.hfr
+            filename = Recording.getDefaultRecordingSaveDirectory() + filename;
+            log("Finish recording: " + filename);
+            Recording.saveRecording(filename);
             recordingState = IDLE;
         }