get-recorder-manager.uvue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. <template>
  2. <page-head :title="title"></page-head>
  3. <view class="page-body-time">
  4. <text class="time-big">{{formatedRecordTime}}</text>
  5. <!-- <text class="time-big">{{recordTimeInterval}}</text> -->
  6. </view>
  7. <scroll-view style="flex: 1;">
  8. <view>
  9. <button class="btnstyle" size="default" @click="registerOnStart">注册onStart</button>
  10. <button class="btnstyle" size="default" @click="registeronStop">注册onStop</button>
  11. <button class="btnstyle" size="default" id="btn-error" @click="registeronError">注册onError</button>
  12. <button class="btnstyle" size="default" @click="registeronPause">注册onPause</button>
  13. <button class="btnstyle" size="default" @click="registeronResume">注册onResume</button>
  14. <button class="btnstyle" size="default" @click="registeronInterruptionBegin">注册onInterruptionBegin</button>
  15. <button class="btnstyle" size="default" @click="registeronInterruptionEnd">注册onInterruptionEnd</button>
  16. <view class="uni-list">
  17. <text style="margin-bottom: 10px"> 请选择录音格式:</text>
  18. <radio-group class="uni-flex uni-row" @change="radioChange" style="flex-wrap: wrap">
  19. <radio class="uni-list-cell" style="margin-right: 15px" v-for="(item, index) in items" :key="item.value"
  20. :value="item.value" :checked="index === current">
  21. {{ item.name }}
  22. </radio>
  23. </radio-group>
  24. </view>
  25. <button class="btnstyle" size="default" :disabled="disableStartBtn" id="btn-startRecord"
  26. @click="startRecord()">开始录制</button>
  27. <button class="btnstyle" size="default" :disabled="disablePauseBtn" @click="pauseRecord">暂停录制</button>
  28. <button class="btnstyle" size="default" :disabled="disableResumeBtn" @click="resumeRecord">继续录制</button>
  29. <button class="btnstyle" size="default" id="btn-stopRecord" @click="stopRecord">停止录制</button>
  30. <button class="btnstyle" size="default" id="btn-startPlay" @click="playVoice">开始播放</button>
  31. <button class="btnstyle" size="default" id="btn-stopPlay" @click="stopVoice">停止播放</button>
  32. </view>
  33. </scroll-view>
  34. </template>
  35. <script>
  36. export type ItemType = { value : string, name : string }
  37. export default {
  38. data() {
  39. return {
  40. disableStartBtn: false,
  41. disableResumeBtn: false,
  42. disablePauseBtn: false,
  43. title: 'start/stopRecord、play/stopVoice',
  44. recording: false, //录音中
  45. playing: false, //播放中
  46. registerError: false,
  47. hasRecord: false, //是否有了一个
  48. playTimeInterval: 0,
  49. recordTimeInterval: 0,
  50. tempFilePath: '',
  51. recordTime: 0,
  52. current: 0,
  53. playTime: 0,
  54. formatedRecordTime: '00:00:00', //录音的总时间
  55. formatedPlayTime: '00:00:00',//播放录音的当前时间,
  56. recorderManager: null as RecorderManager | null,
  57. music: null as InnerAudioContext | null,
  58. items: [
  59. {
  60. value: 'aac',
  61. name: 'aac'
  62. },
  63. {
  64. value: 'mp3',
  65. name: 'mp3'
  66. },
  67. {
  68. value: 'wav',
  69. name: 'wav'
  70. },
  71. // #ifdef APP-HARMONY
  72. {
  73. value: 'm4a',
  74. name: 'm4a'
  75. },
  76. // #endif
  77. // #ifndef APP-HARMONY
  78. {
  79. value: 'pcm',
  80. name: 'pcm'
  81. }
  82. // #endif
  83. ] as ItemType[]
  84. }
  85. },
  86. onUnload: function () {
  87. this.end();
  88. },
  89. onLoad: function () {
  90. this.music = uni.createInnerAudioContext();
  91. this.music!.onEnded(() => {
  92. clearInterval(this.playTimeInterval)
  93. var playTime = 0
  94. console.log('play voice finished')
  95. this.playing = false;
  96. this.formatedPlayTime = this.formatTime(playTime);
  97. this.playTime = playTime;
  98. });
  99. this.recorderManager = uni.getRecorderManager();
  100. this.recorderManager!.onStart(() => {
  101. console.log('recorder onStart');
  102. this.disableStartBtn = true
  103. this.disablePauseBtn = false
  104. this.disableResumeBtn = false
  105. this.recording = true;
  106. this.recordTime = 0
  107. this.recordTimeInterval = setInterval(() => {
  108. this.recordTime += 1;
  109. this.formatedRecordTime = this.formatTime(this.recordTime);
  110. }, 1000)
  111. });
  112. this.recorderManager!.onStop((res) => {
  113. console.log('on stop', res.tempFilePath);
  114. this.disablePauseBtn = false
  115. this.disableResumeBtn = false
  116. this.disableStartBtn = false
  117. this.music!.src = res.tempFilePath
  118. clearInterval(this.recordTimeInterval)
  119. this.hasRecord = true;
  120. this.recording = false;
  121. });
  122. this.recorderManager!.onError((res) => {
  123. console.log('recorder onError', JSON.stringify(res));
  124. this.disablePauseBtn = false
  125. this.disableResumeBtn = false
  126. this.disableStartBtn = false
  127. this.registerError = true
  128. uni.showToast({
  129. title: JSON.stringify(res)
  130. })
  131. });
  132. },
  133. methods: {
  134. radioChange(e : UniRadioGroupChangeEvent) {
  135. for (let i = 0; i < this.items.length; i++) {
  136. if (this.items[i].value === e.detail.value) {
  137. this.current = i;
  138. break;
  139. }
  140. }
  141. },
  142. registerOnStart() {
  143. uni.showToast({
  144. title: 'already registerOnStart'
  145. })
  146. this.recorderManager!.onStart(() => {
  147. console.log('recorder on start');
  148. this.recordTime = 0
  149. this.recording = true;
  150. this.recordTimeInterval = setInterval(() => {
  151. this.recordTime += 1;
  152. this.formatedRecordTime = this.formatTime(this.recordTime);
  153. }, 1000)
  154. });
  155. },
  156. registeronStop() {
  157. uni.showToast({
  158. title: 'already registeronStop'
  159. })
  160. this.recorderManager!.onStop((res) => {
  161. console.log('on stop', res);
  162. this.music!.src = res.tempFilePath
  163. clearInterval(this.recordTimeInterval)
  164. this.hasRecord = true;
  165. this.recording = false;
  166. });
  167. },
  168. registeronError() {
  169. uni.showToast({
  170. title: 'already registeronError'
  171. })
  172. this.registerError = true
  173. this.recorderManager!.onError((res) => {
  174. console.log('recorder onError', JSON.stringify(res));
  175. });
  176. },
  177. registeronPause() {
  178. uni.showToast({
  179. title: 'already registeronPause'
  180. })
  181. this.recorderManager?.onPause(() => {
  182. console.log('recorder onPause');
  183. })
  184. },
  185. registeronResume() {
  186. uni.showToast({
  187. title: 'already registeronStop'
  188. })
  189. this.recorderManager?.onResume(() => {
  190. console.log('recorder onResume');
  191. })
  192. },
  193. registeronOnFrameRecorded() {
  194. uni.showToast({
  195. title: 'already registeronOnFrameRecorded'
  196. })
  197. this.recorderManager?.onFrameRecorded((res) => {
  198. console.log('recorder onFrameRecorded----', res);
  199. })
  200. },
  201. registeronInterruptionBegin() {
  202. uni.showToast({
  203. title: 'already registeronInterruptionBegin'
  204. })
  205. this.recorderManager?.onInterruptionBegin(() => {
  206. console.log('recorder onInterruptionBegin');
  207. })
  208. },
  209. registeronInterruptionEnd() {
  210. uni.showToast({
  211. title: 'already registeronInterruptionEnd'
  212. })
  213. this.recorderManager?.onInterruptionBegin(() => {
  214. console.log('recorder registeronInterruptionEnd');
  215. })
  216. },
  217. pauseRecord() {
  218. console.log('recorder pause');
  219. this.recorderManager?.pause()
  220. if (this.recording) {
  221. this.disableStartBtn = false
  222. this.disablePauseBtn = true
  223. this.disableResumeBtn = false
  224. }
  225. clearInterval(this.recordTimeInterval)
  226. },
  227. resumeRecord() {
  228. console.log('recorder resume ', this.recorderManager);
  229. this.recorderManager?.resume()
  230. this.recorderManager?.onResume(() => {
  231. console.log('recorder onResume');
  232. })
  233. if (this.recording) {
  234. this.disableStartBtn = false
  235. this.disablePauseBtn = false
  236. this.disableResumeBtn = true
  237. this.recordTimeInterval = setInterval(() => {
  238. this.recordTime += 1;
  239. this.formatedRecordTime = this.formatTime(this.recordTime);
  240. }, 1000)
  241. }
  242. },
  243. formatTime(time : number) : string {
  244. if (typeof time !== 'number' || time < 0) {
  245. return time.toString()
  246. }
  247. var hour = parseInt((time / 3600).toString())
  248. time = time % 3600
  249. var minute = parseInt((time / 60).toString())
  250. time = time % 60
  251. var second = time
  252. return [hour, minute, second].map((n : number) => {
  253. let str = n.toString();
  254. return str.length > 1 ? str : "0" + str;
  255. }).join(":");
  256. },
  257. startRecord() { //开始录音
  258. if (this.recording) {
  259. uni.showToast({
  260. title: this.disablePauseBtn ? "当前是录音暂停状态" : "当前正在录音"
  261. })
  262. return
  263. }
  264. console.log('startRecord', this.items[this.current].value)
  265. // TODO ios 在没有请求过权限之前无法得知是否有相关权限,这种状态下需要直接调用录音,但没有状态或回调判断用户拒绝
  266. this.recorderManager?.start({
  267. format: this.items[this.current].value,
  268. sampleRate: 8000,
  269. numberOfChannels: 2,
  270. encodeBitRate: 48000,
  271. frameSize: 2
  272. });
  273. },
  274. stopRecord() { //停止录音
  275. this.recorderManager?.stop();
  276. this.disableStartBtn = false
  277. this.disablePauseBtn = false
  278. this.disableResumeBtn = false
  279. },
  280. playVoice() {
  281. if (this.recording) {
  282. uni.showToast({
  283. title: "当前录音还未结束"
  284. })
  285. return
  286. }
  287. console.log('play voice');
  288. if (this.playing) {
  289. return
  290. }
  291. this.playing = true;
  292. this.playTimeInterval = setInterval(() => {
  293. if (this.playTime < this.recordTime) {
  294. this.playTime += 1;
  295. }
  296. this.formatedRecordTime = this.formatTime(this.playTime);
  297. }, 1000)
  298. this.music?.play();
  299. },
  300. stopVoice() {
  301. if (this.recording) {
  302. uni.showToast({
  303. title: "当前录音还未结束"
  304. })
  305. return
  306. }
  307. clearInterval(this.playTimeInterval)
  308. this.playing = false;
  309. this.formatedRecordTime = this.formatTime(0);
  310. this.playTime = 0;
  311. this.music?.stop();
  312. },
  313. end() {
  314. this.music?.stop();
  315. this.recorderManager?.stop();
  316. clearInterval(this.recordTimeInterval)
  317. clearInterval(this.playTimeInterval);
  318. this.recording = false
  319. this.playing = false
  320. this.hasRecord = false;
  321. this.playTime = 0
  322. this.recordTime = 0;
  323. this.formatedRecordTime = "00:00:00"
  324. this.formatedRecordTime = "00:00:00";
  325. },
  326. clear() {
  327. this.end();
  328. }
  329. }
  330. }
  331. </script>
  332. <style>
  333. .page-body-time {
  334. display: flex;
  335. flex-direction: column;
  336. align-items: center;
  337. }
  338. .time-big {
  339. font-size: 30px;
  340. margin: 10px;
  341. }
  342. .btnstyle {
  343. margin-left: 30px;
  344. margin-right: 30px;
  345. margin-top: 10px;
  346. }
  347. .uni-list {
  348. border-bottom: 0px;
  349. background-color: transparent;
  350. margin-left: 30px;
  351. margin-right: 30px;
  352. margin-top: 10px;
  353. margin-bottom: 10px;
  354. }
  355. </style>