<template> <div class="my-vue-audio-recorder"> <button v-if="!recorder" @click.prevent="record()" class="btn start-record-btn" > <svg class="icon icon-Component-85--1"> <use xlink:href="#icon-Component-85--1"></use> </svg> </button> <button v-else @click.prevent="stop()" class="btn send-record-btn"> <svg class="icon icon-Component-236--1"> <use xlink:href="#icon-Component-236--1"></use> </svg> </button> <button @click.prevent="cancel()" class="btn remove-record-btn" :class="{ recording: recorder }" > <svg class="icon icon-Component-295--1"> <use xlink:href="#icon-Component-295--1"></use> </svg> </button> </div> </template> <script> // import "assets/common/js/RecordRTC.js"; /** * @vue-data {Object|null} [newAudio=null] - صدای جدید * @vue-data {Object|null} [recorder=null] - ضبط کننده * @vue-data {Boolean} [saveAudio=false] - نشان میدهد که آیا صدای ضبط شده ذخیره شود یا خیر * @vue-data {Array} [recordedChunks=[]] - تکههای صدای ضبط شده */ export default { mounted() { // this.uuid = Math.floor(Math.random() * 100); // addJsCssFileToDom("/js/RecordRTC.js", "js", this.uuid); // this.getLocalStream(); }, destroy() { this.recorder?.removeEventListener("dataavailable", onDataAvailable); this.recorder?.removeEventListener("stop", onStopRecording); }, data() { return { newAudio: null, recorder: null, saveAudio: false, recordedChunks: [], }; }, computed: { // newAudioURL() { // return URL.createObjectURL(this.newAudio); // }, }, methods: { /** * هنگامی که دادههای صوتی در دسترس هستند، این متد اجرا میشود. * تکههای ضبط شده را ذخیره کرده و یک رویداد ارسال میکند. * * @param {Event} e - رویداد دادههای موجود */ onDataAvailable(e) { this.recordedChunks = []; this.$emit("onStream"); if (e.data.size > 0) { this.recordedChunks.push(e.data); } }, /** * توقف ضبط و پردازش جریان رسانهای. * تکههای ضبط شده را به یک Blob تبدیل کرده و آن را ارسال میکند. * * @param {Event} mediaStream2 - رویداد جریان رسانهای */ onStopRecording(mediaStream2) { this.newAudio = new Blob(this.recordedChunks); this.recorder.stop(); const audioTracks = mediaStream2.target.stream.getAudioTracks(); audioTracks.forEach((element) => { element.stop(); }); this.recorder = null; if (this.saveAudio) this.$emit("send", this.newAudio); }, /** * شروع ضبط صدا. * درخواست دسترسی به میکروفون کاربر و شروع ضبط صدا. */ async record() { this.newAudio = null; try { const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false, }); // const options = { mimeType: "audio/webm" }; // this.recorder = new MediaRecorder(mediaStream, options); this.recorder = new MediaRecorder(mediaStream); this.recorder.start(); this.recorder.addEventListener("dataavailable", this.onDataAvailable); this.recorder.addEventListener("stop", this.onStopRecording); } catch (err) { mySwalToast({ title: "مرورگر شما از قابلیت ارسال صدا پشتیبانی نمیکند.لطفا مرورگر خود را به آخرین ورژن ارتقا دهید.", icon: "error", timer: 7000, }); } }, /** * توقف ضبط و ذخیره فایل صوتی. */ stop() { this.saveAudio = true; this.recorder.stop(); }, /** * لغو ضبط بدون ذخیره فایل صوتی. */ cancel() { this.saveAudio = false; this.recorder.stop(); }, // با استفاده از پلاگین // getLocalStream() { // try { // navigator.mediaDevices // .getUserMedia({ // video: false, // audio: true, // }) // .then(async function (stream) { // let recorder = RecordRTC(stream, { // type: "audio", // }); // recorder.startRecording(); // const sleep = (m) => new Promise((r) => setTimeout(r, m)); // await sleep(3000); // recorder.stopRecording(function () { // let blob = recorder.getBlob(); // invokeSaveAsDialog(blob); // }); // }); // navigator.mediaDevices // .getUserMedia({ video: false, audio: true }) // .then((stream) => { // window.localStream = stream; // A // window.localAudio.srcObject = stream; // B // window.localAudio.autoplay = true; // C // }) // .catch((err) => { // console.error(`you got an error: ${err}`); // }); // } catch (err) { // let localStream = new MediaStream(); // let localAudioTrack; // let localVideoTrack; // let localVideo; // const userMediaConstraints = { // video: true, // audio: true, // }; // navigator.mediaDevices = localStream; // .getUserMedia(userMediaConstraints) // .then((stream) => { // localAudioTrack = stream.getAudioTracks()[0]; // localAudioTrack.enabled = true; // localStream.addTrack(localAudioTrack); // }); // } // }, }, }; </script> <style scoped lang="scss"> // .vue-audio-recorder { // position: relative; // background-color: #4db6ac; // border-radius: 50%; // width: 64px; // height: 64px; // display: inline-block; // cursor: pointer; // -webkit-box-shadow: 0 0 0 0 rgba(232,76,61,.7); // box-shadow: 0 0 0 0 rgba(232,76,61,.7); // width: 1.9em; // height: 1.9em; // padding: 0.5em; // background-size: 70%; // background-position: center center; // background-repeat: no-repeat; // &.active { // background-color: #ef5350; // -webkit-animation: pulse 1.25s cubic-bezier(.66,0,0,1) infinite; // animation: pulse 1.25s cubic-bezier(.66,0,0,1) infinite; // } // } </style>