diff --git a/src/web-chatview/chatview-gnome.css b/src/web-chatview/chatview-gnome.css
index bc336eed23569ce3ff7c2b2d7901e24a505f9f76..a6d432ea71a6c3cf334f46e17ad942cad55d53c5 100644
--- a/src/web-chatview/chatview-gnome.css
+++ b/src/web-chatview/chatview-gnome.css
@@ -1,90 +1,96 @@
-.internal_mes_wrapper {
-    margin: 3px 0 0 0;
-}
-
-.message_wrapper {
-    padding: 1em;
-}
-
-.sender_image {
-    margin: 10px;
-}
-
-.message_out + .message_out .message_wrapper {
-    border-top-right-radius: 10px;
-}
-
-.message_in + .message_in .message_wrapper {
-    border-top-left-radius: 10px;
-}
-
-.message_in + .message_in .sender_image {
-    visibility: hidden;
-}
-
-.message_out + .message_out .sender_image {
-    visibility: hidden;
-}
-
-.message_text {
-    hyphens: auto;
-    word-break: break-word;
-    word-wrap: break-word;
-}
-
-.nav-right {
-  align-self: flex-end;
-}
-
-.nav-left {
-  align-self: flex-start;
-}
-
-#nav-contactid {
-  margin: 0px;
-  margin-left: 5px;
-  padding: 0px;
-  height: 100%;
-  font-family: emoji;
-
-  /* enable selection (it is globally disabled in the body) */
-  -webkit-user-select: auto;
-
-  /* contactid field should take as much place as possible, but it should
-     also be the first one to shrink if necesary. */
-  flex-grow: 2;
-  flex-shrink: 2;
-  min-width: 0; /* necessary for child to be able to shrink correctly */
-
-  /* center vertically */
-  display: flex;
-  align-items: center;
-}
-
-#nav-contactid-wrapper {
-  width: 100%;
-}
-
-#nav-contactid-alias {
-  font-size: 14px;
-  font-weight: bold;
-  margin-bottom: 3px;
-
-  width: 100%;
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-
-#nav-contactid-bestId {
-  font-size: 11px;
-
-  width: 100%;
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-
-.oneEntry #nav-contactid-bestId {
-  display: none;
+.internal_mes_wrapper {
+    margin: 3px 0 0 0;
+}
+
+.message_wrapper {
+    padding: 1em;
+}
+
+.sender_image {
+    margin: 10px;
+}
+
+.message_out + .message_out .message_wrapper {
+    border-top-right-radius: 10px;
+}
+
+.message_in + .message_in .message_wrapper {
+    border-top-left-radius: 10px;
+}
+
+.message_in + .message_in .sender_image {
+    visibility: hidden;
+}
+
+.message_out + .message_out .sender_image {
+    visibility: hidden;
+}
+
+.message_text {
+    hyphens: auto;
+    word-break: break-word;
+    word-wrap: break-word;
+}
+
+.nav-right {
+  align-self: flex-end;
+}
+
+.nav-left {
+  align-self: flex-start;
+}
+
+#nav-contactid {
+  margin: 0px;
+  margin-left: 5px;
+  padding: 0px;
+  height: 100%;
+  font-family: emoji;
+
+  /* enable selection (it is globally disabled in the body) */
+  -webkit-user-select: auto;
+
+  /* contactid field should take as much place as possible, but it should
+     also be the first one to shrink if necesary. */
+  flex-grow: 2;
+  flex-shrink: 2;
+  min-width: 0; /* necessary for child to be able to shrink correctly */
+
+  /* center vertically */
+  display: flex;
+  align-items: center;
+}
+
+#nav-contactid-wrapper {
+  width: 100%;
+}
+
+#nav-contactid-alias {
+  font-size: 14px;
+  font-weight: bold;
+  margin-bottom: 3px;
+
+  width: 100%;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+#nav-contactid-bestId {
+  font-size: 11px;
+
+  width: 100%;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.oneEntry #nav-contactid-bestId {
+  display: none;
+}
+
+video {
+    width: 320px;
+    height: 180px;
+    align-items: center;
 }
