CustomRecorder.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <template>
  2. <view class="custom-recorder">
  3. <view class="record-file-list" v-if="list.length">
  4. <view class="record-file-list-item" v-for="(item, index) in list" :key="index">
  5. {{item.path}}
  6. </view>
  7. </view>
  8. <uni-popup ref="popup" type="bottom" class="pop-up-box">
  9. <view class="pop-up-content">
  10. <view class="content-header">
  11. 音频录音
  12. </view>
  13. <view class="content-body">
  14. <view class="content-body-duration">
  15. {{duration}}
  16. </view>
  17. <view class="icon">
  18. </view>
  19. <view class="btn">
  20. <button style="height: 68rpx;line-height: 68rpx;border-radius: 1998rpx;" type="primary"
  21. @longpress="handleStart" @touchcancel="handleStop"
  22. @touchend="handleStop">{{btnText[recordStatus]}}</button>
  23. </view>
  24. </view>
  25. </view>
  26. </uni-popup>
  27. </view>
  28. </template>
  29. <script>
  30. import moment from 'moment';
  31. // #ifdef APP-PLUS
  32. console.log('走的app')
  33. const recorder = plus.audio.getRecorder();
  34. const player = plus.audio.createPlayer({
  35. autoplay: false
  36. });
  37. // #endif
  38. // #ifdef MP-WEIXIN
  39. console.log('走的微信')
  40. const recorder = wx.getRecorderManager();
  41. const player = wx.createInnerAudioContext();
  42. // #endif
  43. export default {
  44. data() {
  45. return {
  46. list: [],
  47. duration: "00:00:00",
  48. recordStatus: "stop",
  49. btnText: {
  50. stop: "按住说话",
  51. start: "说完了"
  52. },
  53. voicePath: '',
  54. realDuration: 100
  55. }
  56. },
  57. onLoad() {
  58. // #ifdef MP-WEIXIN
  59. let self = this;
  60. recorder.onStop(function (res){
  61. console.log('结束啦')
  62. let { tempFilePath, duration } = res
  63. self.voicePath = path
  64. console.log(self.voicePath)
  65. console.log('时长', duration)
  66. })
  67. // 监听播放进度
  68. player.onTimeUpdate((res)=>{
  69. console.log(res)
  70. })
  71. // 监听播放进度
  72. recorder.onStart(function(res){
  73. console.log('开始啦')
  74. console.log(res)
  75. })
  76. // 监听播放进度
  77. recorder.onError(function(res){
  78. console.log('出错啦')
  79. console.log(res)
  80. })
  81. // #endif
  82. },
  83. beforeDestroy() {
  84. player.destroy(); // 释放音频资源
  85. },
  86. methods: {
  87. startRecord() {
  88. console.log('开始录音');
  89. // #ifdef APP-PLUS
  90. console.log('走的app')
  91. recorder.record({
  92. format: 'amr',
  93. filename: "_doc/hlt_app/录音文件"
  94. },
  95. (path) => {
  96. console.log('录制成功')
  97. // 此处就要上传这个文件
  98. // 上传成功后,生成一条记录
  99. this.voicePath = path
  100. console.log(this.voicePath)
  101. plus.io.getAudioInfo({
  102. filePath: path,
  103. success: ({
  104. duration
  105. }) => {
  106. console.log('时长', duration)
  107. list.push({
  108. path,
  109. duration
  110. })
  111. }
  112. })
  113. },
  114. (err) => {
  115. uni.$msg(err)
  116. }
  117. )
  118. // #endif
  119. // #ifdef MP-WEIXIN
  120. console.log('走的微信')
  121. recorder.start()
  122. // #endif
  123. },
  124. // 结束录音
  125. endRecord() {
  126. console.log('录音结束');
  127. recorder.stop();
  128. },
  129. // 播放
  130. playVoice() {
  131. console.log('播放录音');
  132. if (this.voicePath) {
  133. // #ifdef APP-PLUS
  134. player.setStyles({
  135. src: this.voicePath
  136. });
  137. // #endif
  138. // #ifdef MP-WEIXIN
  139. player.src = this.voicePath
  140. // #endif
  141. player.play()
  142. }
  143. },
  144. // 打开底部弹窗,用于开始录音
  145. handleOpenRecord() {
  146. this.$refs.popup.open()
  147. },
  148. // 按住说话事件
  149. // 开始录音, 并计时
  150. handleStart() {
  151. this.startRecord()
  152. this.recordStatus = 'start'
  153. this.timer && clearInterval(this.timer)
  154. // 计时器内部处理经过时长并显示在面板
  155. let timeStart = 0
  156. this.timer = setInterval(() => {
  157. timeStart += 1000
  158. let sec = this.timeFormat(moment.duration(timeStart).asSeconds() % 60)
  159. let min = this.timeFormat(moment.duration(timeStart).asMinutes() % 60)
  160. let hour = this.timeFormat(moment.duration(timeStart).asHours())
  161. this.duration = `${hour}:${min}:${sec}`
  162. }, 1000)
  163. },
  164. timeFormat(time) {
  165. if (0 <= time && time < 1) {
  166. return '00'
  167. }
  168. if (time >= 1 && time < 10) {
  169. return '0' + Math.floor(time)
  170. } else {
  171. return Math.floor(time)
  172. }
  173. },
  174. // 松开事件
  175. // 结束录音
  176. handleStop() {
  177. this.endRecord()
  178. this.recordStatus = 'stop'
  179. this.resetRecord()
  180. },
  181. resetRecord() {
  182. this.percent = 0
  183. this.duration = "00:00:00"
  184. this.timer && clearInterval(this.timer)
  185. }
  186. }
  187. }
  188. </script>
  189. <style lang="scss" scoped>
  190. .custom-recorder {
  191. width: 100%;
  192. .pop-up-box {
  193. .pop-up-content {
  194. border-top-left-radius: 20rpx;
  195. border-top-right-radius: 20rpx;
  196. .content-header {
  197. background-color: #fff;
  198. border-top-left-radius: 20rpx;
  199. border-top-right-radius: 20rpx;
  200. height: 100rpx;
  201. display: flex;
  202. align-items: center;
  203. justify-content: center;
  204. font-family: Source Han Sans;
  205. font-size: 32rpx;
  206. font-weight: 500;
  207. font-feature-settings: "kern" on;
  208. color: $uni-text-color;
  209. }
  210. .content-body {
  211. background: #EFF0F5;
  212. height: 400rpx;
  213. display: flex;
  214. flex-direction: column;
  215. align-items: center;
  216. justify-content: center;
  217. .btn {
  218. margin-top: 72rpx;
  219. }
  220. }
  221. }
  222. }
  223. }
  224. </style>