vue3实现录音并播放

<template>
    <div class="container">
        <div class="step-box">
            <div class="min-box">
            </div>
            <tiny-time-line :data="dataLine" :active="normalActive" type="normal"></tiny-time-line>
        </div>
        <div class="describe-box">
            <div class="test-box">
                <div class="title">欢迎您即将开始北英测评考试,请准备好耳机,点击下面【播放】图标,并调整好您的音量。</div>
                <div :class="normalActive == 0 ? 'btn-box btn-box-active' : 'btn-box'" @click="stepOne">
                    <img v-show="normalActive == 0" src="../../../assets/images/laba.png" alt="">
                    <img v-show="normalActive !== 0" src="../../../assets/images/labaactive.png" alt="">
                    <span :class="normalActive == 0 ? 'white' : ''">Put on your headphones and click here Play Sound</span>
                </div>
            </div>
            <div class="test-box">
                <div class="title">请您打开麦克风,调整好音量后,点击下面图标,向我们打招呼吧</div>
                <div :class="normalActive == 1 ? 'btn-box btn-box-active' : 'btn-box'" @click="stepTwo">
                    <img style="width: .42rem;height:.69rem" v-show="normalActive == 1"
                        src="../../../assets/images/maikefeng.png" alt="">
                    <img style="width: .42rem;height:.69rem" v-show="normalActive !== 1"
                        src="../../../assets/images/maikefengactive.png" alt="">
                    <span :class="normalActive == 1 ? 'white' : ''">Open your microphone and set the volume level
                        properly</span>
                </div>
            </div>
            <div class="test-box">
                <div class="title">点击下面图标,看看能否成功听到自己的声音</div>
                <div :class="normalActive == 2 ? 'btn-box btn-box-active' : 'btn-box'" @click="stepThree">
                    <img v-show="normalActive == 2" src="../../../assets/images/bofang.png" alt="">
                    <img v-show="normalActive !== 2" src="../../../assets/images/bofangicon.png" alt="">
                    <span :class="normalActive == 2 ? 'white' : ''">Click on Play Sound. If you cannot hear the sound,change
                        the
                        volume on your device</span>
                </div>
            </div>
        </div>
        <div class="nextStep">
            <div class="nextStepTitle" v-show="!disabled">一切正常,我们就开始吧!</div>
            <div class="nextStepBtn">
                <tiny-button :disabled="disabled" type="primary" native-type="submit" @click="nextStep"> 检测完成 </tiny-button>
            </div>
        </div>

        <tiny-dialog-box v-model:visible="boxVisibility" :modal="false" :title="dialogText.title" width="30%" top="30%">
            <span v-html="dialogText.describe"></span>
            <template #footer>
                <tiny-button type="primary" @click="confrim"> {{ dialogText.sureBtn }} </tiny-button>
                <tiny-button @click="boxVisibility = false"> {{ dialogText.cancleBtn }} </tiny-button>
            </template>
        </tiny-dialog-box>
        <!-- <div class="dialog" v-show="boxVisibility">
            <tiny-button type="primary" @click="confrim"> {{ dialogText.sureBtn }} </tiny-button>
        </div> -->

        <!-- <pointOut></pointOut> -->
    </div>
</template>

<script setup>
// 数据、VUE模块、第三方UI组件库的引入
import { reactive, ref, onMounted, createApp } from 'vue'
import { TimeLine as TinyTimeLine, Modal, Button as TinyButton, DialogBox as TinyDialogBox, Notify } from '@opentiny/vue'
import { useRouter } from 'vue-router'
import Recorder from 'js-audio-recorder'


const data = reactive({
    //用于存储创建的语音对象
    recorder: null,
    formData: null,
    // 控制录音动画的显示隐藏
    showAnima: false,
    mation: true,
    isHistory: true,
    // 录音时长
    duration: 0,
    submit() { // 发送语音的方法
        data.recorder.pause() // 暂停录音
        data.timer = null
        console.log('上传录音')// 上传录音
        var formData = new FormData()
        var blob = data.recorder.getWAVBlob()//获取wav格式音频数据
        //此处获取到blob对象后需要设置fileName满足当前项目上传需求,其它项目可直接传把blob作为		  file塞入formData
        var newbolb = new Blob([blob], { type: 'audio/wav' })
        var fileOfBlob = new File([newbolb], new Date().getTime() + '.wav')
        //formData是传给后端的对象,
        formData.append('file', fileOfBlob)
        //计算出录音时长
        data.duration = Math.ceil((new Date() - data.duration) / 1000);
        console.log(data.duration);
        //发送给后端的方法
        sendAudio(formData).then(res => {
            console.log(res);
        })
    },
    // 录音按钮的点击事件
    voice() {
        //实例化语音对象
        data.recorder = new Recorder({
            sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
            sampleRate: 16000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
            numChannels: 1 // 声道,支持 1 或 2, 默认是1
        })
        //记录开始录音的时间
        data.duration = new Date();
        Recorder.getPermission().then(() => {
            console.log('开始录音')
            data.recorder.start() // 开始录音
        }, (error) => {
            console.log(`${error.name} : ${error.message}`)
        })
    },
    handleStop() {
        console.log('停止录音')
        data.recorder.stop() // 停止录音
        data.mation = false;
    },
    handlePlay() {
        console.log('播放录音')
        data.recorder.play() // 播放录音
    },
    handleDestroy() {
        console.log('销毁实例')
        if (data.recorder) {
            data.recorder.destroy() // 毁实例
        }
    },
})

