_binary diff --git a/src/css/messages.css b/src/css/messages.css
index 1de4aee00..7a5eec7c9 100644
--- a/src/css/messages.css
+++ b/src/css/messages.css
@@ -59,6 +59,10 @@
     padding: 10px;
     text-decoration: none;
 }
+.none
+{
+    display: none !important;
+}
 .user-contacts
 {
     overflow-y: scroll;
@@ -440,3 +444,60 @@
     border: 1px solid grey;
     border-radius: 10%;
 }
+.new-message-container form {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    width: 100%;
+    justify-content: center;
+}
+#audio-record-btn {
+    background-color: #EEF;
+    border-radius: 20px;
+    border: solid 1px gray;
+    color: #000;
+    cursor: pointer;
+    display: inline-block;
+    font-size: 22px;
+    font-weight: bold;
+    margin: 0;
+    padding: 12px;
+    text-align: center;
+    text-decoration: none;
+    width: 44px;
+    height: 44px;
+}
+.audio-control {
+    background-color: #EEF;
+    border-radius: 20px;
+    border: solid 1px gray;
+    color: #000;
+    cursor: pointer;
+    display: inline-block;
+    font-size: 22px;
+    font-weight: bold;
+    margin: 0;
+    padding: 12px;
+    text-align: center;
+    text-decoration: none;
+    width: 44px;
+    height: 44px;
+}
+#audio-controls {
+    display: inline-flex;
+    gap: 4px;
+    align-items: center;
+}
+#mic-icon,
+#play-audio-btn,
+#delete-audio-btn {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 100%;
+    height: 100%;
+}
+.recording {
+    background-color: #EEF !important;
+    color: red;
+}
diff --git a/src/scripts/basic.js b/src/scripts/basic.js
index 5d019c2c1..961d675f9 100755
--- a/src/scripts/basic.js
+++ b/src/scripts/basic.js
@@ -612,6 +612,7 @@ function initializeFileHandler(drop_id, file_id, max_size, drop_kind, types,
         if (was_submitted) {
             return;
         }
+        addAudioToFileList();
         was_submitted = true;
         var form_data = new FormData();
         var form_elements = parent_form.elements;
@@ -768,6 +769,27 @@ function initializeFileHandler(drop_id, file_id, max_size, drop_kind, types,
             tl["basic_js_upload_cancelled"] +'</h1>');
     }
 }
