diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingAxis.cc b/src/UI/DocumentViews/AudioVisualizer/TimingAxis.cc
index 668c618299670cb94bc097c918381ffec4e97598..6f69f07c9f7e3d80ab53bec1267b4ed49b439533 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingAxis.cc
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingAxis.cc
@@ -16,11 +16,8 @@
 
 using namespace Vivy;
 
-TimingAxis::TimingAxis(AudioContext::StreamPtr stream, int height_, int width_) noexcept
+TimingAxis::TimingAxis() noexcept
     : QGraphicsObject()
-    , audioStream(stream)
-    , height(height_)
-    , width(width_)
 {
     pen = QPen(axisColour);
     pen.setWidth(penWidth);
@@ -30,7 +27,8 @@ TimingAxis::TimingAxis(AudioContext::StreamPtr stream, int height_, int width_)
 QRectF
 TimingAxis::boundingRect() const
 {
-    return QRectF(0, penWidth, width + 2 * penWidth, -height - penWidth);
+    return QRectF(0, penWidth, TimingUtils::audioWidth() + 2 * penWidth,
+                  -TimingUtils::axisHeight() - penWidth);
 }
 
 /*
@@ -42,7 +40,8 @@ TimingAxis::refreshTicks()
 {
     int nbAvailableTicks = availableTicks.size();
     int minorTicksIndex  = 0;
-    int length{ int(audioStream->getLength()) };
+    int length           = TimingUtils::audioLength();
+    int width            = TimingUtils::audioWidth();
     if (width != 0 && length != 0) {
         for (minorTicksIndex = 0; minorTicksIndex < nbAvailableTicks; minorTicksIndex++) {
             if (width * availableTicks[minorTicksIndex] / length >= minBetweenMinor) {
@@ -65,8 +64,8 @@ TimingAxis::refreshTicks()
 void
 TimingAxis::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
 {
-    int audioLength;
-    if ((audioLength = int(audioStream->getLength())) == 0)
+    int audioLength = TimingUtils::audioLength();
+    if (audioLength == 0)
         return;
 
     int yText = -majorTicksHeight - timeDigitsMargin;
@@ -83,13 +82,13 @@ TimingAxis::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWi
      * should look whether this precision loss is negligible or not
      */
     for (int i = 0; i < audioLength; i += majorTicks) {
-        int pos = TimingUtils::posFromMs(i, width, audioLength);
+        int pos = TimingUtils::posFromMs(i);
         painter->drawText(QPoint(pos, yText), TimingUtils::printMajorTicks(i));
         painter->drawLine(pos, 0, pos, -majorTicksHeight);
     }
     if (minorTicks > 0) {
         for (int i = 0; i < audioLength; i += minorTicks) {
-            int pos = TimingUtils::posFromMs(i, width, audioLength);
+            int pos = TimingUtils::posFromMs(i);
             if (Q_LIKELY(fmod(i, majorTicks) != 0))
                 painter->drawLine(pos, 0, pos, -minorTicksHeight);
         }
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingAxis.hh b/src/UI/DocumentViews/AudioVisualizer/TimingAxis.hh
index 243468ac98537f0777c7db5c5c3e83e4dcdb17d7..13235d96ba67a301833473b2e632c150a44aece6 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingAxis.hh
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingAxis.hh
@@ -20,7 +20,7 @@ class TimingAxis final : public QGraphicsObject {
     Q_OBJECT
 
 public:
-    explicit TimingAxis(AudioContext::StreamPtr stream, int height, int width) noexcept;
+    explicit TimingAxis() noexcept;
     ~TimingAxis() noexcept override = default;
 
     QRectF boundingRect() const override;
@@ -31,10 +31,6 @@ private:
     QPen pen;
     int penWidth{ 1 };
 
-    AudioContext::StreamPtr audioStream;
-    int height{ 30 };
-    int width{ 0 };
-
     /*
      * We use ints here because
      * qPainter->drawLine() and qPainter->drawText()
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingCursor.cc b/src/UI/DocumentViews/AudioVisualizer/TimingCursor.cc
index 349a1f1e852cb8d2754ac14730763a1994e8a5b9..28b5d4116b99b495e8a0c6f1f2342e609b15aa7c 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingCursor.cc
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingCursor.cc
@@ -7,23 +7,23 @@
 
 using namespace Vivy;
 
-TimingCursor::TimingCursor(int height_, QGraphicsItem *parent)
-    : QGraphicsItem(parent)
-    , height(height_)
+TimingCursor::TimingCursor()
+    : QGraphicsItem()
 {
-    textRect = QRectF(0, 10, maxWidth, height - 20); // TODO : remove 10/20 magic numbers
+    textRect = QRectF(0, 10, maxWidth,
+                      TimingUtils::audioHeight() - 20); // TODO : remove 10/20 magic numbers
 }
 
 QRectF
 TimingCursor::boundingRect() const
 {
-    return QRectF(-maxWidth, 0, maxWidth * 2, height);
+    return QRectF(-maxWidth, 0, maxWidth * 2, TimingUtils::audioHeight());
 }
 
 void
 TimingCursor::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
 {
-    painter->drawLine(0, 0, 0, height);
+    painter->drawLine(0, 0, 0, TimingUtils::audioHeight());
 
     QRectF textRectangle = textRect;
     QPointF sceneLeft    = mapFromScene(QPointF(0, 0));
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingCursor.hh b/src/UI/DocumentViews/AudioVisualizer/TimingCursor.hh
index f9026bed4bbb4fb89c8c1eca5dc26f96dc1464df..bd0c765fa1474ba5490e7fa806ba90a45edb485e 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingCursor.hh
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingCursor.hh
@@ -6,7 +6,7 @@ namespace Vivy
 {
 class TimingCursor final : public QGraphicsItem {
 public:
-    explicit TimingCursor(int, QGraphicsItem *parent = nullptr);
+    explicit TimingCursor();
 
     QRectF boundingRect() const override;
     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingScene.cc b/src/UI/DocumentViews/AudioVisualizer/TimingScene.cc
index 383c4aab6fec7776ee9b7b2ae828296fb94221c5..78f5195eb2bc115036225fe4ad1ea351c9505286 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingScene.cc
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingScene.cc
@@ -52,22 +52,26 @@ TimingScene::rebuildScene()
     }
 
     // We put a common origin for the items at the bottom of the axis
-    int timingAxisHeight = 30; // TODO: remove magic number
+    TimingUtils::setAxisHeight(30); // TODO: remove magic number
 
     QPixmap pixmap(QPixmap::fromImage(img));
     backgroundImg = addPixmap(pixmap);
-    backgroundImg->setPos(0, timingAxisHeight);
+    backgroundImg->setPos(0, TimingUtils::axisHeight());
 
-    ax = new TimingAxis(audioStream, timingAxisHeight, pixmap.width());
+    TimingUtils::setAudioHeight(pixmap.height());
+    TimingUtils::setAudioWidth(img.width());
+    TimingUtils::setAudioLength(audioStream->getLength());
+
+    ax = new TimingAxis();
     addItem(ax);
-    ax->setPos(0, timingAxisHeight);
+    ax->setPos(0, TimingUtils::axisHeight());
 
     // Freeze the scene boundaries
     setSceneRect(sceneRect());
 
-    cursor = new TimingCursor(pixmap.height());
+    cursor = new TimingCursor();
     addItem(cursor);
-    cursor->setPos(0, timingAxisHeight);
+    cursor->setPos(0, TimingUtils::axisHeight());
 
     if (auto assDocument = currentVivyDocument->getAssSubDocument()) {
         QVector<Ass::LinePtr> lines = assDocument->getLines();
@@ -101,8 +105,7 @@ TimingScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) noexcept
 {
     int x = int(mouseEvent->scenePos().rx());
     cursor->setPos(x, 30);
-    cursor->setTime(TimingUtils::printCursor(
-        TimingUtils::msFromPos(x, int(audioStream->getLength()), width())));
+    cursor->setTime(TimingUtils::printCursor(TimingUtils::msFromPos(x)));
     QGraphicsScene::mouseMoveEvent(mouseEvent);
 }
 
@@ -110,7 +113,7 @@ void
 TimingScene::handleMousePressEventLine(QGraphicsSceneMouseEvent *event, Ass::LinePtr p) noexcept
 {
     QPointF pos = event->scenePos();
-    int time    = timeFromPos(int(pos.x()));
+    int time    = TimingUtils::msFromPos(int(pos.x()));
 
     if (const auto &btn = event->button(); btn == Qt::LeftButton) {
         p->setStart(quint64(time));
@@ -129,18 +132,6 @@ TimingScene::handleMousePressEventChar(QGraphicsSceneMouseEvent *, Ass::LinePtr)
 {
 }
 
-int
-TimingScene::timeFromPos(int x) const noexcept
-{
-    return TimingUtils::msFromPos(x, int(width()), int(audioStream->getLength()));
-}
-
-int
-TimingScene::posFromTime(int t) const noexcept
-{
-    return TimingUtils::posFromMs(t, int(width()), int(audioStream->getLength()));
-}
-
 QGraphicsPixmapItem *
 TimingScene::bg() noexcept
 {
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingUtils.cc b/src/UI/DocumentViews/AudioVisualizer/TimingUtils.cc
index 2e847ba2f1378aad0612fe4b411b60b523ef463e..7e710002c5ce47d9fd0826a2a41d1a9ce39da704 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingUtils.cc
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingUtils.cc
@@ -2,8 +2,40 @@
 
 using namespace Vivy;
 
-int TimingUtils::majorTicks{ 0 };
-int TimingUtils::minorTicks{ 0 };
+int TimingUtils::m_majorTicks{ 1 };
+int TimingUtils::m_minorTicks{ 1 };
+
+int TimingUtils::m_axisHeight{ 1 };
+int TimingUtils::m_audioHeight{ 1 };
+int TimingUtils::m_audioWidth{ 1 };
+int TimingUtils::m_audioLength{ 1 };
+
+qreal TimingUtils::m_wl{ 0 };
+qreal TimingUtils::m_lw{ 0 };
+
+int
+TimingUtils::posFromMs(int t) noexcept
+{
+    return int(t * m_wl);
+}
+
+int
+TimingUtils::posFromMs(int t, int audioWidth, int audioLength) noexcept
+{
+    return audioLength == 0 ? 0 : int(qint64(t) * qint64(audioWidth) / audioLength);
+}
+
+int
+TimingUtils::msFromPos(int x) noexcept
+{
+    return int(x * m_lw);
+}
+
+int
+TimingUtils::msFromPos(int x, int audioLength, int audioWidth) noexcept
+{
+    return audioWidth == 0 ? 0 : int(qint64(x) * qint64(audioLength) / audioWidth);
+}
 
 void
 TimingUtils::adjustFlip(QRectF *rect, qreal left, qreal right) noexcept
@@ -33,7 +65,7 @@ TimingUtils::printMajorTicks(int t) noexcept
     // TODO : adapt to different ticks (not everytime with "." first)
     QString ret(
         QStringLiteral("%1").arg(t % 60000 / 1000, t >= 60000 ? 2 : 1, 10, QLatin1Char('0')) +
-        QString(".") + QString::number(t % 1000 / majorTicks));
+        QString(".") + QString::number(t % 1000 / m_majorTicks));
     if (t >= 60000)
         ret.prepend(QString::number(t / 60000) + QString(":"));
     if (t >= 360000)
@@ -47,10 +79,17 @@ TimingUtils::printCursor(int t) noexcept
     // TODO : adapt to different ticks (not everytime with "." first)
     QString ret(
         QStringLiteral("%1").arg(t % 60000 / 1000, t >= 60000 ? 2 : 1, 10, QLatin1Char('0')) +
-        QString(".") + QString::number(t % 1000 / minorTicks));
+        QString(".") + QString::number(t % 1000 / m_minorTicks));
     if (t >= 60000)
         ret.prepend(QString::number(t / 60000) + QString(":"));
     if (t >= 360000)
         ret.prepend(QString::number(t / 360000) + QString(":"));
     return ret;
 }
+
+void
+TimingUtils::updateRatios() noexcept
+{
+    m_wl = m_audioLength != 0 ? qreal(m_audioWidth) / qreal(m_audioLength) : 0;
+    m_lw = m_audioWidth != 0 ? qreal(m_audioLength) / qreal(m_audioWidth) : 0;
+}
diff --git a/src/UI/DocumentViews/AudioVisualizer/TimingUtils.hh b/src/UI/DocumentViews/AudioVisualizer/TimingUtils.hh
index 78d271bf924cd75241f8c149dcd95ae507d65111..1ff08ceb357a314855d491022eaa7396720906e2 100644
--- a/src/UI/DocumentViews/AudioVisualizer/TimingUtils.hh
+++ b/src/UI/DocumentViews/AudioVisualizer/TimingUtils.hh
@@ -9,33 +9,61 @@
 
 #define getTimingScene() static_cast<TimingScene *>(scene())
 
+/*
+ * FIXME
+ * Relying on static may pose issues when multiple audioVisualiser
+ * are open (when multiple VivyDocuments are open)
+ * Solution : yeet the statics and put an instance of this class
+ * in the TimingScene
+ */
 namespace Vivy
 {
 class TimingUtils {
 private:
-    static int majorTicks;
-    static int minorTicks;
+    // Managed by TimingAxis
+    static int m_majorTicks, m_minorTicks;
+    // Managed by TimingScene
+    static int m_axisHeight, m_audioWidth, m_audioLength, m_audioHeight;
+    // Self-managed
+    static qreal m_wl, m_lw;
 
 public:
-    static inline int posFromMs(int t, int audioWidth, int audioLength) noexcept
-    {
-        return audioLength == 0 ? 0 : int(qint64(t) * qint64(audioWidth) / audioLength);
-    }
+    static int posFromMs(int t, int audioWidth, int audioLength) noexcept;
+    static int posFromMs(int t) noexcept;
 
-    static inline int msFromPos(int x, int audioLength, int audioWidth) noexcept
-    {
-        return audioWidth == 0 ? 0 : int(qint64(x) * qint64(audioLength) / audioWidth);
-    }
-
-    static inline void setTicks(int t, int T) noexcept
-    {
-        minorTicks = t;
-        majorTicks = T;
-    };
+    static int msFromPos(int x, int audioLength, int audioWidth) noexcept;
+    static int msFromPos(int x) noexcept;
 
     static void adjustTranslate(QRectF *, qreal, qreal) noexcept;
     static void adjustFlip(QRectF *, qreal, qreal) noexcept;
+
     static QString printMajorTicks(int) noexcept;
     static QString printCursor(int) noexcept;
+
+    static inline void setTicks(int t, int T) noexcept
+    {
+        m_minorTicks = t;
+        m_majorTicks = T;
+    };
+    static inline void setAxisHeight(int x) { m_axisHeight = x; };
+    static inline void setAudioHeight(int x) { m_audioHeight = x; };
+    static inline void setAudioWidth(int x)
+    {
+        m_audioWidth = x;
+        updateRatios();
+    };
+    static inline void setAudioLength(int x)
+    {
+        m_audioLength = x;
+        updateRatios();
+    };
+
+    static inline int axisHeight() { return m_axisHeight; };
+    static inline int audioHeight() { return m_audioHeight; };
+    static inline int audioWidth() { return m_audioWidth; };
+    static inline int audioLength() { return m_audioLength; };
+
+private:
+    static void updateRatios() noexcept;
 };
 }