From 1d336575690dfe2721e8fbe2646b54eae0e0ec5b Mon Sep 17 00:00:00 2001 From: N-Pex Date: Fri, 25 Oct 2024 11:56:27 +0200 Subject: [PATCH] Generate base64 waveform in audio message body --- src/components/messages/AudioPlayer.vue | 7 ++ src/components/messages/AudioWaveformView.vue | 79 +++++++++++++++++++ src/plugins/utils.js | 39 +++++++++ 3 files changed, 125 insertions(+) create mode 100644 src/components/messages/AudioWaveformView.vue diff --git a/src/components/messages/AudioPlayer.vue b/src/components/messages/AudioPlayer.vue index cf7472c..f0194b3 100644 --- a/src/components/messages/AudioPlayer.vue +++ b/src/components/messages/AudioPlayer.vue @@ -6,15 +6,22 @@
{{ currentTime }} / {{ totalTime }}
+
+
+ +
+
+ + \ No newline at end of file diff --git a/src/plugins/utils.js b/src/plugins/utils.js index 56368b3..6af17d5 100644 --- a/src/plugins/utils.js +++ b/src/plugins/utils.js @@ -424,6 +424,9 @@ class Util { promise .then((response) => { messageContent.url = response.content_uri; + return (msgtype == 'm.audio' ? this.generateWaveform(fileContents, messageContent) : true); + }) + .then(() => { return this.sendMessage(matrixClient, roomId, "m.room.message", messageContent) }) .then(result => { @@ -478,6 +481,9 @@ class Util { return reject(response.error); } encryptedFile.url = response.content_uri; + return (msgtype == 'm.audio' ? this.generateWaveform(fileContents, messageContent) : true); + }) + .then(() => { return this.sendMessage(matrixClient, roomId, "m.room.message", messageContent) }) .then(result => { @@ -495,6 +501,39 @@ class Util { return uploadPromise; } + generateWaveform(data, messageContent) { + const audioCtx = new (window.AudioContext || window.webkitAudioContext)(); + if (audioCtx) { + return audioCtx.decodeAudioData(data) + .then((audioBuffer) => { + const rawData = audioBuffer.getChannelData(0); // We only need to work with one channel of data + const samples = 1000; // Number of samples we want to have in our final data set + const blockSize = Math.floor(rawData.length / samples); // the number of samples in each subdivision + let filteredData = []; + for (let i = 0; i < samples; i++) { + let blockStart = blockSize * i; // the location of the first sample in the block + let sum = 0; + for (let j = 0; j < blockSize; j++) { + sum = sum + Math.abs(rawData[blockStart + j]) // find the sum of all the samples in the block + } + filteredData.push(sum / blockSize); // divide the sum by the block size to get the average + } + + // Normalize + const multiplier = Math.pow(Math.max(...filteredData), -1); + filteredData = filteredData.map(n => n * multiplier); + + // Integerize + filteredData = filteredData.map(n => parseInt((n * 255).toFixed())); + + const base64 = Buffer.from(filteredData).toString('base64'); //.replace(/=/g, '') + console.log("BASE64", base64); + messageContent.format = "org.matrix.custom.html"; + messageContent.formatted_body = base64; + }) + } + } + /** * Return what "mode" to use for the given room. *