diff --git a/src/Lib/Document/VivyDocument.cc b/src/Lib/Document/VivyDocument.cc
index 6cff0405c0ea45aa91b05ce900c7660d150acbbc..f9406f5ee2b3deec5345545448af7bcea8a22a36 100644
--- a/src/Lib/Document/VivyDocument.cc
+++ b/src/Lib/Document/VivyDocument.cc
@@ -308,6 +308,14 @@ VivyDocument::getAssSubDocument() const noexcept
     return assDocument;
 }
 
+AudioContext::StreamPtr
+VivyDocument::getAudioStream() const noexcept
+{
+    if (auto p = audioDocument.get())
+        return audioDocument->getDefaultStream();
+    return AudioContext::StreamPtr();
+}
+
 bool
 VivyDocument::checkDocumentCapabilities(Capabilities asType) const noexcept
 {
diff --git a/src/Lib/Document/VivyDocument.hh b/src/Lib/Document/VivyDocument.hh
index b1476d7ca29f272adcd8807a804da9f9e6e00501..f52a3d9cb3790d44c79b1dcd4456beb3cdc7f790 100644
--- a/src/Lib/Document/VivyDocument.hh
+++ b/src/Lib/Document/VivyDocument.hh
@@ -7,7 +7,8 @@
 
 #include "../Utils.hh"
 #include "../AbstractDocument.hh"
-#include "../Uuid.hh"
+#include "../AbstractDocument.hh"
+#include "../Audio.hh"
 #include "CRTPSubDocument.hh"
 
 #define DCL_VIVY_SAVE_KEY(name) static const inline QString Key##name = QStringLiteral(#name);
@@ -87,6 +88,8 @@ public:
     std::shared_ptr<VideoSubDocument> getVideoSubDocument() const noexcept;
     std::shared_ptr<AssSubDocument> getAssSubDocument() const noexcept;
 
+    AudioContext::StreamPtr getAudioStream() const noexcept;
+
     QString getDocumentCapabilitiesString() const noexcept;
 
     bool checkDocumentCapabilities(Capabilities) const noexcept;
diff --git a/src/UI/DocumentViews/AudioVisualizer.cc b/src/UI/DocumentViews/AudioVisualizer.cc
index 8c641453f999dd9407276bee9206b3229ccbfa8b..f48c885e230a0d43675bf75c0e05066c24722018 100644
--- a/src/UI/DocumentViews/AudioVisualizer.cc
+++ b/src/UI/DocumentViews/AudioVisualizer.cc
@@ -6,19 +6,21 @@ using namespace Vivy;
 #define MAXPIXVALUE 7 // Some magix AV magic stuff
 
 AudioVisualizer::AudioVisualizer(AudioContext::StreamPtr stream, QWidget *parent)
-    : QWidget(parent)
+    : audioStream(stream),
+    QWidget(parent)
 {
-    if (!stream->isDecoded()) {
-        stream->decodeData();
+    if (!audioStream->isDecoded()) {
+        qDebug() << "Need to decode data for stream" << audioStream->getStreamIndex();
+        audioStream->decodeData();
     }
 
-    double *decodedData = stream->getDecodedData();
+    double *decodedData = audioStream->getDecodedData();
     if (decodedData == nullptr)
         throw std::logic_error("the passed stream is not decoded");
 
-    const size_t size     = stream->getDecodedDataSize();
-    const size_t height   = stream->getDecodedChunkSize();
-    const size_t decalage = stream->getDecodedDecalage();
+    const size_t size     = audioStream->getDecodedDataSize();
+    const size_t height   = audioStream->getDecodedChunkSize();
+    const size_t decalage = audioStream->getDecodedDecalage();
     const size_t width    = (size - height) / decalage;
     uchar *pixels         = new uchar[static_cast<size_t>(width * height / 2)]();
 
@@ -59,14 +61,14 @@ AudioVisualizer::AudioVisualizer(AudioContext::StreamPtr stream, QWidget *parent
     QImage img = QImage(pixels, static_cast<int>(width), static_cast<int>(height / 2),
                         static_cast<int>(width), QImage::Format_Grayscale8, pixelsDeleter, pixels)
                      .mirrored(false, true);
-    printSpectrum(img, stream->getDuration());
+    printSpectrum(img, audioStream);
 }
 
 void
-AudioVisualizer::printSpectrum(QImage pixmap, quint64 audioLength) noexcept
+AudioVisualizer::printSpectrum(QImage pixmap, AudioContext::StreamPtr stream) noexcept
 {
-    TimingView *timer    = new TimingView(pixmap, audioLength, this);
-    TimingParams *params = new TimingParams(this);
+    TimingView *timer   = new TimingView(pixmap, stream, this);
+    TimingParams *params= new TimingParams(this);
 
     // The only that we want to take all the space is the timer in itself
     QGridLayout *layout = new QGridLayout;
diff --git a/src/UI/DocumentViews/AudioVisualizer.hh b/src/UI/DocumentViews/AudioVisualizer.hh
index 82a1dad979eaf13a816ac87bd85a7c3c7a1f9603..65cbce7590932da689a0778fcea853d9690c4a2f 100644
--- a/src/UI/DocumentViews/AudioVisualizer.hh
+++ b/src/UI/DocumentViews/AudioVisualizer.hh
@@ -14,6 +14,9 @@ namespace Vivy
 class AudioVisualizer final : public QWidget {
     Q_OBJECT
 
+private:
+    AudioContext::StreamPtr audioStream;
+
 private:
     static constexpr inline auto fftSampleDeleter = [](FFTSample *ptr) noexcept -> void {
         if (ptr)
@@ -35,7 +38,7 @@ public:
     ~AudioVisualizer() noexcept override = default;
 
 public slots:
-    void printSpectrum(QImage, quint64) noexcept;
+    void printSpectrum(QImage, AudioContext::StreamPtr) noexcept;
 };
 
 }
diff --git a/src/UI/DocumentViews/TimingAxis.cc b/src/UI/DocumentViews/TimingAxis.cc
index d21b81144b13e092493d06032ebb987d87effad2..ca0ed613859d1a18f265dadbb45ea7f758825046 100644
--- a/src/UI/DocumentViews/TimingAxis.cc
+++ b/src/UI/DocumentViews/TimingAxis.cc
@@ -13,12 +13,12 @@
 
 using namespace Vivy;
 
-TimingAxis::TimingAxis(quint64 audioLength_, int x0_, int x1_, int y_) noexcept
-    : QGraphicsObject()
-    , audioLength(audioLength_)
-    , x0(x0_)
-    , x1(x1_)
-    , y(y_)
+TimingAxis::TimingAxis(AudioContext::StreamPtr stream, int x0_, int x1_, int y_) noexcept
+    : QGraphicsObject(),
+    audioStream(stream),
+    x0(x0_),
+    x1(x1_),
+    y(y_)
 {
 }
 
@@ -39,10 +39,9 @@ TimingAxis::refreshTicks()
     int nbAvailableTicks        = availableTicks.size();
     int minorTicksIndex         = 0;
     QGraphicsScene *parentScene = scene();
-    if (parentScene != nullptr) {
-        for (minorTicksIndex = 0; minorTicksIndex < nbAvailableTicks; minorTicksIndex++) {
-            if (parentScene->width() / (qreal(audioLength) * availableTicks[minorTicksIndex]) <
-                minBetweenMinor) {
+    if (parentScene != nullptr){
+        for (minorTicksIndex = 0; minorTicksIndex < nbAvailableTicks; minorTicksIndex++){
+            if (parentScene->width() / (qreal(audioStream->getLength()) * availableTicks[minorTicksIndex]) < minBetweenMinor){
                 minorTicksIndex = minorTicksIndex == 0 ? 0 : minorTicksIndex - 1;
                 break;
             }
@@ -58,10 +57,8 @@ TimingAxis::refreshTicks()
     }
 }
 
-void
-TimingAxis::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
-{
-    if (audioLength == 0)
+void TimingAxis::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
+    if (audioStream->getLength() == 0)
         return;
 
     int ticks_base = y+ticksBase;
diff --git a/src/UI/DocumentViews/TimingAxis.hh b/src/UI/DocumentViews/TimingAxis.hh
index b045a0028a28dfce91b1090c4fc495df55a3aef6..d66c0c381114b86fd63077ff8def8750641b9cc7 100644
--- a/src/UI/DocumentViews/TimingAxis.hh
+++ b/src/UI/DocumentViews/TimingAxis.hh
@@ -9,6 +9,7 @@
 #include <QPainter>
 #include <QGraphicsScene>
 #include <cmath>
+#include "../../Lib/Audio.hh"
 
 namespace Vivy
 {
@@ -16,8 +17,8 @@ class TimingAxis final : public QGraphicsObject {
     Q_OBJECT
 
 public:
-    explicit TimingAxis(quint64 audioLength, int x0, int x1, int y) noexcept;
-    ~TimingAxis() noexcept override = default;
+    explicit TimingAxis(AudioContext::StreamPtr stream, int x0, int x1, int y) noexcept;
+    ~TimingAxis() noexcept = default;
 
     QRectF boundingRect() const override;
     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
@@ -26,7 +27,7 @@ private:
     static inline constexpr QColor axisColour = QColor(0, 0, 127);
 
     qreal penWidth{ 1 };
-    quint64 audioLength{ 0 };
+    AudioContext::StreamPtr audioStream;
 
     /*
      * We use ints here because
diff --git a/src/UI/DocumentViews/TimingScene.cc b/src/UI/DocumentViews/TimingScene.cc
index a83996580a72b0f78c620f7f4f13db7e21d7bb6c..09372d8d96e420ed65352999d716a53419fdbaf7 100644
--- a/src/UI/DocumentViews/TimingScene.cc
+++ b/src/UI/DocumentViews/TimingScene.cc
@@ -16,13 +16,19 @@
 using namespace Vivy;
 
 TimingScene::TimingScene(QImage img_, quint64 soundLength_, QWidget *parent) noexcept
+TimingScene::TimingScene(QWidget *parent) noexcept
+    : QGraphicsScene(parent)
+{
+}
+
+TimingScene::TimingScene(QImage img_, AudioContext::StreamPtr stream, QWidget *parent) noexcept
     : QGraphicsScene(parent)
     , img(img_)
-    , soundLength(soundLength_)
+    , audioStream(stream)
 {
     QPixmap pixmap(QPixmap::fromImage(img));
     backgroundImg = addPixmap(pixmap);
-    ax            = new TimingAxis(soundLength, 0, pixmap.width(), 10);
+    ax = new TimingAxis(stream, 0, pixmap.width(), 10);
     addItem(ax);
     ax->refreshTicks();
 }
@@ -83,7 +89,7 @@ TimingScene::timeFromPos(quint64 x) const
         qCritical() << "Try avoid possible divide by zero in the time from position";
         return 0;
     } else {
-        return x * soundLength / w;
+        return x * audioStream->getLength() / w;
     }
 }
 
diff --git a/src/UI/DocumentViews/TimingScene.hh b/src/UI/DocumentViews/TimingScene.hh
index 3dc3f26cc0931d234032e0749e22a53483ddf0ec..5097a229b1e0436843184fb6c2d20e54adacf307 100644
--- a/src/UI/DocumentViews/TimingScene.hh
+++ b/src/UI/DocumentViews/TimingScene.hh
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "../../Lib/Utils.hh"
+#include "../../Lib/Audio.hh"
 #include "../../Lib/Ass/Ass.hh"
 #include "TimingBar.hh"
 #include "TimingAxis.hh"
@@ -18,13 +19,13 @@ public:
     static inline constexpr QColor startColour = QColor(127, 0, 127);
     static inline constexpr QColor endColour   = QColor(0, 127, 0);
 
-    explicit TimingScene(QImage, quint64, QWidget * = nullptr) noexcept;
-    ~TimingScene() noexcept override = default;
+    explicit TimingScene(QWidget *parent = nullptr) noexcept;
+    explicit TimingScene(QImage, AudioContext::StreamPtr, QWidget * = nullptr) noexcept;
 
 private:
     QGraphicsPixmapItem *backgroundImg{ nullptr };
     QImage img;
-    quint64 soundLength{ 0 };
+    AudioContext::StreamPtr audioStream;
     Ass::LineWeakPtr currentLine{};
     TimingMode timingMode{ TimingMode::Line };
     TimingAxis *ax;
diff --git a/src/UI/DocumentViews/TimingView.cc b/src/UI/DocumentViews/TimingView.cc
index 81232d6f5fff31da7a4dacf56e235e879ae514fd..f40b27a6a3b0b820eda14c645234ff92a443fb30 100644
--- a/src/UI/DocumentViews/TimingView.cc
+++ b/src/UI/DocumentViews/TimingView.cc
@@ -2,10 +2,11 @@
 
 using namespace Vivy;
 
-TimingView::TimingView(QImage img, quint64 soundLength, QWidget *parent) noexcept
+TimingView::TimingView(QImage img, AudioContext::StreamPtr stream, QWidget *parent) noexcept
     : QGraphicsView(parent)
+    , audioStream(stream)
 {
-    currentScene = new TimingScene(img, soundLength, this);
+    currentScene = new TimingScene(img, stream, this);
     setFixedHeight(img.height());
     setMaximumHeight(img.height());
     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
diff --git a/src/UI/DocumentViews/TimingView.hh b/src/UI/DocumentViews/TimingView.hh
index e39ea90e4c13f2bcc140027305fb094d0c32d087..604d737ea16d2a0ea414acffd889f33cdd9dc129 100644
--- a/src/UI/DocumentViews/TimingView.hh
+++ b/src/UI/DocumentViews/TimingView.hh
@@ -5,6 +5,7 @@
 #endif
 
 #include "../../Lib/Utils.hh"
+#include "../../Lib/Audio.hh"
 #include "TimingBar.hh"
 #include "TimingScene.hh"
 #include "TimingAxis.hh"
@@ -20,14 +21,17 @@ public:
     static inline constexpr QColor startColour = QColor(127, 0, 127);
     static inline constexpr QColor endColour   = QColor(0, 127, 0);
 
-    explicit TimingView(QImage, quint64, QWidget * = nullptr) noexcept;
-    ~TimingView() noexcept override = default;
+    explicit TimingView(QImage, AudioContext::StreamPtr, QWidget * = nullptr) noexcept;
+    ~TimingView() noexcept = default;
+
+    TimingScene* getTimingScene() const;
 
     TimingScene *getTimingScene() const;
     void wheelEvent(QWheelEvent *) noexcept override;
 
 private:
     TimingScene *currentScene{ nullptr };
+    AudioContext::StreamPtr audioStream;
 
 public slots:
     void mousePressEvent(QMouseEvent *event) noexcept override;
diff --git a/src/UI/VivyDocumentView.cc b/src/UI/VivyDocumentView.cc
index 86e155afd60eac27964e0f270e8dba6f6d8ff4f8..4fb0a4307404179047f79c8416392f9760075e4d 100644
--- a/src/UI/VivyDocumentView.cc
+++ b/src/UI/VivyDocumentView.cc
@@ -7,6 +7,14 @@
 #include "../VivyApplication.hh"
 #include "../Lib/Document/VivyDocument.hh"
 #include "../Lib/Document/VivyDocumentStore.hh"
+#include "../Lib/Audio.hh"
+
+#include <QHeaderView>
+#include <QTreeView>
+#include <QVBoxLayout>
+#include <QTableView>
+#include <QWidget>
+#include <QDockWidget>
 
 using namespace Vivy;
 
@@ -118,15 +126,31 @@ VivyDocumentView::loadAssView() noexcept
 void
 VivyDocumentView::loadAudioView() noexcept
 {
-    if (!document->checkDocumentCapabilities(VivyDocument::AudioAble))
-        return;
-
-    std::shared_ptr<AudioSubDocument> audioDocument = document->getAudioSubDocument();
-    AudioContext::StreamPtr stream                  = audioDocument->getDefaultStream();
-
-    if (stream == nullptr) {
-        logError() << "Failed to get default audio stream";
-        return;
+    if (document->checkDocumentCapabilities(VivyDocument::AudioAble)) {
+        AudioContext::StreamPtr stream = document->getAudioStream();
+        if (stream == nullptr) {
+            qCritical() << "Failed to get default audio stream";
+            return;
+        }
+
+        if (!visualizer) {
+            visualizer = new QDockWidget("Visualizer", this);
+
+            visualizer->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Minimum);
+            visualizer->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::TopDockWidgetArea |
+                                        Qt::BottomDockWidgetArea);
+            visualizer->setFeatures(QDockWidget::DockWidgetMovable |
+                                    QDockWidget::DockWidgetClosable);
+            addDockWidget(Qt::LeftDockWidgetArea, visualizer, Qt::Horizontal);
+            visualizer->setTitleBarWidget(new QWidget(this));
+            Utils::setTransparentBackgroundForWidget(visualizer->titleBarWidget());
+        }
+
+        // Kubat: don't check, may throw an error but don't think we can
+        // recover from it.
+        AudioVisualizer *visualizerInner = new AudioVisualizer(stream, visualizer);
+        visualizer->setWidget(visualizerInner);
+        visualizer->layout()->setAlignment(visualizerInner, Qt::AlignTop);
     }
 
     if (!visualizer) {