diff --git a/src/UI/DocumentViews/MpvContainer.cc b/src/UI/DocumentViews/MpvContainer.cc
index 2ac832af0aa040ebacd0054baa7516e66a85bd3c..326f8c2bdfae10857279de32a68d9c9c182b3eb0 100644
--- a/src/UI/DocumentViews/MpvContainer.cc
+++ b/src/UI/DocumentViews/MpvContainer.cc
@@ -12,8 +12,9 @@ MpvContainer::mpvEventWakeUpCB(void *user) noexcept
     emit container->mpvEvent();
 }
 
-MpvContainer::MpvContainer()
-    : mpv(mpv_create())
+MpvContainer::MpvContainer(QWidget *parent)
+    : QWidget(parent)
+    , mpv(mpv_create())
 {
     if (mpv == nullptr)
         throw std::runtime_error("Failed to create the MPV context");
@@ -40,20 +41,18 @@ MpvContainer::MpvContainer()
 }
 
 void
-MpvContainer::registerMpvTimeCallback(void (*callback)(double)) noexcept
+MpvContainer::registerMpvTimeCallback(std::function<void(double)> callback) noexcept
 {
     if (mpvTimeCallback)
-        qWarning() << "Override a previous mpv callback, was" << mpvTimeCallback
-                   << "and now will be" << callback;
+        qWarning() << "Override a previous mpv callback!";
     mpvTimeCallback = callback;
 }
 
 void
-MpvContainer::registerMpvDurationCallback(void (*callback)(double)) noexcept
+MpvContainer::registerMpvDurationCallback(std::function<void(double)> callback) noexcept
 {
     if (mpvDurationCallback)
-        qWarning() << "Override a previous mpv callback, was" << mpvDurationCallback
-                   << "and now will be" << callback;
+        qWarning() << "Override a previous mpv callback!";
     mpvDurationCallback = callback;
 }
 
diff --git a/src/UI/DocumentViews/MpvContainer.hh b/src/UI/DocumentViews/MpvContainer.hh
index df1fe1505f8a284b2bda7dd8b6496dbe31f4902d..e8ac2cac4fe1207fa6535d337b7117a9d9c5eb07 100644
--- a/src/UI/DocumentViews/MpvContainer.hh
+++ b/src/UI/DocumentViews/MpvContainer.hh
@@ -6,6 +6,8 @@
 
 #include "../../Lib/Utils.hh"
 