// 页面数据的定义
const normalActive = ref(0) //步骤条的控制
const disabled = ref(true) //判断检测完成按钮时都可以点击
const boxVisibility = ref(false) //控制dialog的显示与隐藏

// 步骤条的描述文字
const dataLine = ref([{ name: '耳机检测' }, { name: '麦克风检测' }, { name: '录音播放' }])
// dialog里面的内容字段
const dialogText = reactive({
    title: '步骤一:耳机检测',
    describe: '是否可以听清播放内容',
    cancleBtn: '不可以',
    sureBtn: '可以'
})
const app = createApp({})

const router = useRouter()

app.component({
    // pointOut
})

// 进入页面获取麦克风权限
onMounted(() => {

})

function nextStep() {
    router.push({
        path: '/secondaryAnswer'
    })
}

// 耳机测试
function stepOne() {
    if (normalActive.value == 0) {
        setTimeout(() => {
            boxVisibility.value = true
        }, 2000)
    }
}

// 麦克风测试
const stepTwo = function () {
    if (normalActive.value == 1) {
        // 录音
        data.voice()

        dialogText.title = '步骤二:麦克风检测'
        dialogText.describe = `请阅读以下内容:</br><p>You are not strong, no one strong for you.</p>`
        dialogText.sureBtn = '阅读完毕'
        dialogText.cancleBtn = '返回'
        boxVisibility.value = true
    }
}

// 听取录音设置
const stepThree = function () {
    if (normalActive.value == 2) {
        // 播放录音
        data.handleStop()
        data.handlePlay()


        // console.log(normalActive)
        dialogText.title = '步骤二:录音播放'
        dialogText.describe = `可以听清楚自己的录音吗?`
        dialogText.sureBtn = '可以'
        dialogText.cancleBtn = '不可以'
        setTimeout(() => {
            boxVisibility.value = true
        }, 2000)

    }
}

const confrim = function () {
    // 点击的第二个步骤的时候,结束录音机的录制
    if (normalActive.value == 1) {

    }
    // 判断是否是第三个步骤,是的话normalActive禁止++
    if (normalActive.value !== 2) {
        normalActive.value++
    } else {
        disabled.value = false
    }
    boxVisibility.value = false
}

</script>

<style lang="scss" scoped>
.container {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    position: relative;
    // border: 1px solid red;

    // border: 1px solid red;
    .dialog {
        position: fixed;
        top: 0;
        left: 0;
        background-color: rgb(202, 205, 207, .4);
        width: 10rem;
        height: 10rem;
    }

    .step-box {
        height: .56rem;
        width: 100%;
        border-radius: .17rem;
        margin-top: .49rem;
        display: flex;
        align-items: center;
        position: relative;

        .min-box {
            position: absolute;
            border-radius: .17rem;
            // border: 1px solid red;
            background-color: #fff;
            width: 80%;
            left: 10%;
            height: .56rem;
        }

        // border: 1px solid red;
        .tiny-steps {
            width: 100%;
        }
    }

    .describe-box {
        width: 100%;
        margin-top: .49rem;
        display: flex;
        justify-content: space-evenly;

        .test-box {
            width: 2.78rem;

            // border: 1px solid red;
            .title {
                width: 2.72rem;
                height: .49rem;
                margin: 0 auto;
                font-size: .08rem;
            }

            .btn-box {
                width: 100%;
                height: 1.35rem;
                border-radius: .21rem;
                display: flex;
                background-color: #fff;
                justify-content: center;
                align-items: center;

                img {
                    width: .69rem;
                    height: .52rem;
                }

                span {
                    width: 1.61rem;
                    margin-left: .17rem;
                    font-size: .08rem;
                    color: #000;
                }

                .white {
                    width: 1.61rem;
                    margin-left: .17rem;
                    font-size: .08rem;
                    color: white;
                }
            }

            .btn-box-active {
                width: 100%;
                height: 1.35rem;
                border-radius: .21rem;
                display: flex;
                background-color: #4696e9;
                justify-content: center;
                align-items: center;
            }
        }
    }

    .nextStep {
        display: flex;
        align-content: center;
        justify-content: center;
        flex-direction: column;
        margin-top: .38rem;

        .nextStepTitle {
            font-size: .08rem;
            letter-spacing: 0rem;
            line-height: .16rem;
            color: rgba(25, 151, 240, 1);
            text-align: center;
        }

        .nextStepBtn {
            margin: 0 auto;
            width: 2.85rem;
            height: .38rem;
            opacity: 1;
            border-radius: .21rem;
            margin-top: .07rem;

            .tiny-button {
                width: 2.85rem;
                height: .24rem;
                margin: 0 auto;
                font-size: .11rem;
                border-radius: .13rem;
            }
        }
    }
}
</style>>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值