江月照我眠
江月照我眠
  • 发布:2020-08-21 16:11
  • 更新:2022-06-15 14:40
  • 阅读:1831

【报Bug】setInterval中执行定时播放音频音效,时间间隔不准确

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: Win10

HBuilderX类型: 正式

HBuilderX版本号: 2.8.8

手机系统: Android

手机系统版本号: Android 10

手机厂商: 模拟器

手机机型: HUAWEI P30 Pro

页面类型: vue

打包方式: 云端

项目创建方式: HBuilderX

操作步骤:

同上

预期结果:

同上

实际结果:

同上

bug描述:

问题1
同样的代码在小程序中和H5中都做了实现,均可以正常跑通,测试无误。迁移到uniapp中,我现在onShow中初始化了一个播放器

this.innerAudioContext = uni.createInnerAudioContext();

然后在点击开始的时候使用setInterval以一定频率执行playAudio,以固定频率播放强弱音效

this.isPlay = setInterval(function() {  
    self.playAudio(type);  
}, time);
playAudio (type) {  
    if(type == 1){  
       var src = '../../static/audio/strong.mp3';  
    }else{  
       var src = '../../static/audio/week.mp3';  
    }  
			  
    let audio = this.innerAudioContext;  
    audio.src = src;  
    audio.seek = 0;  
    audio.play();  
}

结果是这个不是以稳定频率播放音效,时快时慢。

问题2
我在h5中实现了这个效果,在uniapp中尝试用webview打开h5页面,发现频率又变得不准确。

2020-08-21 16:11 负责人:DCloud_uniAD_HDX 分享
已邀请:
DCloud_uniAD_HDX

DCloud_uniAD_HDX

定时器间隔多长时间?
PC版Chrome 最大精度为 16 毫秒(算是最精准的了),但是会受界面及其他js逻辑的影响
如果想要精准定时器
1.定时器必须在webworker中
2.音频频繁创建也会有延时
3.建议方案,一次decode所有音频文件,需要时播放,不要来回换src现解码

或者将两个文件合并,循环播放

  • 江月照我眠 (作者)

    不好意思这两天没有上班,定时器500ms间隔。尝试过在onShow时创建两个播放器:strongAudio、weekAudio,需要时直接调用对应的播放器,设想中这样应该会省去创建的耗时,但是依然无果,还是偶尔会出现卡顿的现象。另外有个问题是为什么在H5中实现了,我用webview打开页面也会卡顿呢?


    2020-08-25 16:14

  • DCloud_uniAD_HDX

    回复 江月照我眠: 上面已经解释过了,如果在非worker中使用,会受主线程的影响,在哪里实现都会有同样问题


    2020-08-25 16:59

  • 江月照我眠 (作者)

    回复 DCloud_uniAD_HDX: 那我要怎么实现这个需求呢?“一次decode所有音频文件”是什么意思,麻烦大佬稍微解释一下,谢谢


    2020-08-25 17:15

  • 江月照我眠 (作者)

    回复 DCloud_uniAD_HDX: 另外我用webview打开h5页面,在h5中用个JS实现我要的效果,应该是独立的线程吧,为何也会受到影响呢?


    2020-08-26 10:59

DCMarvel

DCMarvel

setInterval 不准时 尝试改成setTimeout试试

  • 江月照我眠 (作者)

    我尝试过,还是会卡住,主要就是切换切换src和play那几下,耗时有时长有时短


    2020-08-25 16:16

江月照我眠

江月照我眠 (作者)

@DCloud_UNI_HDX 不知道你说的一次性decode所有音频文件是不是这意思:

var metronome = {  
	// 播放强音  
	playStrong:function(){  
		const strongAudioContext = uni.createInnerAudioContext();  
		strongAudioContext.autoplay = true;  
		strongAudioContext.src = 'https://api.dayinjiaoyu.cn/static/audio/strong.mp3';  
		strongAudioContext.onEnded(() => {  
			strongAudioContext.destroy();  
		});  
		strongAudioContext.onPlay(() => {  
			console.log('strong开始播放');  
		});  
		strongAudioContext.onError((res) => {  
		  	console.log(res.errMsg);  
		  	console.log(res.errCode);  
			strongAudioContext.destroy()  
		});  
	},  
	// 播放弱音  
	playWeek:function(){  
		const weekAudioContext = uni.createInnerAudioContext();  
		weekAudioContext.autoplay = true;  
		weekAudioContext.src = 'https://api.dayinjiaoyu.cn/static/audio/week.mp3';  
		weekAudioContext.onEnded(() => {  
			weekAudioContext.destroy();  
		});  
		weekAudioContext.onPlay(() => {  
			console.log('week开始播放');  
		});  
		weekAudioContext.onError((res) => {  
		  	console.log(res.errMsg);  
		  	console.log(res.errCode);  
			weekAudioContext.destroy();  
		});  
	}  
}  
  
module.exports = metronome;

引入这个js后直接在定时器中调用,没有进行src的切换,但是播放节奏还是不准确啊,真的很头疼,关于WebWorker的问题我看文档说的用web-view调用的js就是独立的线程,不该受主线程影响才对。。。

luch

luch

你把两个音频和成一个音频,循环播放这一个音频不就可了。

  • 江月照我眠 (作者)

    我这个音频有不同的节奏呀,比如ABABAB,ABBBABBB这种,还有切换频率还可以调整


    2020-08-26 15:26

  • luch

    回复 江月照我眠: 可以用队列解决吗


    2020-08-26 15:47

  • 江月照我眠 (作者)

    回复 luch: 不知道你有没有听说过节拍器,它是可以切换不同的频率和不同的节拍,用队列我想不太合适吧?uniapp支持队列吗?


    2020-08-26 15:56

DCloud_uniAD_HDX

DCloud_uniAD_HDX

如果是想实现节拍器,直接使用H5的webaudio,不过需要使用renderjs
app平台有通信延时问题,无法保证精准,且无法同时处理过多的复音

  • 江月照我眠 (作者)

    感谢回答 我先尝试一下


    2020-08-28 15:36

cmxXXX

cmxXXX

我也实现节拍器功能。也遇到同样的问题

要回复问题请先登录注册