diff --git a/src/cam/camera_session.cpp b/src/cam/camera_session.cpp
index a1b447235009..74c2acd79499 100644
--- a/src/cam/camera_session.cpp
+++ b/src/cam/camera_session.cpp
@@ -94,6 +94,13 @@ CameraSession::CameraSession(CameraManager *cm,
 	}
 #endif
 
+	if (options_.isSet(OptCaptureScript)) {
+		script_ = std::make_unique<CaptureScript>(camera_,
+					  options_[OptCaptureScript].toString());
+		if (!script_->valid())
+			return;
+	}
+
 	switch (config->validate()) {
 	case CameraConfiguration::Valid:
 		break;
@@ -327,6 +334,9 @@ int CameraSession::startCapture()
 
 int CameraSession::queueRequest(Request *request)
 {
+	if (script_)
+		request->controls() = script_->frameControls(queueCount_);
+
 	queueCount_++;
 
 	return camera_->queueRequest(request);
diff --git a/src/cam/camera_session.h b/src/cam/camera_session.h
index bf966bd15ab0..2cca92df0079 100644
--- a/src/cam/camera_session.h
+++ b/src/cam/camera_session.h
@@ -21,6 +21,7 @@
 #include <libcamera/request.h>
 #include <libcamera/stream.h>
 
+#include "capture_script.h"
 #include "options.h"
 
 class FrameSink;
@@ -60,6 +61,8 @@ private:
 	std::shared_ptr<libcamera::Camera> camera_;
 	std::unique_ptr<libcamera::CameraConfiguration> config_;
 
+	std::unique_ptr<CaptureScript> script_;
+
 	std::map<const libcamera::Stream *, std::string> streamNames_;
 	std::unique_ptr<FrameSink> sink_;
 	unsigned int cameraIndex_;
