diff --git a/applications/gui2/src/modules/camera.cpp b/applications/gui2/src/modules/camera.cpp
index 648b409095265c1b12b1f169189386d3a6c65da2..e16f381a4c286c04bc7e216b3f774b4c59bde1be 100644
--- a/applications/gui2/src/modules/camera.cpp
+++ b/applications/gui2/src/modules/camera.cpp
@@ -332,6 +332,11 @@ void Camera::startRecording(const std::string &filename, const std::unordered_se
 	io->feed()->startRecording(filter, filename);
 }
 
+void Camera::startStreaming(const std::unordered_set<ftl::codecs::Channel> &channels) {
+	filter->select(channels);
+	io->feed()->startStreaming(filter);
+}
+
 ftl::cuda::TextureObject<uchar4>& Camera::getFrame() {
 	if (std::atomic_load(&current_fs_)) {
 		auto& frame = current_fs_->frames[frame_idx].cast<ftl::rgbd::Frame>();
diff --git a/applications/gui2/src/modules/camera.hpp b/applications/gui2/src/modules/camera.hpp
index 2f2857b3a389219057aaee4a8c1b7114f385874b..162500e367d6a741911c26e7549860ff24229062 100644
--- a/applications/gui2/src/modules/camera.hpp
+++ b/applications/gui2/src/modules/camera.hpp
@@ -57,6 +57,7 @@ public:
 	bool isRecording();
 	void stopRecording();
 	void startRecording(const std::string &filename, const std::unordered_set<ftl::codecs::Channel> &channels);
+	void startStreaming(const std::unordered_set<ftl::codecs::Channel> &channels);
 
 private:
 	int frame_idx = -1;
diff --git a/applications/gui2/src/views/camera.cpp b/applications/gui2/src/views/camera.cpp
index 1301eacaf389a2fcd579dffaa4c8a646fb8d4cef..5d1e21f83801c09eb962b2e5625844f1d8f0e7af 100644
--- a/applications/gui2/src/views/camera.cpp
+++ b/applications/gui2/src/views/camera.cpp
@@ -124,7 +124,21 @@ RecordOptions::RecordOptions(nanogui::Widget *parent, Camera* ctrl)
 	});
 
 	auto stream = new Button(button_panel, "Stream");
-	stream->setEnabled(false);
+	stream->setCallback([this]() {
+		std::unordered_set<ftl::codecs::Channel> selection;
+		for (auto &s : channels_) {
+			if (std::get<0>(s)->checked()) {
+				selection.emplace(std::get<1>(s));
+			}
+		}
+
+		if (selection.size() > 0) {
+			ctrl_->startStreaming(selection);
+			setVisible(false);
+		}
+
+		if (callback_) callback_(true);
+	});
 
 	auto closebut = new Button(button_panel, "Cancel");
 	closebut->setCallback([this]() {
diff --git a/components/streams/src/feed.cpp b/components/streams/src/feed.cpp
index 4d19eb5423d3cc7c6a413b761ae85524ef891ad1..1a61885e0d2b7c4b529a8cd0a57a413fbf65283f 100644
--- a/components/streams/src/feed.cpp
+++ b/components/streams/src/feed.cpp
@@ -796,9 +796,19 @@ void Feed::startStreaming(Filter *f, const std::string &filename) {
 }
 
 void Feed::startStreaming(Filter *f) {
-	if (_isRecording()) throw FTL_Error("Already recording, cannot live stream");
+	{
+		UNIQUE_LOCK(mtx_, lk);
+		if (_isRecording()) throw FTL_Error("Already recording, cannot live stream");
 
-	// TODO: Allow net streaming
+		record_filter_ = f;
+
+		auto *nstream = ftl::create<ftl::stream::Net>(this, "live_stream", net_);
+		nstream->set("uri", value("uri", std::string("ftl://vision.utu.fi/live")));
+		record_stream_->add(nstream);
+		record_stream_->begin();
+		recorder_->resetSender();
+	}
+	_beginRecord(f);
 }
 
 void Feed::_beginRecord(Filter *f) {