Merge branch 'develop' into feat/linear-backend
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import getUuid from 'widget/helpers/uuid';
|
||||
import 'video.js/dist/video-js.css';
|
||||
import 'videojs-record/dist/css/videojs.record.css';
|
||||
|
||||
@@ -28,6 +29,7 @@ import OpusRecorderEngine from 'videojs-record/dist/plugins/videojs.record.opus-
|
||||
|
||||
import { format, addSeconds } from 'date-fns';
|
||||
import { AUDIO_FORMATS } from 'shared/constants/messages';
|
||||
import { convertWavToMp3 } from './utils/mp3ConversionUtils';
|
||||
|
||||
WaveSurfer.microphone = MicrophonePlugin;
|
||||
|
||||
@@ -39,6 +41,10 @@ export default {
|
||||
type: String,
|
||||
default: AUDIO_FORMATS.WAV,
|
||||
},
|
||||
isAWhatsAppChannel: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -145,12 +151,17 @@ export default {
|
||||
stopRecord() {
|
||||
this.fireStateRecorderChanged('stopped');
|
||||
},
|
||||
finishRecord() {
|
||||
const file = new File(
|
||||
[this.player.recordedData],
|
||||
this.player.recordedData.name,
|
||||
{ type: this.player.recordedData.type }
|
||||
);
|
||||
async finishRecord() {
|
||||
let recordedContent = this.player.recordedData;
|
||||
let fileName = this.player.recordedData.name;
|
||||
if (this.isAWhatsAppChannel) {
|
||||
recordedContent = await convertWavToMp3(this.player.recordedData);
|
||||
fileName = `${getUuid()}.mp3`;
|
||||
}
|
||||
const type = !this.isAWhatsAppChannel
|
||||
? this.player.recordedData.type
|
||||
: 'audio/mp3';
|
||||
const file = new File([recordedContent], fileName, { type });
|
||||
this.fireRecorderBlob(file);
|
||||
},
|
||||
progressRecord() {
|
||||
@@ -231,11 +242,13 @@ export default {
|
||||
@apply bg-transparent max-h-60 min-h-[3rem] pt-4 px-0 pb-0 resize-none;
|
||||
}
|
||||
}
|
||||
|
||||
// Added to override the default text and bg style to support dark and light mode.
|
||||
.video-js .vjs-control-bar,
|
||||
.vjs-record.video-js .vjs-control.vjs-record-indicator:before {
|
||||
@apply text-slate-600 dark:text-slate-200 bg-transparent dark:bg-transparent;
|
||||
}
|
||||
|
||||
// Added to fix div overlays the screen and takes over the button clicks
|
||||
// https://github.com/collab-project/videojs-record/issues/688
|
||||
// https://github.com/collab-project/videojs-record/pull/709
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import lamejs from 'lamejs';
|
||||
/**
|
||||
* Encodes a mono channel audio stream to MP3 format.
|
||||
* @param {number} channels - Number of audio channels.
|
||||
* @param {number} sampleRate - Sample rate in Hz.
|
||||
* @param {Int16Array} samples - Audio samples to be encoded.
|
||||
* @returns {Blob} - The MP3 encoded audio as a Blob.
|
||||
*/
|
||||
export const encodeToMP3 = (channels, sampleRate, samples) => {
|
||||
const outputBuffer = [];
|
||||
const encoder = new lamejs.Mp3Encoder(channels, sampleRate, 128);
|
||||
const maxSamplesPerFrame = 1152;
|
||||
|
||||
for (let offset = 0; offset < samples.length; offset += maxSamplesPerFrame) {
|
||||
const sliceEnd = Math.min(offset + maxSamplesPerFrame, samples.length);
|
||||
const sampleSlice = samples.subarray(offset, sliceEnd);
|
||||
const mp3Buffer = encoder.encodeBuffer(sampleSlice);
|
||||
|
||||
if (mp3Buffer.length > 0) {
|
||||
outputBuffer.push(new Int8Array(mp3Buffer));
|
||||
}
|
||||
}
|
||||
|
||||
const remainingData = encoder.flush();
|
||||
if (remainingData.length > 0) {
|
||||
outputBuffer.push(new Int8Array(remainingData));
|
||||
}
|
||||
|
||||
return new Blob(outputBuffer, { type: 'audio/mp3' });
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a WAV audio Blob to an MP3 format Blob.
|
||||
* @param {Blob} blob - The audio data in WAV format as a Blob.
|
||||
* @returns {Promise<Blob>} - A Blob containing the MP3 encoded audio.
|
||||
*/
|
||||
export const convertWavToMp3 = async blob => {
|
||||
try {
|
||||
const audioBuffer = await blob.arrayBuffer();
|
||||
const wavHeader = lamejs.WavHeader.readHeader(new DataView(audioBuffer));
|
||||
const samples = new Int16Array(
|
||||
audioBuffer,
|
||||
wavHeader.dataOffset,
|
||||
wavHeader.dataLen / 2
|
||||
);
|
||||
|
||||
return encodeToMP3(wavHeader.channels, wavHeader.sampleRate, samples);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line
|
||||
console.log('Failed to convert WAV to MP3:', error);
|
||||
throw new Error('Conversion from WAV to MP3 failed.');
|
||||
}
|
||||
};
|
||||
@@ -53,6 +53,7 @@
|
||||
v-if="showAudioRecorderEditor"
|
||||
ref="audioRecorderInput"
|
||||
:audio-record-format="audioRecordFormat"
|
||||
:is-a-whats-app-channel="isAWhatsAppChannel"
|
||||
@state-recorder-progress-changed="onStateProgressRecorderChanged"
|
||||
@state-recorder-changed="onStateRecorderChanged"
|
||||
@finish-record="onFinishRecorder"
|
||||
@@ -501,11 +502,7 @@ export default {
|
||||
return `draft-${this.conversationIdByRoute}-${this.replyType}`;
|
||||
},
|
||||
audioRecordFormat() {
|
||||
if (
|
||||
this.isAWhatsAppChannel ||
|
||||
this.isAPIInbox ||
|
||||
this.isATelegramChannel
|
||||
) {
|
||||
if (this.isAPIInbox || this.isATelegramChannel) {
|
||||
return AUDIO_FORMATS.OGG;
|
||||
}
|
||||
return AUDIO_FORMATS.WAV;
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
"idb": "^7.1.1",
|
||||
"ionicons": "~2.0.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
"lamejs": "1.2.0",
|
||||
"libphonenumber-js": "^1.10.24",
|
||||
"markdown-it": "^13.0.2",
|
||||
"markdown-it-link-attributes": "^4.0.1",
|
||||
|
||||
@@ -14062,6 +14062,13 @@ klona@^2.0.4:
|
||||
resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0"
|
||||
integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==
|
||||
|
||||
lamejs@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/lamejs/-/lamejs-1.2.0.tgz#0259f83db4666141a7b671b8caa6369d95177d08"
|
||||
integrity sha512-xEYvsB2sZ9jIccqfUQpQEBdB6UYQDG/ta2xQkH7oEpENb0JHFJii965WVF8ErUMdZzoe7EdIruz1WpICdhZ9Pw==
|
||||
dependencies:
|
||||
use-strict "1.0.1"
|
||||
|
||||
language-subtag-registry@~0.3.2:
|
||||
version "0.3.21"
|
||||
resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a"
|
||||
@@ -20289,6 +20296,11 @@ urlpattern-polyfill@^6.0.2:
|
||||
dependencies:
|
||||
braces "^3.0.2"
|
||||
|
||||
use-strict@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/use-strict/-/use-strict-1.0.1.tgz#0bb80d94f49a4a05192b84a8c7d34e95f1a7e3a0"
|
||||
integrity sha512-IeiWvvEXfW5ltKVMkxq6FvNf2LojMKvB2OCeja6+ct24S1XOmQw2dGr2JyndwACWAGJva9B7yPHwAmeA9QCqAQ==
|
||||
|
||||
use@^3.1.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
|
||||
|
||||
Reference in New Issue
Block a user