pcm-player icon indicating copy to clipboard operation
pcm-player copied to clipboard

onended回调函数,在播放途中会多次触发

Open be-leo opened this issue 1 year ago • 12 comments

目前使用websocket持续接收后端传回来的音频流,然后调用feed持续进行播放,然后在播放途中会多次触发onended。播放的音频越长,onended触发的次数就越多。在使用中,feed了大概20次,后端ws传输音频中间没有断,在播放中onended大概会触发3、4次。

be-leo avatar May 20 '24 01:05 be-leo

现在挂的onended事件是挂在了每段音频素材上,这里可能会有歧义。因为是音频流形式,所以没有严格意义上的音频结束的概念。

pkjy avatar May 24 '24 14:05 pkjy

老师,现在有能判断该Player是否在播放语音的方法或方式吗?

be-leo avatar May 27 '24 04:05 be-leo

老师,现在有能判断该Player是否在播放语音的方法或方式吗?

你的场景是怎样的? 我看下如何处理下

pkjy avatar May 27 '24 09:05 pkjy

在播放途中会展示关闭播放按钮,播放完成隐藏掉关闭播放按钮,所以现在这个按钮显隐不太好控制

be-leo avatar May 28 '24 03:05 be-leo

在播放途中会展示关闭播放按钮,播放完成隐藏掉关闭播放按钮,所以现在这个按钮显隐不太好控制

整个数据都是流式的,通过数据并不好判断是否播放完成。难道音频数据一段时间为空就识别为播放完成?我觉得是不合适的,万一某些音频里面有比较长的静止阶段呢。个人建议比较好的方案是,后端音频传完后,发送一个播放完成的事件给前端,前端通过这个标记来做处理,而不是去依赖音频数据来识别播放完毕。

pkjy avatar May 30 '24 03:05 pkjy

也遇到了同样问题。实际中后端音频只是负责传送到前端,前端流式接收后,其实早早就与后端断开了,其余的就是前端一直播放着音频。因此是否还是需要根据音频实际数据才能标识是否结束,或者流式中有什么标识可以告诉流式结束了。

在播放途中会展示关闭播放按钮,播放完成隐藏掉关闭播放按钮,所以现在这个按钮显隐不太好控制

整个数据都是流式的,通过数据并不好判断是否播放完成。难道音频数据一段时间为空就识别为播放完成?我觉得是不合适的,万一某些音频里面有比较长的静止阶段呢。个人建议比较好的方案是,后端音频传完后,发送一个播放完成的事件给前端,前端通过这个标记来做处理,而不是去依赖音频数据来识别播放完毕。

Waldenz avatar Jun 07 '24 23:06 Waldenz

在播放途中会展示关闭播放按钮,播放完成隐藏掉关闭播放按钮,所以现在这个按钮显隐不太好控制

整个数据都是流式的,通过数据并不好判断是否播放完成。难道音频数据一段时间为空就识别为播放完成?我觉得是不合适的,万一某些音频里面有比较长的静止阶段呢。个人建议比较好的方案是,后端音频传完后,发送一个播放完成的事件给前端,前端通过这个标记来做处理,而不是去依赖音频数据来识别播放完毕。

确实是不好根据ws是否传送完音频数据进行判断,因为ws传输音频流很快,播放的音频速度很慢,ws可能1s就传完了,但是语音才刚开始播放,所以想向您寻求帮助,看看咱们的这个插件是否能解决

be-leo avatar Jun 18 '24 01:06 be-leo

在播放过程中会显示关闭播放按钮,播放隐藏掉关闭播放按钮,所以现在这个按钮显隐不太好控制

整个数据都是流式的,通过数据不好判断完成。考虑音频数据片段时间是否为空就识别为播放完成?我觉得是不合适的,万一某些音频播放里面有比较长的静止阶段个人建议比较好的方案是,耳机音频传输完成后,发送一个播放完成的事件给前端,而不是通过这个标记进行处理,去依赖音频数据来识别播放完毕。

确实不好根据ws传送是否完成音频数据进行判断,因为ws传输流很快,播放的音频音频速度很慢,ws可能1s就传完了,但是语音才刚刚开始播放,所以想向您寻求帮助,看看看我们的这个插件是否能解决

@be-leo 解决了吗

mimimamahaoduozi avatar Aug 07 '24 02:08 mimimamahaoduozi

flush()我加了个计数值和onallended方法 var bufferSource = this.audioCtx.createBufferSource(); this.bufferSourceNumber = this.bufferSourceNumber + 1; if (typeof this.option.onended === "function") { bufferSource.onended = function (event) { self.bufferSourceNumberOfEnd = self.bufferSourceNumberOfEnd + 1; self.option.onended( this, event, self.bufferSourceNumberOfEnd, self.bufferSourceNumber ); if (typeof self.option.onallended === "function") { if (self.bufferSourceNumber == self.bufferSourceNumberOfEnd) { self.option.onallended( this, event, self.bufferSourceNumberOfEnd, self.bufferSourceNumber ); } } }; }

qzzhujixue avatar Aug 10 '24 04:08 qzzhujixue

通过pcm数据来判断是不太好处理的。就是客户端没有很好的办法判断音频流的结束。

建议通过websocket连接断开来判断,如果播放结束,服务端断开此次连接,然后客户端监听close来处理。 或者websocket里面塞入一个结束信号,比如传入一个END字符串进去,如果客户端识别到了,就知道音频数据已传完。

从播放器角度来看,还未想到什么好办法能解决这个问题。

pkjy avatar Nov 06 '24 01:11 pkjy

onended其实只是某一段播放完了,并不代表着全部播放完了。 因为feed()可能执行多次,都会合并成一个samples。执行flush会对所有的samples做处理,导致一个问题:onended触发次数会<=feed方法的次数(flushTime值越大,越明显)

我的方式: 1、把flushTime设置为0,源码里改成0就不执行定时器。 2、维护一个是否结束了的队列。 3、在ws的接收处: 队列.push(是否结束),并手动触发 player.flush() 4、在onended处: const 是否结束 = 队列.shift() 5、当为true时表示最后一次。

说明:3 的是否结束要后端传过来进行标识

zhuxiwen avatar Dec 12 '24 06:12 zhuxiwen

onended其实只是某一段播放完了,并不代表着全部播放完了。 因为feed()可能执行多次,都会合并成一个samples。执行flush会对所有的samples做处理,导致一个问题:onended触发次数会<=feed方法的次数(flushTime值越大,越明显)

我的方式: 1、把flushTime设置为0,源码里改成0就不执行定时器。 2、维护一个是否结束了的队列。 3、在ws的接收处: 队列.push(是否结束),并手动触发 player.flush() 4、在onended处: const 是否结束 = 队列.shift() 5、当为true时表示最后一次。

说明:3 的是否结束要后端传过来进行标识

https://github.com/pkjy/pcm-player/pull/25

zhuxiwen avatar Dec 12 '24 07:12 zhuxiwen