mirror of
https://gitee.com/yudaocode/yudao-ui-admin-vben.git
synced 2025-12-30 02:22:25 +00:00
91 lines
2.0 KiB
Vue
91 lines
2.0 KiB
Vue
<script lang="ts" setup>
|
||
import { ref } from 'vue';
|
||
|
||
import { IconifyIcon } from '@vben/icons';
|
||
|
||
// 因为微信语音是 amr 格式,所以需要用到 amr 解码器:https://www.npmjs.com/package/benz-amr-recorder
|
||
import BenzAMRRecorder from 'benz-amr-recorder';
|
||
import { ElTag } from 'element-plus';
|
||
|
||
/** 微信消息 - 语音 */
|
||
defineOptions({ name: 'WxVoicePlayer' });
|
||
|
||
const props = withDefaults(
|
||
defineProps<{
|
||
content?: string; // 语音文本
|
||
url: string; // 语音地址,例如说:https://www.iocoder.cn/xxx.amr
|
||
}>(),
|
||
{
|
||
content: '',
|
||
},
|
||
);
|
||
|
||
const amr = ref<any>();
|
||
const playing = ref(false);
|
||
const duration = ref<number>();
|
||
|
||
/** 处理点击,播放或暂停 */
|
||
function playVoice() {
|
||
// 情况一:未初始化,则创建 BenzAMRRecorder
|
||
if (amr.value === undefined) {
|
||
amrInit();
|
||
return;
|
||
}
|
||
// 情况二:已经初始化,则根据情况播放或暂时
|
||
if (amr.value.isPlaying()) {
|
||
amrStop();
|
||
} else {
|
||
amrPlay();
|
||
}
|
||
}
|
||
|
||
/** 音频初始化 */
|
||
function amrInit() {
|
||
amr.value = new BenzAMRRecorder();
|
||
// 设置播放
|
||
amr.value.initWithUrl(props.url).then(() => {
|
||
amrPlay();
|
||
duration.value = amr.value.getDuration();
|
||
});
|
||
// 监听暂停
|
||
amr.value.onEnded(() => {
|
||
playing.value = false;
|
||
});
|
||
}
|
||
|
||
/** 音频播放 */
|
||
function amrPlay() {
|
||
playing.value = true;
|
||
amr.value.play();
|
||
}
|
||
|
||
/** 音频暂停 */
|
||
function amrStop() {
|
||
playing.value = false;
|
||
amr.value.stop();
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div
|
||
class="flex h-[50px] w-[120px] cursor-pointer items-center justify-center rounded-[10px] bg-[#eaeaea] p-[5px]"
|
||
@click="playVoice"
|
||
>
|
||
<el-icon>
|
||
<IconifyIcon
|
||
v-if="playing !== true"
|
||
icon="lucide:circle-play"
|
||
:size="32"
|
||
/>
|
||
<IconifyIcon v-else icon="lucide:circle-pause" :size="32" />
|
||
<span v-if="duration" class="ml-[5px] text-[11px]">
|
||
{{ duration }} 秒
|
||
</span>
|
||
</el-icon>
|
||
<div v-if="content">
|
||
<ElTag type="success" size="small">语音识别</ElTag>
|
||
{{ content }}
|
||
</div>
|
||
</div>
|
||
</template>
|