diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index ec57d0e5b..9fc736660 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -176,8 +176,9 @@ GMainWindow::GMainWindow()
 
     Network::Init();
 
-    Core::Movie::GetInstance().SetPlaybackCompletionCallback(
-        [this] { QMetaObject::invokeMethod(this, "OnMoviePlaybackCompleted"); });
+    Core::Movie::GetInstance().SetPlaybackCompletionCallback([this] {
+        QMetaObject::invokeMethod(this, "OnMoviePlaybackCompleted", Qt::BlockingQueuedConnection);
+    });
 
     InitializeWidgets();
     InitializeDebugWidgets();
@@ -748,6 +749,7 @@ void GMainWindow::ConnectMenuEvents() {
     connect(ui->action_Record_Movie, &QAction::triggered, this, &GMainWindow::OnRecordMovie);
     connect(ui->action_Play_Movie, &QAction::triggered, this, &GMainWindow::OnPlayMovie);
     connect(ui->action_Close_Movie, &QAction::triggered, this, &GMainWindow::OnCloseMovie);
+    connect(ui->action_Save_Movie, &QAction::triggered, this, &GMainWindow::OnSaveMovie);
     connect(ui->action_Movie_Read_Only_Mode, &QAction::toggled, this,
             [this](bool checked) { Core::Movie::GetInstance().SetReadOnly(checked); });
     connect(ui->action_Enable_Frame_Advancing, &QAction::triggered, this, [this] {
@@ -1878,6 +1880,7 @@ void GMainWindow::OnRecordMovie() {
         BootGame(QString(game_path));
     }
     ui->action_Close_Movie->setEnabled(true);
+    ui->action_Save_Movie->setEnabled(true);
 }
 
 void GMainWindow::OnPlayMovie() {
@@ -1891,6 +1894,7 @@ void GMainWindow::OnPlayMovie() {
     BootGame(dialog.GetGamePath());
 
     ui->action_Close_Movie->setEnabled(true);
+    ui->action_Save_Movie->setEnabled(false);
 }
 
 void GMainWindow::OnCloseMovie() {
@@ -1919,6 +1923,25 @@ void GMainWindow::OnCloseMovie() {
     }
 
     ui->action_Close_Movie->setEnabled(false);
+    ui->action_Save_Movie->setEnabled(false);
+}
+
+void GMainWindow::OnSaveMovie() {
+    const bool was_running = emu_thread && emu_thread->IsRunning();
+    if (was_running) {
+        OnPauseGame();
+    }
+
+    if (Core::Movie::GetInstance().GetPlayMode() == Core::Movie::PlayMode::Recording) {
+        Core::Movie::GetInstance().SaveMovie();
+        QMessageBox::information(this, tr("Movie Saved"), tr("The movie is successfully saved."));
+    } else {
+        LOG_ERROR(Frontend, "Tried to save movie while movie is not being recorded");
+    }
+
+    if (was_running) {
+        OnStartGame();
+    }
 }
 
 void GMainWindow::OnCaptureScreenshot() {
@@ -2005,18 +2028,22 @@ void GMainWindow::UpdateStatusBar() {
         message_label->setText(tr("Recording %1").arg(current));
         message_label->setVisible(true);
         message_label_used_for_movie = true;
+        ui->action_Save_Movie->setEnabled(true);
     } else if (play_mode == Core::Movie::PlayMode::Playing) {
         message_label->setText(tr("Playing %1 / %2").arg(current).arg(total));
         message_label->setVisible(true);
         message_label_used_for_movie = true;
+        ui->action_Save_Movie->setEnabled(false);
     } else if (play_mode == Core::Movie::PlayMode::MovieFinished) {
         message_label->setText(tr("Movie Finished"));
         message_label->setVisible(true);
         message_label_used_for_movie = true;
+        ui->action_Save_Movie->setEnabled(false);
     } else if (message_label_used_for_movie) { // Clear the label if movie was just closed
         message_label->setText(QString{});
         message_label->setVisible(false);
         message_label_used_for_movie = false;
+        ui->action_Save_Movie->setEnabled(false);
     }
 
     auto results = Core::System::GetInstance().GetAndResetPerfStats();
@@ -2309,6 +2336,7 @@ void GMainWindow::OnLanguageChanged(const QString& locale) {
 }
 
 void GMainWindow::OnMoviePlaybackCompleted() {
+    OnPauseGame();
     QMessageBox::information(this, tr("Playback Completed"), tr("Movie playback completed."));
 }
 
diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h
index 9b29edd2a..970f19cad 100644
--- a/src/citra_qt/main.h
+++ b/src/citra_qt/main.h
@@ -209,6 +209,7 @@ private slots:
     void OnRecordMovie();
     void OnPlayMovie();
     void OnCloseMovie();
+    void OnSaveMovie();
     void OnCaptureScreenshot();
 #ifdef ENABLE_FFMPEG_VIDEO_DUMPER
     void OnStartVideoDumping();
diff --git a/src/citra_qt/main.ui b/src/citra_qt/main.ui
index e192f1062..1436017c5 100644
--- a/src/citra_qt/main.ui
+++ b/src/citra_qt/main.ui
@@ -166,6 +166,7 @@
      <addaction name="action_Close_Movie"/>
      <addaction name="separator"/>
      <addaction name="action_Movie_Read_Only_Mode"/>
+     <addaction name="action_Save_Movie"/>
     </widget>
     <widget class="QMenu" name="menu_Frame_Advance">
      <property name="title">
@@ -334,6 +335,14 @@
     <string>Close</string>
    </property>
   </action>
+  <action name="action_Save_Movie">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="text">
+    <string>Save without Closing</string>
+   </property>
+  </action>
   <action name="action_Movie_Read_Only_Mode">
    <property name="checkable">
     <bool>true</bool>
diff --git a/src/core/movie.cpp b/src/core/movie.cpp
index 109cf08dd..49d1e654f 100644
--- a/src/core/movie.cpp
+++ b/src/core/movie.cpp
@@ -543,6 +543,7 @@ void Movie::StartPlayback(const std::string& movie_file) {
             current_byte = 0;
             current_input = 0;
             id = header.id;
+            program_id = header.program_id;
 
             LOG_INFO(Movie, "Loaded Movie, ID: {:016X}", id);
         }
diff --git a/src/core/movie.h b/src/core/movie.h
index 0d1b689df..d4b615876 100644
--- a/src/core/movie.h
+++ b/src/core/movie.h
@@ -125,6 +125,12 @@ public:
     u64 GetCurrentInputIndex() const;
     u64 GetTotalInputCount() const;
 
+    /**
+     * Saves the movie immediately, in its current state.
+     * This is called in Shutdown.
+     */
+    void SaveMovie();
+
 private:
     static Movie s_instance;
 
@@ -152,8 +158,6 @@ private:
     ValidationResult ValidateHeader(const CTMHeader& header) const;
     ValidationResult ValidateInput(const std::vector<u8>& input, u64 expected_count) const;
 
-    void SaveMovie();
-
     PlayMode play_mode;
 
     std::string record_movie_file;