diff --git a/src/Lib/Ass/AssFactory.cc b/src/Lib/Ass/AssFactory.cc
index 334de5b8b3e1fc18514958faf63b3684aac84cc0..7bd08bfe0792fd013662a72a85b931b5a8b4dd47 100644
--- a/src/Lib/Ass/AssFactory.cc
+++ b/src/Lib/Ass/AssFactory.cc
@@ -120,6 +120,19 @@ AssFactory::AssFactory(const QString &fileName)
         throw std::runtime_error("the loaded ass is invalid");
 }
 
+AssFactory::AssFactory(const QJsonValue &internal)
+    : diskStorage("")
+{
+    if (!diskStorage.open(QIODevice::ReadOnly | QIODevice::Text))
+        throw std::runtime_error("failed to open file for reading");
+
+    if (!initFromStorage())
+        throw std::runtime_error("failed to init ass factory from file");
+
+    if (!checkValidity())
+        throw std::runtime_error("the loaded ass is invalid");
+}
+
 void
 AssFactory::getStyles(QVector<StylePtr> &ret) const noexcept
 {
diff --git a/src/Lib/Ass/AssFactory.hh b/src/Lib/Ass/AssFactory.hh
index 8e1812889b07cf4fb7183943662d6a6fb56d0b54..544806afe3c7b608ca4ad65dd254b438abc970a7 100644
--- a/src/Lib/Ass/AssFactory.hh
+++ b/src/Lib/Ass/AssFactory.hh
@@ -46,6 +46,7 @@ private:
 
 public:
     explicit AssFactory(const QString &);
+    explicit AssFactory(const QJsonValue &);
     ~AssFactory() noexcept = default;
 
     bool hasStyle(const QString &) const noexcept;
diff --git a/src/Lib/Document/CRTPSubDocument.hh b/src/Lib/Document/CRTPSubDocument.hh
index 7aea6cf7871c4a7caf0167ac79f998ad16e38de6..a32869f9ecf4daff7b710c399bd120b038c7fa68 100644
--- a/src/Lib/Document/CRTPSubDocument.hh
+++ b/src/Lib/Document/CRTPSubDocument.hh
@@ -129,7 +129,25 @@ class AssSubDocument final : public CRTPSubDocument<AssDocumentType, AssSubDocum
     static constexpr inline bool hasContext = false;
     const QStringList &suffixList           = Vivy::Utils::assFileSuffix;
 
+public:
+    static std::unique_ptr<AssSubDocument> fromInternal(const QJsonValue &internal) noexcept
+    {
+        auto ret = std::unique_ptr<AssSubDocument>(new AssSubDocument());
+        ret->logDebug() << "Init ASS subdocument from internal";
+
+        try {
+            ret->initFromInternal(internal); // May throw
+        } catch (const std::runtime_error &e) {
+            ret->logDebug() << "Failed to init ASS subdocument from internal: " << e.what();
+            ret.reset();
+        }
+
+        return ret;
+    }
+
+private:
     void initFromPath(const QString &);
+    void initFromInternal(const QJsonValue &);
 
     explicit AssSubDocument() noexcept = default;
     friend CRTPSubDocument<AssDocumentType, AssSubDocument, void>;
@@ -143,9 +161,14 @@ public:
     const QVector<Ass::LinePtr> &getLines() const noexcept;
     const QVector<Ass::StylePtr> &getStyles() const noexcept;
 
+    void setFilePath(QString filepath) noexcept;
+    void setInternalAss(bool b) noexcept;
+    bool haveInternalAss() const noexcept;
+
 private:
     QVector<Ass::StylePtr> styles;
     QVector<Ass::LinePtr> lines;
     Ass::AssFactory *assFactory;
+    bool internalAss{ false };
 };
 }
diff --git a/src/Lib/Document/CRTPSubDocument/AssSubDocument.cc b/src/Lib/Document/CRTPSubDocument/AssSubDocument.cc
index 9f55a6f3a722b98accb463def72b8ba59e1a7af2..a1266bf8ce4ea84107e564bb268d85ab9b106fb8 100644
--- a/src/Lib/Document/CRTPSubDocument/AssSubDocument.cc
+++ b/src/Lib/Document/CRTPSubDocument/AssSubDocument.cc
@@ -15,6 +15,16 @@ AssSubDocument::initFromPath(const QString &path)
     assFactory->getLines(lines);
 }
 