\ No newline at end of file
diff --git a/src/web-chatview/chatview-windows.css b/src/web-chatview/chatview-windows.css
index b186f456aa996420cce1df74959ad4ab78ef6856..43a28c98d83bd5999bd230c240a54129f45c3e66 100644
--- a/src/web-chatview/chatview-windows.css
+++ b/src/web-chatview/chatview-windows.css
@@ -201,4 +201,10 @@ pre {
     display: flex;
     border-radius: 16px;
     cursor: auto;
+}
+
+video {
+    width: 320px;
+    height: 180px;
+    align-items: center;
 }
\ No newline at end of file
diff --git a/src/web-chatview/chatview.css b/src/web-chatview/chatview.css
index 42e5c6a4e3f9c1eea3a5a8e7e6dce7c59e2b9294..4e8d2f36e6ef39c8659fe30832f77fb8608cf8fb 100644
--- a/src/web-chatview/chatview.css
+++ b/src/web-chatview/chatview.css
@@ -607,6 +607,14 @@ a:hover {
     max-width: none;
 }
 
+.message_type_audio_video_transfer {
+    display: flex;
+    flex-direction: column;
+    padding: 0;
+    width: auto !important;
+    max-width: none;
+}
+
 .transfer_info_wrapper {
     display: flex;
     flex-direction: row;
@@ -1046,6 +1054,16 @@ audio {
     align-self: center;
 }
 
+.no-video-overlay {
+    overflow: visible;
+}
+
+video {
+    width: 320px;
+    height: 180px;
+    align-items: center;
+}
+
 /* classic screens */
 @media screen and (max-width: 1920px), screen and (max-height: 1080px) {
   .message_in {
diff --git a/src/web-chatview/chatview.js b/src/web-chatview/chatview.js
index 51c9f61f35a6aba5cffb5eeb2353116ad2ec6115..72d8a931d8e2812e894f410dcff1b6bc42354b16 100644
--- a/src/web-chatview/chatview.js
+++ b/src/web-chatview/chatview.js
@@ -1030,13 +1030,17 @@ function updateFileInteraction(message_div, message_object, forceTypeToFile = fa
 
     if (isAudio(message_text) && message_delivery_status === "finished" && displayLinksEnabled && !forceTypeToFile) {
         // Replace the old wrapper by the downloaded audio
-        var old_wrapper = message_div.querySelector(".internal_mes_wrapper")
+        if (use_qt) {
+            var old_wrapper = message_div.querySelector(".message_wrapper")
+        } else {
+            var old_wrapper = message_div.querySelector(".internal_mes_wrapper")
+        }
         if (old_wrapper) {
             old_wrapper.parentNode.removeChild(old_wrapper)
         }
 
         var errorHandler = function () {
-            var wrapper = message_div.querySelector(".internal_mes_wrapper")
+            var wrapper = message_div.querySelector(".message_type_audio_video_transfer")
             wrapper.parentNode.classList.remove("no-audio-overlay")
             var message_wrapper = message_div.querySelector(".message_wrapper")
             if (message_wrapper) {
@@ -1069,14 +1073,82 @@ function updateFileInteraction(message_div, message_object, forceTypeToFile = fa
         new_wrapper.setAttribute("type", audio_type)
         new_wrapper.setAttribute("class", "audio")
         const internal_mes_wrapper = document.createElement("div")
-        internal_mes_wrapper.setAttribute("class", "internal_mes_wrapper")
+        internal_mes_wrapper.setAttribute("class", "message_type_audio_video_transfer")
         internal_mes_wrapper.appendChild(new_wrapper)
-        message_div.insertBefore(internal_mes_wrapper, message_div.querySelector(".menu_interaction"))
+        if (use_qt) {
+            message_div.querySelector(".msg_cell").appendChild(internal_mes_wrapper)
+        } else {
+            message_div.insertBefore(internal_mes_wrapper, message_div.querySelector(".menu_interaction"))
+        }
         internal_mes_wrapper.parentNode.classList.add("no-audio-overlay")
 
         return
     }
 
+    if (isVideo(message_text) && message_delivery_status === "finished" && displayLinksEnabled && !forceTypeToFile) {
+        // Replace the old wrapper by the downloaded audio
+        if (use_qt) {
+            var old_wrapper = message_div.querySelector(".message_wrapper")
+        } else {
+            var old_wrapper = message_div.querySelector(".internal_mes_wrapper")
+        }
+
+        if (old_wrapper) {
+            old_wrapper.parentNode.removeChild(old_wrapper)
+        }
+
+        var errorHandler = function () {
+            var wrapper = message_div.querySelector(".message_type_audio_video_transfer")
+                wrapper.parentNode.classList.remove("no-video-overlay")
+            var message_wrapper = message_div.querySelector(".message_wrapper")
+            if (message_wrapper) {
+                message_wrapper.parentNode.removeChild(message_wrapper)
+            }
+
+            var media_wrapper = message_div.querySelector(".video")
+            if (media_wrapper) {
+                media_wrapper.parentNode.removeChild(media_wrapper)
+            }
+
+            var new_interaction = fileInteraction(message_id)
+            var new_message_wrapper = new_interaction.querySelector(".message_wrapper")
+            wrapper.prepend(new_message_wrapper)
+            updateFileInteraction(message_div, message_object, true)
+        }
+
+        var hideContext = function () {return false;}
+        const new_wrapper = document.createElement("video")
+        new_wrapper.onerror = errorHandler
+        new_wrapper.oncontextmenu = hideContext
+        new_wrapper.setAttribute("src", "file://" + message_text)
+        new_wrapper.setAttribute("controls", "controls")
+        var audio_type = "video/mp4"
+        if (message_text.toLowerCase().match(/\.(mp4)$/)) {
+            audio_type = "video/mp4"
+        } else if (message_text.toLowerCase().match(/\.(avi)$/)) {
+            audio_type = "video/avi"
+        } else if (message_text.toLowerCase().match(/\.(mov)$/)) {
+            audio_type = "video/mov"
+        } else if (message_text.toLowerCase().match(/\.(webm)$/)) {
+            audio_type = "video/webm"
+        } else if (message_text.toLowerCase().match(/\.(rmvb)$/)) {
+            audio_type = "video/rmvb"
+        }
+        new_wrapper.setAttribute("type", audio_type)
+        new_wrapper.setAttribute("class", "video")
+        const internal_mes_wrapper = document.createElement("div")
+
+        internal_mes_wrapper.setAttribute("class", "message_type_audio_video_transfer")
+        internal_mes_wrapper.appendChild(new_wrapper)
+        if (use_qt) {
+            message_div.querySelector(".msg_cell").appendChild(internal_mes_wrapper)
+        } else {
+            message_div.insertBefore(internal_mes_wrapper, message_div.querySelector(".menu_interaction"))
+        }
+        internal_mes_wrapper.parentNode.classList.add("no-video-overlay")
+        return
+    }
+
     // Set informations text
     var informations_div = message_div.querySelector(".informations")
     informations_div.innerText = buildFileInformationText(message_object)
@@ -1148,7 +1220,7 @@ function isImage(file) {
 }
 
 /**
- * Return if a file is an image
+ * Return if a file is an audio
  * @param file
  */
 function isAudio(file) {
@@ -1156,10 +1228,18 @@ function isAudio(file) {
 }
 
 /**
- * Return if a file is a youtube video
+ * Return if a file is an video
  * @param file
  */
 function isVideo(file) {
+    return file.toLowerCase().match(/\.(mp4|avi|webm|mov|rmvb)$/) !== null
+}
+
+/**
+ * Return if a file is a youtube video
+ * @param file
+ */
+function isYoutubeVideo(file) {
     const availableProtocols = ["http:", "https:"]
     const videoHostname = ["youtube.com", "www.youtube.com", "youtu.be"]
     const urlParser = document.createElement("a")
@@ -1577,7 +1657,7 @@ function buildNewMessage(message_object) {
             const links = DOMMsg.querySelectorAll("a")
             if (DOMMsg.childNodes.length && links.length) {
                 var isTextToShow = (DOMMsg.childNodes[0].childNodes.length > 1)
-                const ytid = (isVideo(message_text)) ? youtube_id(message_text) : ""
+                const ytid = (isYoutubeVideo(message_text)) ? youtube_id(message_text) : ""
                 if (!isTextToShow && (ytid || isImage(message_text))) {
                     type = "media"
                     message_div.append(mediaInteraction(message_id, message_direction, message_text, ytid))