+#include <functional>
+
 extern "C" {
 struct mpv_handle;
 struct mpv_event;
@@ -13,25 +15,26 @@ struct mpv_event;
 
 namespace Vivy
 {
-class MpvContainer : public QWidget {
+class MpvContainer final : public QWidget {
     Q_OBJECT
     VIVY_UNMOVABLE_OBJECT(MpvContainer)
 
 private:
     bool isPlaybackPaused{ true };
     mpv_handle *mpv{ nullptr };
-    void (*mpvTimeCallback)(double){ nullptr };
-    void (*mpvDurationCallback)(double){ nullptr };
+    std::function<void(double)> mpvTimeCallback{ nullptr };
+    std::function<void(double)> mpvDurationCallback{ nullptr };
 
 public:
-    explicit MpvContainer();
+    explicit MpvContainer(QWidget *parent);
     ~MpvContainer() noexcept override;
 
     void loadFile(const QString &) noexcept;
 
     // Register a callback for time change, don't use Qt's signals for that.
-    void registerMpvTimeCallback(void (*)(double)) noexcept;
-    void registerMpvDurationCallback(void (*)(double)) noexcept;
+    // Here the function will likely be moved if necessary (I hope...).
+    void registerMpvTimeCallback(std::function<void(double)>) noexcept;
+    void registerMpvDurationCallback(std::function<void(double)>) noexcept;
 
 private:
     void handleMpvEvent(mpv_event *) noexcept;
diff --git a/src/UI/DocumentViews/MpvControls.cc b/src/UI/DocumentViews/MpvControls.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b129142b17b78f33a1f84ec0c684b12d43d11677
--- /dev/null
+++ b/src/UI/DocumentViews/MpvControls.cc
@@ -0,0 +1,26 @@
+#include "MpvControls.hh"
+#include "MpvContainer.hh"
+
+#include <QProgressBar>
+#include <QVBoxLayout>
+
+using namespace Vivy;
+
+MpvControls::MpvControls(MpvContainer *passedContainer, QWidget *parent) noexcept
+    : QWidget(parent)
+    , mpv(passedContainer)
+{
+    QProgressBar *progressBar = new QProgressBar(this);
+
+    mpv->registerMpvDurationCallback([progressBar](double time) noexcept -> void {
+        progressBar->setMaximum(static_cast<int>(time));
+        progressBar->setValue(0);
+    });
+    mpv->registerMpvTimeCallback([progressBar](double time) noexcept -> void {
+        progressBar->setValue(static_cast<int>(time));
+    });
+
+    auto *centralLayout = new QVBoxLayout(this);
+    centralLayout->addWidget(progressBar);
+    setLayout(centralLayout);
+}
diff --git a/src/UI/DocumentViews/MpvControls.hh b/src/UI/DocumentViews/MpvControls.hh
new file mode 100644
index 0000000000000000000000000000000000000000..acb53d11362bf6f3d78629a64020fb87285a513c
--- /dev/null
+++ b/src/UI/DocumentViews/MpvControls.hh
@@ -0,0 +1,21 @@
+#pragma once
+
+#ifndef __cplusplus
+#error "This is a C++ header"
+#endif
+
+namespace Vivy
+{
+class MpvContainer;
+
+class MpvControls final : public QWidget {
+    Q_OBJECT
+    VIVY_UNMOVABLE_OBJECT(MpvControls)
+
+private:
+    MpvContainer *mpv{ nullptr };
+
+public:
+    explicit MpvControls(MpvContainer *mpv, QWidget *parent) noexcept;
+};
+}
diff --git a/src/UI/DocumentViews/VideoView.cc b/src/UI/DocumentViews/VideoView.cc
new file mode 100644
index 0000000000000000000000000000000000000000..bc73922e714944733f788251d866f26441bba4e0
--- /dev/null
+++ b/src/UI/DocumentViews/VideoView.cc
@@ -0,0 +1,31 @@
+#include "VideoView.hh"
+#include "MpvContainer.hh"
+#include "MpvControls.hh"
+
+#include <QVBoxLayout>
+
+using namespace Vivy;
+
+VideoView::VideoView(QWidget *parent) noexcept
+    : QWidget(parent)
+    , mpv(new MpvContainer(this))
+{
+    auto *centralLayout = new QVBoxLayout(this);
+
+    centralLayout->addWidget(mpv, 1);
+    centralLayout->addWidget(new MpvControls(mpv, this));
+
+    setLayout(centralLayout);
+}
+
+void
+VideoView::loadFile(const QString &filename) noexcept
+{
+    mpv->loadFile(filename);
+}
+
+void
+VideoView::forceStopPlayback() noexcept
+{
+    mpv->mpvPause();
+}
diff --git a/src/UI/DocumentViews/VideoView.hh b/src/UI/DocumentViews/VideoView.hh
new file mode 100644
index 0000000000000000000000000000000000000000..20a97b8d6c519cd28d0b1d96e670161303582a9c
--- /dev/null
+++ b/src/UI/DocumentViews/VideoView.hh
@@ -0,0 +1,26 @@
+#pragma once
+
+#ifndef __cplusplus
+#error "This is a C++ header"
+#endif
+
+#include "../../Lib/Utils.hh"
+
+namespace Vivy
+{
+class MpvContainer;
+
+class VideoView final : public QWidget {
+    Q_OBJECT
+    VIVY_UNMOVABLE_OBJECT(VideoView)
+
+    MpvContainer *mpv{ nullptr };
+
+public:
+    explicit VideoView(QWidget *parent) noexcept;
+
+public slots:
+    void loadFile(const QString &) noexcept;
+    void forceStopPlayback() noexcept;
+};
+}