+void
+AssSubDocument::initFromInternal(const QJsonValue &internal)
+{
+    styles.clear();
+    lines.clear();
+    assFactory = new Ass::AssFactory(internal);
+    assFactory->getStyles(styles);
+    assFactory->getLines(lines);
+}
+
 QString
 AssSubDocument::getElementName() const noexcept
 {
@@ -53,6 +63,18 @@ AssSubDocument::getFactory() noexcept
     return assFactory;
 }
 
+bool
+AssSubDocument::haveInternalAss() const noexcept
+{
+    return internalAss;
+}
+
+void
+AssSubDocument::setInternalAss(bool b) noexcept
+{
+    internalAss = b;
+}
+
 QJsonArray
 AssSubDocument::getInternalAss() noexcept
 {
@@ -64,3 +86,9 @@ AssSubDocument::getInternalAss() noexcept
 
     return ret;
 }
+
+void
+AssSubDocument::setFilePath(QString filepath) noexcept
+{
+    filePath = filepath;
+}
diff --git a/src/Lib/Document/VivyDocument.cc b/src/Lib/Document/VivyDocument.cc
index baf0113ea79a285a7a690b4ddcd3e874d9f38e8d..8dc4064c017be92d214df16c30e65e9320c3f269 100644
--- a/src/Lib/Document/VivyDocument.cc
+++ b/src/Lib/Document/VivyDocument.cc
@@ -89,6 +89,26 @@ VivyDocument::loadSaveJsonDocumentFile_ALPHA(VivyDocument *const self, const QJs
         if (!self->loadSubDocument(ass.toString(), Capabilities::AssAble))
             throw std::runtime_error("Failed to load ASS sub document");
     }
+
+    /*
+     * TODO: for now, if there is an internal ass we use it and ignore the SubAss file
+     * In the future, both should be loaded to allow the user to switch between the 2
+     * (e.g. a "reference" ass and the vivy ass)
+     */
+    if (QJsonValue haveInternalAss = json[KeySubDocuments][KeyHaveInternalAss];
+        !haveInternalAss.isUndefined() && haveInternalAss.toBool()) {
+        // ASS is inside Vivy document
+        if (QJsonValue internalAssSource = json[KeySubDocuments][KeyInternalAssSource];
+            !internalAssSource.isUndefined() && internalAssSource.isArray()) {
+            if (!self->loadSubDocument(internalAssSource, Capabilities::AssAble)) {
+                throw std::runtime_error("Failed to load ASS sub document");
+            }
+        }
+    } else if (QJsonValue ass = json[KeySubDocuments][KeySubAss]; !ass.isUndefined()) {
+        // ASS in its own ASS file
+        if (!self->loadSubDocument(ass.toString(), Capabilities::AssAble))
+            throw std::runtime_error("Failed to load ASS sub document");
+    }
 }
 
 void
@@ -130,13 +150,12 @@ VivyDocument::getSaveJsonDocumentFile() const
         subDocumentJson.insert(KeySubVideo, videoDocument->getFilePath());
 
     if (documentType & Capabilities::AssAble) {
+        subDocumentJson.insert(KeySubAss, assDocument->getFilePath());
+        subDocumentJson.insert(KeyHaveInternalAss, assDocument->haveInternalAss());
+
         // ASS is inside Vivy document
-        if ((assDocument->getFilePath() == getName()))
+        if (assDocument->haveInternalAss())
             subDocumentJson.insert(KeyInternalAssSource, assDocument->getInternalAss());
-
-        // ASS is in its own ASS file
-        else
-            subDocumentJson.insert(KeySubAss, assDocument->getFilePath());
     }
 
     json.insert(KeySubDocuments, subDocumentJson);
@@ -203,6 +222,26 @@ VivyDocument::loadSubDocument(const QString &subName, VivyDocument::Capabilities
     return true;
 }
 
