likes
comments
collection
share

用空闲时间做了一个小程序-文字转语音2.0(获取语音时长)

作者站长头像
站长
· 阅读数 12

一直在摸鱼中赚钱的大家好呀~

自从小程序上次增加了一个文字转语音的功能之后,使用的用户不是很多,可能与这个功能实现有关系。当时只支持转换以及下载,这个下载功能还只能在小程序内部复制到资源链接,然后用户通过链接下载。没有办法很好的使用到这个功能,所以导致使用的用户不是很多。于是我就开始做语音分享给好友的功能,希望这次的更新可以有更多的鱼友们(没错就是你们)的使用。

用空闲时间做了一个小程序-文字转语音2.0(获取语音时长)

这次更新的内容是文字转语音的小工具支持将语音分享给用户以及修复已知BUG、部分页面UI优化。老规矩,先来看下知名UI设计师设计的UI图。

用空闲时间做了一个小程序-文字转语音2.0(获取语音时长) 用空闲时间做了一个小程序-文字转语音2.0(获取语音时长) 用空闲时间做了一个小程序-文字转语音2.0(获取语音时长)

既然可以支持分享给好友,那这个语音数据必须存储起来。表设计其实就很简单,只要语音ID 用户ID 文字内容 语音资源路径 状态 创建时间 这几个字段。分享的时候将这个语音ID传给分享的目标用户,通过语音ID查询分享的语音信息,然后在小程序中显示并支持播放。后端设计和逻辑其实并不难,比较繁琐的是小程序播放这块的逻辑和细节处理,下面就从小程序这边开始讲起。

从左边第一张UI图可以看出这个页面倒是没有什么太多的改动,只是将试听的按钮移动到输入框下、然后加上了一个分享的按钮。这边没有什么特别的难点,只要在分享前将这个语音数据创建,然后得到这个语音ID分享出去即可。我这边做的逻辑是不管点击哪个按钮都先判断是否生成过,如果没有生成都先请求接口创建语音数据,然后在进行下一步的操作。

当被分享者通过链接进入小程序时候会获取到语音ID,然后请求接口并通过接口返回的数据判断语音是否失效 (由于语音文件是存储在服务本地的且楼主的口袋太干净了,所以要定期的删除文件以释放空间) 若是失效直接弹出提示告知用户已经失效。

用空闲时间做了一个小程序-文字转语音2.0(获取语音时长)

我在开发中主要遇到的难点就在上图的实现过程中:

第一个难点:获取语音的时长

本来获取时长并不是什么难的事,只是我在微信小程序开发中踩到了一些坑。先介绍一下wx.createInnerAudioContext API:用于创建内部 audio 上下文 InnerAudioContext 对象。

InnerAudioContext中有几个属性和方法会在下面的实现中用到:

  • src:音频资源的地址,用于直接播放
  • currentTime:当前音频的播放位置(单位 s)
  • duration:当前音频的长度(单位 s)
  • play:播放的方法
  • pause:暂停的方法
  • onCanplay:监听音频进入可以播放状态的事件
  • onPlay:监听音频播放事件
  • onTimeUpdate: 监听音频播放进度更新事件
  • onPause: 监听音频暂停事件
  • onError: 监听音频播放错误事件

通过上面两个属性看来获取音频的时长并不是什么困难的事,困难的是获取duration这个属性的时机。在创建了InnerAudioContext 对象并设置了src属性后调用audio.duration属性发现获取到的值是0,既然此路不通那只能另寻它路。

通过官方文档发现onCanplay这个监听事件,在这个方法里面尝试调用audio.duration属性确实是能获取到正确的值。但是从UI图中可以看到这个并不符合我的需求,我需要在播放之前就获取到时长,所以这条路也放弃。

最后通过官方文档发现了onCanplay这个监听事件,然后在这个方法里面尝试调用audio.duration属性发现获取到的值是NaN。这个时候我已经开始骂人了 (此处省略万个字符)。然后通过查找官方论坛发现可以使用setTimeout获取到时长,然后我再onCanplay监听事件中调用audio.duration属性发现获取到的值任然是NaN (不管设置多长时间都是如此)。到这个时候我已经吐血了。功夫不负有心人,在我调试过程中发现:只要在onCanplay这个监听事件调用过audio.duration这个属性,那setTimeout中调用audio.duration就会获取到正确的时长。到此这个难题就已经解决了,我个人的看法我觉得这是官方的BUG,希望官方可以修复掉这个问题。下面贴上部分实现代码:

const { url } = this.data.info
const audio = wx.createInnerAudioContext('audio')
audio.src = url
audio.onCanplay(() => {
    audio.duration;
    setTimeout(() => {
      const duration = audio.duration
      this.setData({ duration, durationText: Math.ceil(duration) + 's' })
    }, 10000)
})
this.setData({ audio })

由于篇幅太长,这篇文章就讲这一个难点。下篇文章讲播放进度条的实现。

感谢大家观看我今日的水文,文笔实在是不行,欢迎鱼友们给小程序提提意见,或者有什么有趣的想法也可以与楼主提一提。最后希望大家到我的小程序来多坐坐。

最后的最后,如果觉得文章不错的话,可以给小生的几个开源项目点个Star⭐!

转载自:https://juejin.cn/post/7282692458256105507
评论
请登录