diff --git a/Application/src/commons/common/gui/CrossPlatform.h b/Application/src/commons/common/gui/CrossPlatform.h
index c3818bed3e226872beeff7f8aea72408d1d50123..1618e22287de2c4f0797a1df43e4fd94936540af 100644
--- a/Application/src/commons/common/gui/CrossPlatform.h
+++ b/Application/src/commons/common/gui/CrossPlatform.h
@@ -35,7 +35,7 @@ namespace gui {
         virtual ~CrossPlatform() {}
         virtual void init() = 0;
         virtual void post_init() = 0;
-        virtual void create_window(int width, int height) = 0;
+        virtual void create_window(const char* title, int width, int height) = 0;
         virtual void loop(custom_function_t) = 0;
         virtual LoopStatus update_loop() = 0;
         //virtual void* texture(uint width, uint height) = 0;
diff --git a/Application/src/commons/common/gui/GLImpl.cpp b/Application/src/commons/common/gui/GLImpl.cpp
index c5b88a4f63e7be7abcb0aa886cc129bdde38a1bd..ba10ec87c5f4a89c6281c4be4962133b6f1b2baf 100644
--- a/Application/src/commons/common/gui/GLImpl.cpp
+++ b/Application/src/commons/common/gui/GLImpl.cpp
@@ -112,7 +112,7 @@ void GLImpl::set_icons(const std::vector<file::Path>& icons) {
     glfwSetWindowIcon(window, images.size(), images.data());
 }
 
-void GLImpl::create_window(int width, int height) {
+void GLImpl::create_window(const char* title, int width, int height) {
 #if __APPLE__
     // GL 3.2 + GLSL 150
     const char* glsl_version = "#version 150";
diff --git a/Application/src/commons/common/gui/GLImpl.h b/Application/src/commons/common/gui/GLImpl.h
index 77cfd2642f9f83d8640c5a00ab0f9676a1718b72..88f54ce510d7caf074f1d76db87ced7cb77b055a 100644
--- a/Application/src/commons/common/gui/GLImpl.h
+++ b/Application/src/commons/common/gui/GLImpl.h
@@ -28,7 +28,7 @@ namespace gui {
         
         void init() override;
         void post_init() override;
-        void create_window(int width, int height) override;
+        void create_window(const char* title, int width, int height) override;
         void loop(custom_function_t) override;
         LoopStatus update_loop() override;
         TexturePtr texture(const Image*) override;
diff --git a/Application/src/commons/common/gui/IMGUIBase.cpp b/Application/src/commons/common/gui/IMGUIBase.cpp
index 07825d337b9930a63fc1553b4df5cdaaaa318a1c..951e9e51a2391cee36651493c8fd0209a8cae536 100644
--- a/Application/src/commons/common/gui/IMGUIBase.cpp
+++ b/Application/src/commons/common/gui/IMGUIBase.cpp
@@ -399,7 +399,7 @@ void clear_cache() {
             }
         }
         
-        _platform->create_window(width, height);
+        _platform->create_window(title.c_str(), width, height);
         glfwSetWindowPos(_platform->window_handle(), mx + (mw - width) * 0.5, my + (mh - height) * 0.5);
         
         glfwSetDropCallback(_platform->window_handle(), [](GLFWwindow* window, int N, const char** texts){
diff --git a/Application/src/commons/common/gui/MetalImpl.h b/Application/src/commons/common/gui/MetalImpl.h
index 15f95cf7cb009f221de36a5090a0e93a0ef8c972..940ceeb6b695ee983144a69c2244660f8c44b5eb 100644
--- a/Application/src/commons/common/gui/MetalImpl.h
+++ b/Application/src/commons/common/gui/MetalImpl.h
@@ -30,7 +30,7 @@ namespace gui {
         
         void init() override;
         void post_init() override;
-        void create_window(int width, int height) override;
+        void create_window(const char* title, int width, int height) override;
         void loop(custom_function_t) override;
         LoopStatus update_loop() override;
         TexturePtr texture(const Image*) override;
diff --git a/Application/src/commons/common/gui/MetalImpl.mm b/Application/src/commons/common/gui/MetalImpl.mm
index a8b66609037c4e58256b89ddeeb8941e71636897..63a5593c7dc67262247d6597215960b21833b758 100644
--- a/Application/src/commons/common/gui/MetalImpl.mm
+++ b/Application/src/commons/common/gui/MetalImpl.mm
@@ -198,10 +198,10 @@ bool MetalImpl::open_files(const std::vector<file::Path> &paths) {
         _data->commandQueue = [_data->device newCommandQueue];
     }
     
-    void MetalImpl::create_window(int width, int height) {
+    void MetalImpl::create_window(const char* title, int width, int height) {
         // Create window with graphics context
         glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
-        window = glfwCreateWindow(width, height, "Dear ImGui GLFW+Metal example", NULL, NULL);
+        window = glfwCreateWindow(width, height, "", NULL, NULL);
         if (window == NULL)
             U_EXCEPTION("[METAL] Cannot create GLFW window.");
         
diff --git a/Application/src/commons/common/video/GenericVideo.cpp b/Application/src/commons/common/video/GenericVideo.cpp
index 0bce8303b3f193beddd4812b3bad409da5873ef6..346456b5e3bfa56efa72a9384f8ec4c158e3fc10 100644
--- a/Application/src/commons/common/video/GenericVideo.cpp
+++ b/Application/src/commons/common/video/GenericVideo.cpp
@@ -9,9 +9,9 @@ using namespace cmn;
 namespace cmn {
 ENUM_CLASS_DOCS(averaging_method_t,
     "Sum all samples and divide by N.",
-    "Calculate a per-pixel median of the samples.",
-    "Use a per-pixel minimum across samples.",
-    "Use a per-pixel maximum across samples."
+    "Calculate a per-pixel median of the samples to avoid noise. More computationally involved than mean, but often better results.",
+    "Use a per-pixel minimum across samples. Usually a good choice for short videos with black backgrounds and individuals that do not move much.",
+    "Use a per-pixel maximum across samples. Usually a good choice for short videos with white backgrounds and individuals that do not move much."
 );
 }
 
diff --git a/Application/src/commons/common/video/VideoSource.cpp b/Application/src/commons/common/video/VideoSource.cpp
index 05d6d6e446bb6a0c3ce282f83863a71f3ba9466e..14fd6ceadcbc5c0628625762cc26b227d50f7554 100644
--- a/Application/src/commons/common/video/VideoSource.cpp
+++ b/Application/src/commons/common/video/VideoSource.cpp
@@ -58,17 +58,26 @@ VideoSource::File::File(long_t index, const std::string& basename, const std::st
             _video = new Video();
             auto npz = file::Path(_filename).replace_extension("npz");
             if(npz.exists()) {
-                static bool message = false;
-                if(!message) {
-                    Debug("Found timestamps for file '%S'.", &npz.str());
-                    message = true;
+                try {
+                    static bool message = false;
+                    if(!message) {
+                        Debug("Found timestamps for file '%S'.", &npz.str());
+                        message = true;
+                    }
+                    
+                    _timestamps = cnpy::npz_load(npz.str(), "frame_time").as_vec<double>();
+                    auto res = cnpy::npz_load(npz.str(), "imgshape").as_vec<int64_t>();
+                    _size = cv::Size( (int)res[1], (int)res[0] );
+                    _length = (long_t)_timestamps.size();
+                } catch(...) {
+                    Except("Failed opening NPZ archive '%S' with (presumably) timestamps in them for video '%S'. Proceeding without.", &npz.str(), &_filename);
+                    
+                    if(!_video->open(_filename))
+                        U_EXCEPTION("Opening Video '%S' failed.", &_filename);
+                    _length = _video->length();
+                    _video->close();
                 }
                 
-                _timestamps = cnpy::npz_load(npz.str(), "frame_time").as_vec<double>();
-                auto res = cnpy::npz_load(npz.str(), "imgshape").as_vec<int64_t>();
-                _size = cv::Size( (int)res[1], (int)res[0] );
-                _length = (long_t)_timestamps.size();
-                
             } else {
                 if(!_video->open(_filename))
                     U_EXCEPTION("Opening Video '%S' failed.", &_filename);
diff --git a/Application/src/grabber/default_config.cpp b/Application/src/grabber/default_config.cpp
index c1211a79892951b23b7c8272553a74bb237a7e5e..8e4e01e95cad1cf1d3e00be67b414724b93039fb 100644
--- a/Application/src/grabber/default_config.cpp
+++ b/Application/src/grabber/default_config.cpp
@@ -119,7 +119,7 @@ namespace default_config {
         CONFIG("equalize_histogram", false, "Equalizes the histogram of the image before thresholding and background subtraction.");
         CONFIG("quit_after_average", false, "If set to true, this will terminate the program directly after generating (or loading) a background average image.", STARTUP);
         CONFIG("averaging_method", averaging_method_t::mean, "Determines the way in which the background samples are combined. The background generated in the process will be used to subtract background from foreground objects during conversion.");
-        CONFIG("average_samples", int(100), "Number of samples taken to generate an average image. Usually has to be less if `average_method` is set to max.");
+        CONFIG("average_samples", int(100), "Number of samples taken to generate an average image. Usually fewer are necessary for `average_method`s max, and min.");
         CONFIG("reset_average", false, "If set to true, the average will be regenerated using the live stream of images (video or camera).");
         
         CONFIG("video_size", Size2(-1,-1), "Is set to the dimensions of the resulting image.", SYSTEM);
diff --git a/Application/src/tracker/VideoOpener.cpp b/Application/src/tracker/VideoOpener.cpp
index 460bd3f44a44ac601758d1e3b092ee07f82077af..830d9e5211db93c114d64899e3c6f3ea34ff6139 100644
--- a/Application/src/tracker/VideoOpener.cpp
+++ b/Application/src/tracker/VideoOpener.cpp
@@ -94,6 +94,44 @@ VideoOpener::VideoOpener() {
     grab::default_config::get(temp_settings, temp_docs, nullptr);
     //::default_config::get(GlobalSettings::map(), temp_docs, nullptr);
     
+    _stale_thread = std::make_unique<std::thread>([this](){
+        std::unique_lock guard(_stale_mutex);
+        bool quit = false;
+        
+        while(!quit) {
+            _stale_variable.wait(guard);
+            
+            size_t i=0;
+            while(!_stale_buffers.empty()) {
+                auto ptr = std::move(_stale_buffers.front());
+                _stale_buffers.pop();
+                
+                if(ptr == nullptr) {
+                    quit = true;
+                    continue;
+                }
+                
+                guard.unlock();
+                try {
+                    auto path = ptr->_path;
+                    Debug("Removing stale buffer '%S'...", &path.str());
+                    ptr = nullptr;
+                    Debug("Removed stale buffer '%S'.", &path.str());
+                } catch(const std::exception& e) {
+                    Except("Exception while freeing stale buffer '%s'.", e.what());
+                }
+                guard.lock();
+                
+                ++i;
+            }
+            
+            if(i)
+                Debug("Removed %d stale buffers", i);
+        }
+        
+        Debug("Quit stale thread.");
+    });
+    
     _horizontal = std::make_shared<gui::HorizontalLayout>();
     _extra = std::make_shared<gui::VerticalLayout>();
     _infos = std::make_shared<gui::VerticalLayout>();
@@ -144,7 +182,7 @@ VideoOpener::VideoOpener() {
     
     _loading_text = std::make_shared<gui::Text>("generating average", Vec2(100,0), Cyan, gui::Font(0.5));
     
-    _raw_description = std::make_shared<gui::StaticText>("Info", Vec2(), Size2(400, -1), Font(0.6));
+    _raw_description = std::make_shared<gui::StaticText>("Info", Vec2(), Size2(500, -1), Font(0.6));
     _raw_info->set_children({
         Layout::Ptr(std::make_shared<Text>("Preview", Vec2(), White, gui::Font(0.8, Style::Bold))),
         _screenshot,
@@ -303,16 +341,37 @@ VideoOpener::VideoOpener() {
             if(image) {
                 _screenshot->set_source(std::move(image));
                 
-                if(_screenshot->size().max() != _screenshot_previous_size) {
-                    _screenshot_previous_size = _screenshot->size().max();
-                    
-                    const double max_width = 500;
-                    auto ratio = max_width / _screenshot_previous_size;
+                const auto mw = _file_chooser->graph()->width() * 0.3;
+                if(_raw_description->max_size().x != mw) {
+                    _raw_description->set_max_size(Size2(mw, -1));
+                    _screenshot_previous_size = 0;
+                }
+                
+                auto size = _screenshot->size().max();
+                if(size != _screenshot_previous_size) {
+                    auto ratio = mw / size;
                     _screenshot->set_scale(Vec2(ratio));
                     
                     _raw_info->auto_size(Margin{0, 0});
                     _raw_settings->auto_size(Margin{0, 0});
                     _horizontal_raw->auto_size(Margin{0, 0});
+                    
+                    if(_screenshot_previous_size == 0) {
+                        {
+                            std::string info_text = "<h3>Info</h3>\n";
+                            info_text += "<key>resolution</key>: <ref><nr>"+Meta::toStr(_buffer->_video->size().width)+"</nr>x<nr>"+Meta::toStr(_buffer->_video->size().height)+"</nr></ref>\n";
+                            
+                            DurationUS us{ uint64_t( _buffer->_video->length() / double(_buffer->_video->framerate()) * 1000.0 * 1000.0 ) };
+                            auto len = us.to_html();
+                            info_text += "<key>length</key>: <ref>"+len+"</ref>";
+                            
+                            _raw_description->set_txt(info_text);
+                        }
+                        
+                        _file_chooser->update_size();
+                    }
+                    
+                    _screenshot_previous_size = size;
                 }
             }
             
@@ -336,16 +395,40 @@ VideoOpener::VideoOpener() {
     });
     
     _file_chooser->on_open([this](auto){
-        _buffer = nullptr;
+        move_to_stale(std::move(_buffer));
     });
     
     _file_chooser->on_tab_change([this](auto){
-        _buffer = nullptr;
+        move_to_stale(std::move(_buffer));
     });
     
     _file_chooser->open();
 }
 
+VideoOpener::~VideoOpener() {
+    {
+        std::lock_guard guard(_stale_mutex);
+        if(_buffer)
+            _stale_buffers.push(std::move(_buffer));
+        _stale_buffers.push(nullptr);
+    }
+    
+    _stale_variable.notify_all();
+    _stale_thread->join();
+}
+
+void VideoOpener::move_to_stale(std::unique_ptr<BufferedVideo>&& ptr) {
+    if(!ptr)
+        return;
+    
+    {
+        std::lock_guard guard(_stale_mutex);
+        _stale_buffers.push(std::move(ptr));
+    }
+    
+    _stale_variable.notify_one();
+}
+
 VideoOpener::BufferedVideo::BufferedVideo(const file::Path& path) : _path(path) {
 }
 
@@ -374,8 +457,6 @@ void VideoOpener::BufferedVideo::restart_background() {
     if(max(img.cols, img.rows) > 500)
         resize_image(img, 500 / double(max(img.cols, img.rows)));
     
-    img.convertTo(_background_image, CV_32FC1);
-    
     _background_video_index = 0;
     _accumulator = std::make_unique<AveragingAccumulator<>>(TEMP_SETTING(averaging_method).value<averaging_method_t::Class>());
     _accumulator->add(img);
@@ -407,74 +488,98 @@ void VideoOpener::BufferedVideo::restart_background() {
     });
 }
 
-void VideoOpener::BufferedVideo::open() {
+void VideoOpener::BufferedVideo::open(std::function<void(const bool)>&& callback) {
     std::lock_guard guard(_video_mutex);
-    _video = std::make_unique<VideoSource>(_path.str());
-    
-    _video->frame(0, _local);
-    _local.copyTo(_img);
-    
-    _background_video = std::make_unique<VideoSource>(_path.str());
-    _cached_frame = std::make_unique<Image>(_local);
-    
-    _playback_index = 0;
-    _video_timer.reset();
-    
-    restart_background();
-    
-    // playback at 2x speed
-    _seconds_between_frames = 1 / double(_video->framerate());
-
-    _update_thread = std::make_unique<std::thread>([this](){
-        while(!_terminate) {
-            std::lock_guard guard(_video_mutex);
-            auto dt = _video_timer.elapsed();
-            if(dt < _seconds_between_frames)
-                continue;
-            
-            _playback_index = _playback_index + 1;
-            _video_timer.reset();
+    _update_thread = std::make_unique<std::thread>([this, cb = std::move(callback)]() mutable {
+        int64_t playback_index = 0;
+        Timer video_timer;
+        double seconds_between_frames = 0;
+        
+        cv::Mat local;
+        gpuMat background_image;
+        gpuMat flt, img, mask, diff, alpha, output;
+        
+        try {
+            {
+                std::lock_guard guard(_video_mutex);
+                _video = std::make_unique<VideoSource>(_path.str());
+                
+                _video->frame(0, local);
+                local.copyTo(img);
+                
+                _background_video = std::make_unique<VideoSource>(_path.str());
+                
+                playback_index = 0;
+                video_timer.reset();
+                
+                restart_background();
+                
+                // playback at 2x speed
+                seconds_between_frames = 1 / double(_video->framerate());
+            }
             
-            if(_playback_index+1 >= _video->length())
-                _playback_index = 0;
+            {
+                std::lock_guard gaurd(_frame_mutex);
+                _cached_frame = std::make_unique<Image>(local);
+            }
             
-            update_loop();
-        }
-    });
-}
-
-void VideoOpener::BufferedVideo::update_loop() {
-    try {
-        _video->frame((size_t)_playback_index, _local);
-        _local.copyTo(_img);
-        if(max(_img.cols, _img.rows) > 500)
-            resize_image(_img, 500 / double(max(_img.cols, _img.rows)));
-        _img.convertTo(_flt, CV_32FC1);
-
-        if(_alpha.empty()) {
-            _alpha = gpuMat(_img.rows, _img.cols, CV_8UC1);
-            _alpha.setTo(cv::Scalar(255));
-        }
+            cb(true);
         
-        {
-            std::lock_guard frame_guard(_frame_mutex);
-            if(_background_copy) {
-                _background_copy->get().convertTo(_background_image, CV_32FC1);
-                _background_copy = nullptr;
+            while(!_terminate) {
+                std::lock_guard guard(_video_mutex);
+                auto dt = video_timer.elapsed();
+                if(dt < seconds_between_frames)
+                    continue;
+                
+                ++playback_index;
+                video_timer.reset();
+                
+                if((uint64_t)playback_index+1 >= _video->length())
+                    playback_index = 0;
+                
+                try {
+                    _video->frame((size_t)playback_index, local);
+                    
+                    if(_number_samples.load() > 1) {
+                        local.copyTo(img);
+                        if(max(img.cols, img.rows) > 500)
+                            resize_image(img, 500 / double(max(img.cols, img.rows)));
+                        img.convertTo(flt, CV_32FC1);
+
+                        if(alpha.empty()) {
+                            alpha = gpuMat(img.rows, img.cols, CV_8UC1);
+                            alpha.setTo(cv::Scalar(255));
+                        }
+                        
+                        {
+                            std::lock_guard frame_guard(_frame_mutex);
+                            if(_background_copy) {
+                                _background_copy->get().convertTo(background_image, CV_32FC1);
+                                _background_copy = nullptr;
+                            }
+                            cv::absdiff(background_image, flt, diff);
+                        }
+                        
+                        cv::inRange(diff, _threshold.load(), 255, mask);
+                        cv::merge(std::vector<gpuMat>{mask, img, img, alpha}, output);
+                        output.copyTo(local);
+                    }
+                    
+                    std::lock_guard frame_guard(_frame_mutex);
+                    _cached_frame = std::make_unique<Image>(local);
+                    
+                } catch(const std::exception& e) {
+                    Except("Caught exception while updating '%s'", e.what());
+                }
             }
-            cv::absdiff(_background_image, _flt, _diff);
+            
+        } catch(const UtilsException& ex) {
+            // pass
+            cb(false);
+        } catch(...) {
+            cb(false);
         }
-        
-        cv::inRange(_diff, _threshold.load(), 255, _mask);
-        cv::merge(std::vector<gpuMat>{_mask, _img, _img, _alpha}, _output);
-        _output.copyTo(_local);
-        
-        std::lock_guard frame_guard(_frame_mutex);
-        _cached_frame = std::make_unique<Image>(_local);
-        
-    } catch(const std::exception& e) {
-        Except("Caught exception while updating '%s'", e.what());
-    }
+    });
 }
 
 Size2 VideoOpener::BufferedVideo::size() {
@@ -488,10 +593,26 @@ std::unique_ptr<Image> VideoOpener::BufferedVideo::next() {
 }
 
 void VideoOpener::select_file(const file::Path &p) {
-    const double max_width = 500;
+    const double max_width = _file_chooser->graph()->width() * 0.3;
     std::lock_guard guard(_file_chooser->graph()->lock());
     
     if(_file_chooser->current_tab().extension != "pv") {
+        auto callback = [this, p, max_width](const bool success){
+            if(!success) {
+                // immediately move to stale
+                std::lock_guard gui_lock(_file_chooser->graph()->lock());
+                std::lock_guard guard(_video_mutex);
+                Except("Could not open file '%S'.", &p.str());
+                
+                cv::Mat img = cv::Mat::zeros(max_width, max_width, CV_8UC1);
+                cv::putText(img, "Cannot open video.", Vec2(50, 220), cv::FONT_HERSHEY_PLAIN, 1, White);
+                _screenshot->set_source(std::make_unique<Image>(img));
+                _screenshot->set_scale(Vec2(1));
+                _file_chooser->deselect();
+                move_to_stale(std::move(_buffer));
+            }
+        };
+        
         try {
             if(p.empty())
                 U_EXCEPTION("No file selected.");
@@ -515,11 +636,10 @@ void VideoOpener::select_file(const file::Path &p) {
                 _text_fields["output_name"]->update();
             }
             
-            _buffer = std::make_unique<BufferedVideo>(p);
-            _buffer->open();
-            _screenshot->set_source(std::move(_buffer->next()));
-            _screenshot_previous_size = 0;
+            move_to_stale(std::move(_buffer));
             
+            _screenshot_previous_size = 0;
+            _buffer = std::make_unique<BufferedVideo>(p);
             try {
                 _buffer->_threshold = TEMP_SETTING(threshold).value<int>();
                 
@@ -527,42 +647,17 @@ void VideoOpener::select_file(const file::Path &p) {
                 Except("Converting number: '%s'", e.what());
             }
             
-            {
-                std::string info_text = "<h3>Info</h3>\n";
-                info_text += "<key>resolution</key>: <ref><nr>"+Meta::toStr(_buffer->_video->size().width)+"</nr>x<nr>"+Meta::toStr(_buffer->_video->size().height)+"</nr></ref>\n";
-                
-                DurationUS us{ uint64_t( _buffer->_video->length() / double(_buffer->_video->framerate()) * 1000.0 * 1000.0 ) };
-                auto len = us.to_html();
-                info_text += "<key>length</key>: <ref>"+len+"</ref>";
-                
-                _raw_description->set_txt(info_text);
-            }
-            
-            auto ratio = max_width / _screenshot->size().max();
-            _screenshot->set_scale(Vec2(ratio));
-            
-            _raw_info->auto_size(Margin{0, 0});
-            _raw_settings->auto_size(Margin{0, 0});
-            _horizontal_raw->auto_size(Margin{0, 0});
+            _buffer->open(callback);
             
         } catch(const std::exception& e) {
-            std::lock_guard guard(_video_mutex);
             Except("Cannot open file '%S' (%s)", &p.str(), e.what());
-            
-            cv::Mat img = cv::Mat::zeros(max_width, max_width, CV_8UC1);
-            cv::putText(img, "Cannot open video.", Vec2(50, 220), cv::FONT_HERSHEY_PLAIN, 1, White);
-            _screenshot->set_source(std::make_unique<Image>(img));
-            _screenshot->set_scale(Vec2(1));
-            _file_chooser->deselect();
-            _buffer = nullptr;
+            callback(false);
         }
         return;
         
     } else {
         std::lock_guard guard(_video_mutex);
-        if(_buffer) {
-            _buffer = nullptr;
-        }
+        move_to_stale(std::move(_buffer));
     }
     
     using namespace gui;
diff --git a/Application/src/tracker/VideoOpener.h b/Application/src/tracker/VideoOpener.h
index b252573bd4b29b63de72857216f9c1e3ded06506..5099670cdf676415be930b257da0c1958d46e6b3 100644
--- a/Application/src/tracker/VideoOpener.h
+++ b/Application/src/tracker/VideoOpener.h
@@ -29,25 +29,19 @@ public:
         file::Path _path;
         std::unique_ptr<VideoSource> _video;
         std::unique_ptr<VideoSource> _background_video;
-        gpuMat _background_image;
-        cv::Mat _local;
-        gpuMat _flt, _img, _mask, _diff, _alpha, _output;
         std::unique_ptr<Image> _background_copy;
         std::unique_ptr<AveragingAccumulator<>> _accumulator;
         //uint64_t _background_samples = 0;
         uint64_t _background_video_index = 0;
         
-        std::atomic<bool> _terminated_background_task;
-        std::atomic<size_t> _number_samples;
+        std::atomic<bool> _terminated_background_task = true;
+        std::atomic<size_t> _number_samples = 0;
         
         std::mutex _frame_mutex;
         std::mutex _video_mutex;
         
         std::unique_ptr<Image> _cached_frame;
         std::atomic<bool> _terminate = false, _terminate_background = false;
-        std::atomic<double> _playback_index = 0;
-        Timer _video_timer;
-        double _seconds_between_frames = 0;
         
         std::atomic<uint32_t> _threshold = 0;
         
@@ -59,15 +53,15 @@ public:
         ~BufferedVideo();
         
         std::unique_ptr<Image> next();
-        void open();
+        void open(std::function<void(const bool)>&& callback);
         Size2 size();
         
         void restart_background();
-        void update_loop();
     };
     
     std::mutex _video_mutex;
     std::unique_ptr<BufferedVideo> _buffer;
+    std::queue<std::unique_ptr<BufferedVideo>> _stale_buffers;
     
     std::shared_ptr<FileChooser> _file_chooser;
     std::map<std::string, gui::Drawable*> pointers;
@@ -78,6 +72,9 @@ public:
     gui::derived_ptr<gui::ExternalImage> _screenshot;
     gui::derived_ptr<gui::Text> _loading_text;
     gui::derived_ptr<gui::StaticText> _raw_description;
+    std::unique_ptr<std::thread> _stale_thread;
+    std::condition_variable _stale_variable;
+    
     double _screenshot_previous_size;
     
     struct LabeledField {
@@ -143,9 +140,13 @@ public:
     
 public:
     VideoOpener();
+    ~VideoOpener();
     
 private:
     void select_file(const file::Path& path);
+    
+    std::mutex _stale_mutex;
+    void move_to_stale(std::unique_ptr<BufferedVideo>&&);
 };
 
 }
diff --git a/Application/src/tracker/main.cpp b/Application/src/tracker/main.cpp
index 505e975f764a150b601066754ef545ca836073cc..cdb8eb3d1737a7898adf8b7ec2be7878f8a492fe 100644
--- a/Application/src/tracker/main.cpp
+++ b/Application/src/tracker/main.cpp
@@ -1293,7 +1293,7 @@ int main(int argc, char** argv)
     
     gui::IMGUIBase *imgui_base = nullptr;
     if((GlobalSettings::map().has("nowindow") ? SETTING(nowindow).value<bool>() : false) == false) {
-        imgui_base = new gui::IMGUIBase("", gui.gui(), [&](){
+        imgui_base = new gui::IMGUIBase(gui.window_title(), gui.gui(), [&](){
             //std::lock_guard<std::recursive_mutex> lock(gui.gui().lock());
             if(SETTING(terminate))
                 return false;
diff --git a/docs/parameters_trex.rst b/docs/parameters_trex.rst
index 6926e85d6bf417fc5ea7380692203fae7a211bd9..44f0263931b32cf897d323ce2aa99a297f3fbea4 100644
--- a/docs/parameters_trex.rst
+++ b/docs/parameters_trex.rst
@@ -1900,7 +1900,7 @@ TRex parameters
 
 .. function:: version(string)
 
-	**default value:** "1.0"
+	**default value:** "1.0.4"
 
 
 	Current application version.