+bool
+VivyDocument::loadSubDocument(const QJsonValue &internalAss,
+                              VivyDocument::Capabilities asType) noexcept
+{
+    logDebug() << "ASS sub-doc: Trying to open file internal ASS";
+
+    if (asType == Capabilities::AssAble) {
+        if ([[maybe_unused]] auto doc = assDocument.get()) {
+            // Here we may want to do some confirmation / cleanup
+            assDocument.reset();
+        }
+
+        assDocument = AssSubDocument::fromInternal(internalAss);
+        if (assDocument)
+            addDocumentType(AssAble);
+    }
+
+    return true;
+}
+
 bool
 VivyDocument::detectDocumentType(const QFileInfo &file, Capabilities *const ableType) noexcept
 {
diff --git a/src/Lib/Document/VivyDocument.hh b/src/Lib/Document/VivyDocument.hh
index 37448b56bc833252086505dfb6f850700ab961cb..e2f4d25bb9cf61dafe438881ae73cd37228070f2 100644
--- a/src/Lib/Document/VivyDocument.hh
+++ b/src/Lib/Document/VivyDocument.hh
@@ -26,6 +26,7 @@ class VivyDocument final : public AbstractDocument {
     DCL_VIVY_SAVE_KEY(SubAss)
     DCL_VIVY_SAVE_KEY(SubVideo)
     DCL_VIVY_SAVE_KEY(InternalAssSource)
+    DCL_VIVY_SAVE_KEY(HaveInternalAss)
     DCL_VIVY_SAVE_KEY(DocumentVersion)
 
     using LoadFunctionForVersion =
@@ -82,6 +83,7 @@ public:
     void save() override;
     bool loadSubDocument(const QString &) noexcept;
     bool loadSubDocument(const QString &, Capabilities) noexcept;
+    bool loadSubDocument(const QJsonValue &, VivyDocument::Capabilities) noexcept;
 
     // Getters
     std::shared_ptr<AudioSubDocument> getAudioSubDocument() const noexcept;
diff --git a/src/UI/MainWindow.cc b/src/UI/MainWindow.cc
index a877dcc60bd6118a41e895cb8e170e9e12c227ac..a2bf30110b1979e046f8c7877c37948fc31280da 100644
--- a/src/UI/MainWindow.cc
+++ b/src/UI/MainWindow.cc
@@ -47,6 +47,7 @@ MainWindow::MainWindow() noexcept
     DCL_MENU(edit, "&Edit");
     DCL_MENU(viewTmp, "&View");
     viewMenu = viewTmpMenu; // Save the view menu
+    DCL_MENU(ass, "&ASS");
     DCL_MENU(simulate, "&Simulate");
     DCL_MENU(help, "&Help");
 
@@ -60,6 +61,8 @@ MainWindow::MainWindow() noexcept
     DCL_ACTION(loadSubDocumentVideo, "&Load video", "Load a vide file as a sub-document", file);
     DCL_ACTION(loadSubDocumentAss, "&Load ASS", "Load an ASS file as a sub-document", file);
 
+    DCL_ACTION(setAssInternal, "&Internal ASS", "Set the ASS subdocument as internal", ass);
+
     DCL_ACTION(openDialogHelp, "&About", "Open the help dialog", help);
 
     ACTION_ADD_ICON(newDocument, VIVY_ICON_NEW);
@@ -205,6 +208,23 @@ MainWindow::openProperties(int index) noexcept
     current->openProperties();
 }
 
+void
+MainWindow::setAssInternal() noexcept
+{
+    try {
+        const auto document = dynamic_cast<VivyDocument *>(getCurrentDocument());
+        if (document) {
+            if (auto p = document->getAssSubDocument()) {
+                p->setInternalAss(true);
+            }
+        }
+    }
+
+    catch (const std::runtime_error &e) {
+        logError() << "Failed to set ASS as internal: " << e.what();
+    }
+}
+
 void
 MainWindow::openDialogHelp() noexcept
 {
diff --git a/src/UI/MainWindow.hh b/src/UI/MainWindow.hh
index 690ed2f9b0f3f49b53d5779c7c198bd34a2f49a7..bc59b3ce87f516f6e5079a7cd4c31addcf4028f8 100644
--- a/src/UI/MainWindow.hh
+++ b/src/UI/MainWindow.hh
@@ -117,6 +117,8 @@ private slots:
     void saveFileAs() noexcept;
     void renameFile() noexcept;
 
+    void setAssInternal() noexcept;
+
     void openDialogHelp() noexcept;
 
     void documentViewActionsChanged() noexcept;