+function addAudioToFileList() {
+    if (!audio_blob || !current_audio_filename) {
+        return;
+    }
+
+    const audio_file = new File([audio_blob], current_audio_filename, {
+        type: 'audio/webm',
+        lastModified: new Date().getTime()
+    });
+
+    const audio_files = {
+        0: audio_file,
+        length: 1,
+        item: function(i) { return this[i]; }
+    };
+
+    if (file_list['file_new_message'] === undefined) {
+        file_list['file_new_message'] = new Array();
+    }
+    file_list['file_new_message'][file_list['file_new_message'].length] = audio_files;
+}
 /*
  * Sets whether an elt is styled as display:none or block
  *
@@ -886,3 +908,139 @@ function initScrollPositionPreserver(scroll_container_id)
             scroll_container_id + "X");
     }
 }
+/*
+ * Global media_recorder instance used to handle audio recording functionality
+ * Stores the current recording session
+ * @var media_recorder
+ */
+let media_recorder = null;
+/*
+ * Global array used to store audio chunks as they are recorded
+ * Each chunk represents a segment of recorded audio data
+ * @var Array
+ */
+let audio_chunks = [];
+/*
+ * Global Blob instance that stores the complete recorded audio
+ * Created when recording stops by combining all audio_chunks
+ * @var Blob
+ */
+let audio_blob = null;
+/*
+ * Global Audio instance used for playback of recorded audio
+ * Created when user clicks play button
+ * @var Audio
+ */
+let audio = null;
+/*
+ * Global string storing the filename for the current audio recording
+ * Generated using timestamp when recording completes
+ * @var String
+ */
+let current_audio_filename = null;
+/*
+ * Initializes audio recording functionality for the message input
+ * Sets up event listeners for record, play, and delete buttons
+ * Handles recording states and audio blob creation
+ */
+function initializeAudioRecorder()
+{
+    const record_button = elt('audio-record-btn');
+    const mic_icon = elt('mic-icon');
+    const audio_controls = elt('audio-controls');
+    const play_button = elt('play-audio-btn');
+    const delete_button = elt('delete-audio-btn');
+    let is_recording = false;
+
+    record_button.addEventListener('click', async () => {
+        if (!is_recording) {
+            try {
+                const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
+                media_recorder = new media_recorder(stream, {
+                    mimeType: 'audio/webm;codecs=opus',
+                });
+                audio_chunks = [];
+
+                media_recorder.addEventListener('dataavailable', (event) => {
+                    audio_chunks.push(event.data);
+                });
+
+                media_recorder.addEventListener('stop', () => {
+                    // Create the blob when recording stops
+                    audio_blob = new Blob(audio_chunks, { type: 'audio/webm;codecs=opus' });
+                    audio_chunks = []; // Clear the chunks array
+
+                    // Generate filename with timestamp
+                    const timestamp = new Date().toISOString().replace(/[:]/g, '-').replace(/\..+/, '');
+                    current_audio_filename = `audio_message_${timestamp}.webm`;
+
+                    record_button.classList.add('none');
+                    audio_controls.classList.remove('none');
+
+                    // Add to file_list immediately
+                    addAudioToFileList();
+
+                    // Update the description field with resource format
+                    const description_field = elt('new-message');
+                    description_field.value = `((resource:${current_audio_filename}|Resource Description for ${current_audio_filename}))`;
+                });
+
+                media_recorder.start();
+                is_recording = true;
+                mic_icon.textContent = '⬛';
+                mic_icon.parentElement.classList.add('recording');
+            } catch (err) {
+                console.error('Error accessing microphone:', err);
+                alert('Could not access microphone. Please ensure you have granted permission.');
+            }
+        } else {
+            stopRecording();
+            is_recording = false;
+            mic_icon.textContent = '🎤';
+            mic_icon.parentElement.classList.remove('recording');
+        }
+    });
+
+    play_button.addEventListener('click', () => {
+        if (audio_blob && !audio) {
+            const audio_url = URL.createObjectURL(audio_blob);
+            audio = new Audio(audio_url);
+            audio.addEventListener('ended', () => {
+                URL.revokeObjectURL(audio_url);
+                audio = null;
+            });
+            audio.play();
+        }
+    });
+
+    delete_button.addEventListener('click', () => {
+        if (audio) {
+            audio.pause();
+            audio = null;
+        }
+        audio_blob = null;
+        current_audio_filename = null;
+        // Clear from file_list when deleted
+        if (file_list['file_new_message']) {
+            file_list['file_new_message'] = [];
+        }
+        // Clear description field
+        const description_field = elt('new-message');
+        description_field.value = '';
+
+        audio_controls.classList.add('none');
+        record_button.classList.remove('none');
+    });
+}
+/*
+ * Stops the current audio recording session
+ * Stops the media_recorder and all active audio tracks
+ * Called when user clicks stop button or starts a new recording
+ */
+function stopRecording()
+{
+    if (media_recorder && media_recorder.state === 'recording') {
+        media_recorder.stop();
+        media_recorder.stream.getTracks().forEach(track => track.stop());
+    }
+}
diff --git a/src/views/elements/ResultseditorElement.php b/src/views/elements/ResultseditorElement.php
index 84a6c4e4a..bf434f809 100644
--- a/src/views/elements/ResultseditorElement.php
+++ b/src/views/elements/ResultseditorElement.php
@@ -138,9 +138,9 @@ class ResultsEditorElement extends Element
                 ?>' >
             </div>
             <div class="top-margin" id='description-div'><label
