<template>
<view class="audio-page">
<view class="box-left">
<image class="box-img" :src="props.image" mode="aspectFill"></image>
<view class="page-btn" @click="clickAudio">
<image :src="VF.music_play?VF.stop_img:VF.start_img" mode="widthFix"></image>
</view>
</view>
<view class="box-content">
<view class="content-name">{{props.title}}</view>
<view class="progress">
<text>{{getMinuteTime(VF.now_time)}}</text>
<slider :value="VF.now_time/VF.total_time*100" block-size="10" block-color="#FF3333"
activeColor="#FF3333" @change="sliderChange"></slider>
<text>{{getMinuteTime(VF.total_time)}}</text>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { onBeforeUnmount, onMounted, reactive } from 'vue';
interface Props {
autoplay : boolean,
music : string,
image : string,
title : number | string,
audioContext?: any, // 接收外部传入的音频实例
}
let props = withDefaults(defineProps<Props>(), {
autoplay: false,
music: '',
image: '',
title: '',
})
interface reactiveRules {
music_play : boolean,
AUDIO : any,
total_time : any,
now_time : any,
timeupdata : any,
interval : any,
start_img : string
stop_img : string
}
let VF = reactive<reactiveRules>({
music_play: false,
AUDIO: '',
total_time: 0,
now_time: 0,
timeupdata: '',
interval: '',
start_img: "",
stop_img: ""
})
onMounted(()=>{
initAudio()
})
const getMinuteTime = (data : any) => {
let minute : any = parseInt((data / 60).toString())
let second : any = parseInt((data % 60).toString())
if (minute.toString().length == 1) minute = `0${minute}`
if (second.toString().length == 1) second = `0${second}`
return `${minute}:${second}`
}
const clickAudio = () => {
if (!VF.AUDIO) return
if (VF.music_play) {
VF.music_play = false
VF.AUDIO.pause()
} else {
VF.music_play = true
VF.AUDIO.play()
}
}
const sliderChange = (e : any) => {
if (!VF.AUDIO) return
let second = e.detail.value / 100 * VF.total_time
VF.AUDIO.seek(second)
VF.now_time = second
}
const initAudio = () => {
// 销毁之前的实例
if (VF.AUDIO) {
VF.AUDIO.destroy()
}
// 使用传入的音频实例
if (props.audioContext) {
VF.AUDIO = props.audioContext;
console.log('使用外部传入的音频实例');
} else {
// 如果没有传入实例,则创建新的实例(兼容旧代码)
// #ifdef MP-WEIXIN
try {
VF.AUDIO = wx.createInnerAudioContext()
// 微信小程序特殊处理
wx.setInnerAudioOption({
obeyMuteSwitch: false, // 不遵循静音开关
speakerOn: true, // 开启扬声器播放
mixWithOther: true, // 与其他音频混播
success: function() {
console.log('音频选项设置成功');
},
fail: function(err) {
console.error('音频选项设置失败:', err);
}
});
} catch (error) {
console.error('创建音频实例失败:', error);
}
// #endif
// #ifndef !MP-WEIXIN
VF.AUDIO = uni.createInnerAudioContext()
// #endif
}
if (!VF.AUDIO) return
// 基本设置
VF.AUDIO.obeyMuteSwitch = false // 不遵循系统静音开关
VF.AUDIO.volume = 1 // 设置音量为最大
// #ifdef MP-WEIXIN
// 微信小程序下额外设置
VF.AUDIO.volume = 1; // 再次确保音量最大
// #endif
VF.AUDIO.src = props.music
// 事件监听
VF.AUDIO.onPlay(() => {
console.log('音频开始播放')
VF.music_play = true
// #ifdef MP-WEIXIN
// 播放时再次确认音量设置
VF.AUDIO.volume = 1;
// #endif
})
VF.AUDIO.onPause(() => {
console.log('音频暂停播放')
VF.music_play = false
})
VF.AUDIO.onStop(() => {
console.log('音频停止播放')
VF.music_play = false
VF.now_time = 0
})
VF.AUDIO.onEnded(() => {
console.log('音频播放结束')
VF.music_play = false
VF.now_time = 0
clearInterval(VF.timeupdata)
})
VF.AUDIO.onError((res) => {
console.error('音频播放错误:', res.errMsg, res.errCode)
VF.music_play = false
})
VF.AUDIO.onCanplay(() => {
console.log('音频准备就绪')
if (props.autoplay) {
VF.AUDIO.play()
VF.music_play = true
}
})
// 获取音频时长
VF.interval = setInterval(() => {
if (VF.AUDIO.duration != 0 && !isNaN(VF.AUDIO.duration)) {
VF.total_time = Math.round(VF.AUDIO.duration)
console.log("音频时长", VF.total_time)
clearInterval(VF.interval)
VF.AUDIO.play()
}
}, 100)
// 添加音量变化监听
// #ifdef MP-WEIXIN
// VF.AUDIO.onVolumeChange(() => {
// console.log('音量变化:', VF.AUDIO.volume)
// // 如果音量被设置为0,尝试恢复
// if (VF.AUDIO.volume === 0) {
// VF.AUDIO.volume = 1
// }
// })
VF.AUDIO.volume = 1
// #endif
// 更新播放进度的代码改为使用currentTime
VF.timeupdata = setInterval(() => {
if (VF.music_play) {
VF.now_time++
if (VF.now_time >= VF.total_time) {
VF.music_play = false
VF.now_time = 0
VF.AUDIO.stop()
clearInterval(VF.timeupdata)
}
}
}, 1000)
}
onBeforeUnmount(()=>{
if (VF.AUDIO) {
VF.music_play = false
VF.AUDIO.stop()
VF.AUDIO.destroy()
VF.AUDIO = null
}
clearInterval(VF.timeupdata)
clearInterval(VF.interval)
})
</script>
<style lang="scss">
.audio-page{
width: 100%;
height: 150upx;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 3upx 3upx 6upx #ccc;
.box-left{
width: 150upx;
height: 150upx;
position: relative;
display: flex;
.box-img{
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 2;
}
.page-btn{
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
left: 0;
top: 0;
z-index: 3;
image{
width: 50upx;
height: 50upx;
background-color: rgba($color: #000000, $alpha: 0.3);
border-radius: 50%;
}
}
}
.box-content{
flex: 1;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 30upx;
box-sizing: border-box;
font-size: 24upx;
.content-name{
width: 100%;
display: -webkit-box;/* 弹性盒模型 */
-webkit-box-orient: vertical;/* 元素垂直居中*/
-webkit-line-clamp: 1;/* 文字显示的行数*/
overflow:hidden;/* 超出隐藏 */
}
.progress{
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
slider{
width: 80%;
}
}
}
}
</style>

- 发布:2025-02-27 12:51
- 更新:2025-03-11 22:41
- 阅读:193
产品分类: uniapp/小程序/微信
PC开发环境操作系统: Windows
PC开发环境操作系统版本号: WIN10
HBuilderX类型: 正式
HBuilderX版本号: 4.53
第三方开发者工具版本号: 最新
基础库版本号: 最新
项目创建方式: HBuilderX
示例代码:
操作步骤:
调用组件,然后播放。
调用组件,然后播放。
预期结果:
正常播放,有声音。
<kk-audio
audioContext="globalAudioContext"
music="https://web-ext-storage.dcloud.net.cn/uni-app/ForElise.mp3"
title="音频标题"
/>
title="音频标题"
/>
实际结果:
不能正常播放。
不能正常播放。
bug描述:
有没有大佬可以指导下uni.createInnerAudioContext?
现在的情况是:
1、web上正常播放
2、小程序上设置autoplay,正常播放
3、点击按钮播放,没有声音。
再细一点解释下:
1、使用uni.createInnerAudioContext构建了一个播放器,在web上正常运行。
2、使用uni.createInnerAudioContext的方法,在页面onload后进行创建,关联src,autoplay,正常播放。
3、同2的使用,但是绑定button,手动触发play()方法,无效,不能播放。
4、查看实例,里面正常拥有src数据。且可以读出音频时长。但是点播放没有声音,也不知道是没有正常播放,还是没有声音。
以上情况都是小程序上不能正常使用。

DCloud_UNI_OttoJi - 日常回复 uni-app/x 问题,如果艾特我没看到,请主动私信
可能是你在开发阶段没有开启忽略网络白名单校验。我使用下面简单代码可以正常 play 和 autoplay
我测试 vue3 + 最新的 HBuilderX Alpha 可以正常运行到微信小程序模拟器,你可以结合我的代码修改并反馈
<template>
<view @click="start">start</view>
<view @click="play">play</view>
</template>
<script>
export default {
data() {
return {
ctx: null,
isPlaying: false
}
},
methods: {
play() {
if (this.ctx) {
if (this.isPlaying) {
this.ctx.pause()
this.isPlaying = false
} else {
this.ctx.play()
this.isPlaying = true
}
}
},
start() {
const innerAudioContext = uni.createInnerAudioContext();
this.ctx = innerAudioContext
innerAudioContext.autoplay = true;
innerAudioContext.src = 'https://web-ext-storage.dcloud.net.cn/uni-app/ForElise.mp3';
innerAudioContext.onPlay(() => {
console.log('开始播放');
});
innerAudioContext.onError((res) => {
console.log(res.errMsg);
console.log(res.errCode);
});
}
}
}
</script>

5***@163.com (作者)
无语了,还真就是Hbuilder 的问题。。。
我的排查步骤:
1、更新微信小程序基础库——bug依旧
2、更新微信开发者工具到最新——bug依旧
3、更新Hbuilder到最新——解决。。。
5***@163.com (作者)
我用你的源码试了下,这美妙的钢琴曲变成了噪音(太多实例)。而且我说的问题,其实被你复现了。自动播放正常,但暂停和播放功能无效。我的代码和你的代码,问题一样。
2025-03-11 12:10
5***@163.com (作者)
我试试更新下 hx,,,不能删IDE的锅吧???
2025-03-11 12:11
DCloud_UNI_OttoJi
回复 5***@163.com: 你升级下最新版 alpha,我复测是正常可以正常播放和暂停的,你再试一下?如果还有问题私聊我吧
2025-03-11 21:52
5***@163.com (作者)
回复 DCloud_UNI_OttoJi: 无语了,还真就是Hbuilder 的问题。。。
我的排查步骤:
1、更新微信小程序基础库——bug依旧
2、更新微信开发者工具到最新——bug依旧
3、更新Hbuilder到最新——解决。。。
2025-03-11 22:41