-                for="descriptionfield"><b><?=
+                for="description_field"><b><?=
                 tl('resultseditor_element_description') ?></b></label></div>
-            <textarea class="tall-text-area" id="descriptionfield"
+            <textarea class="tall-text-area" id="description_field"
                 name="DESCRIPTION" ><?=$data['DESCRIPTION'] ?></textarea><?php
             if (empty($data['BACK_QUERY'])) {
                 $back_url = $admin_url . "a=resultsEditor&amp;" . C\CSRF_TOKEN .
@@ -295,11 +295,11 @@ class ResultsEditorElement extends Element
                 C\SEARCH_FILTER_GROUP_ITEM ?>) {
                 setDisplay('title-div', false);
                 setDisplay('description-div', false);
-                setDisplay('descriptionfield', false);
+                setDisplay('description_field', false);
             } else {
                 setDisplay('title-div', true);
                 setDisplay('description-div', true);
-                setDisplay('descriptionfield', true);
+                setDisplay('description_field', true);
             }
         }
         </script><?php
diff --git a/src/views/elements/UsermessagesElement.php b/src/views/elements/UsermessagesElement.php
index 74d4ff8a1..30850bf40 100644
--- a/src/views/elements/UsermessagesElement.php
+++ b/src/views/elements/UsermessagesElement.php
@@ -322,6 +322,13 @@ class UsermessagesElement extends Element implements CrawlConstants
             <input type="text" id="new-message"  name="description"
                 placeholder="<?=tl('usermessages_element_new_message') ?>" >
         </span>
+        <button type="button" id="audio-record-btn" class="audio-control">
+        <span id="mic-icon">🎤</span>
+        </button>
+        <div id="audio-controls" class="none">
+            <button type="button" id="play-audio-btn" class="audio-control">▶️</button>
+            <button type="button" id="delete-audio-btn" class="audio-control">🗑️</button>
+        </div>
         <button type="submit" id="send-message" ><?=$arrow ?></button>
         </form>
         </div>
@@ -329,12 +336,15 @@ class UsermessagesElement extends Element implements CrawlConstants
         if (typeof yioop_post_scripts !== 'object' ) {
             yioop_post_scripts = {};
         }
+
         yioop_post_scripts['new-message'] = function() {
             initializeFileHandler('new-message', "file-new-message",
               <?= min(L\metricToInt(ini_get('upload_max_filesize')),
               L\metricToInt(ini_get('post_max_size')))
               ?>, "textarea", null, true);
+            initializeAudioRecorder(); 
         }
+
         const emoji_groups = <?php echo
             json_encode($this->emoji_helper->emoji_groups); ?>;
         let emojis_array = {};
@@ -344,11 +354,13 @@ class UsermessagesElement extends Element implements CrawlConstants
                 emojis_array[emoji] = group_data["emojis"][emoji][0];
             }
         }
+
         function insertEmoji(emoji)
         {
             let input = elt('new-message');
             input.value += emoji;
         }
+
         function toggleEmojiPicker()
         {
             let emoji_picker = elt('emoji-picker-container');
@@ -362,6 +374,7 @@ class UsermessagesElement extends Element implements CrawlConstants
                 emoji_picker_button.innerHTML = "🙂";
             }
         }
+
         function toggleEmojiGroup(emoji_grp_tab, emoji_grp_name)
         {
             let emoji_grp_id = "emoji-group-" + emoji_grp_name;
@@ -381,6 +394,7 @@ class UsermessagesElement extends Element implements CrawlConstants
             }
             emoji_grp_tab.className += " active-emoji-group-tab";
         }
+
         function parseEmojiShortcuts()
         {
             let input = document.getElementById("new-message");
@@ -404,7 +418,6 @@ class UsermessagesElement extends Element implements CrawlConstants
             input.value = parse_message;
             return true;
         }
-        </script>
-        </div><?php
+    </script></div><?php
     }
 }
