elise-audio.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. <template>
  2. <view class='flex audio' :class="{active:status}" :style="{background:audioColor}" @click='play(audioId)'>
  3. <view class='mr-3'>
  4. <view class="wifi-symbol " :class="status?'active':''">
  5. <view class="wifi-circle first"></view>
  6. <view class="wifi-circle second"></view>
  7. <view class="wifi-circle third"></view>
  8. </view>
  9. </view>
  10. <view v-if="!create" class="ml-4">生成</view>
  11. <block v-else>
  12. <view v-if="Loading" class="loading_icon">
  13. <u-loading-icon size="18" color="#fff"></u-loading-icon>
  14. </view>
  15. <view v-else class="ml-4">{{status?'暂停':'阅读'}}</view>
  16. </block>
  17. </view>
  18. </template>
  19. <script>
  20. export default {
  21. data() {
  22. return {
  23. context: null,
  24. duration: 100,
  25. status: false,
  26. task_id:'',
  27. Loading:false,
  28. currentid:'',
  29. create:false
  30. }
  31. },
  32. props: {
  33. url: {
  34. type: String,
  35. default: ''
  36. },
  37. content: {
  38. type: String,
  39. default: ''
  40. },
  41. audioColor: {
  42. type: String,
  43. default: '#5ba5ef'
  44. },
  45. index: {
  46. type: Number,
  47. default: 0
  48. },
  49. cancel: {
  50. type: Boolean,
  51. default:false
  52. },
  53. // create: {
  54. // type: Boolean,
  55. // default:false
  56. // },
  57. durationS: [String, Number],
  58. audioId: [String, Number]
  59. },
  60. created() {
  61. this.context = uni.createInnerAudioContext();
  62. // this.context.autoplay = true
  63. this.context.src = this.url;
  64. this.context.volume = 1;
  65. this.onEnded();
  66. uni.$on('stop', (id) => {
  67. if (id && id != this.audioId) {
  68. this.context.stop();
  69. this.status = false;
  70. } else if (!id) {
  71. this.context.stop();
  72. this.status = false;
  73. }
  74. })
  75. },
  76. methods: {
  77. play(id) { //点击播放
  78. if (this.url) {
  79. if (this.status) {
  80. this.context.pause();
  81. this.status = !this.status;
  82. } else {
  83. uni.$emit('stop', id)
  84. this.context.volume = 1;
  85. this.context.play()
  86. this.status = !this.status;
  87. }
  88. } else {
  89. if(id == this.currentid&&this.Loading){
  90. uni.showToast({
  91. title:'正在生成',
  92. icon:'none'
  93. })
  94. return;
  95. }
  96. if(id == this.currentid&&!this.Loading){
  97. // console.log('1');
  98. if (this.status) {
  99. this.context.pause();
  100. this.status = !this.status;
  101. } else {
  102. uni.$emit('stop', id)
  103. this.context.volume = 1;
  104. this.context.play()
  105. this.status = !this.status;
  106. }
  107. return;
  108. }
  109. this.create = true
  110. this.cancel = false
  111. this.Loading = true
  112. this.currentid = id
  113. this.$http('ai.tts', {
  114. text: this.content
  115. }).then(res => {
  116. if(res.code == 0){
  117. this.task_id = res.data.task_id
  118. this.aittsJob(id)
  119. }else{
  120. uni.showToast({
  121. title:'阅读失败',
  122. icon:'none'
  123. })
  124. this.Loading = false
  125. this.create = false
  126. }
  127. })
  128. }
  129. },
  130. aittsJob(id){
  131. this.$http('ai.ttsJob', {
  132. task_ids: this.task_id
  133. }).then(res => {
  134. if (res.code == 0) {
  135. if(this.cancel){
  136. this.status = false;
  137. this.Loading = false
  138. return;
  139. }
  140. if (res.data.task_status == 'Running') {
  141. setTimeout(() => {
  142. this.aittsJob()
  143. }, 1500);
  144. return;
  145. }
  146. let ress = {
  147. speech_url:res.data.task_result.speech_url,
  148. index:this.index
  149. }
  150. this.context.src = res.data.task_result.speech_url
  151. uni.$emit('stop', id)
  152. // this.status = !this.status;
  153. this.Loading = false
  154. this.$emit('aittsjob',ress);
  155. // this.context.play()
  156. } else {
  157. uni.showToast({
  158. title:'阅读失败',
  159. icon:'none'
  160. })
  161. this.Loading = false
  162. this.create = false
  163. }
  164. });
  165. },
  166. onEnded() { //播放结束
  167. this.context.onEnded(() => {
  168. this.status = false;
  169. })
  170. },
  171. }
  172. }
  173. </script>
  174. <style lang="scss">
  175. .audio {
  176. background: #68d7bb;
  177. height: 45rpx;
  178. border-radius: 60rpx;
  179. width: 125rpx;
  180. align-items: center;
  181. position: relative;
  182. // padding: 20rpx;
  183. &.active {
  184. opacity: 0.8;
  185. }
  186. }
  187. .flex {
  188. display: flex;
  189. flex-direction: row;
  190. justify-content: space-between;
  191. }
  192. .flex-1 {
  193. flex: 1;
  194. }
  195. .ml-3 {
  196. margin-right: 30rpx;
  197. color: #fff;
  198. }
  199. .ml-4 {
  200. font-size: 24rpx;
  201. margin-right: 20rpx;
  202. color: #fff;
  203. position: absolute;
  204. right: 0;
  205. }
  206. .mr-3 {
  207. margin-left: 30rpx;
  208. }
  209. .wifi-symbol {
  210. width: 50rpx;
  211. height: 50rpx;
  212. box-sizing: border-box;
  213. overflow: hidden;
  214. transform: rotate(135deg) translate3d(0, 0, 0);
  215. -webkit-transform: rotate(135deg) translate3d(0, 0, 0);
  216. backface-visibility: hidden;
  217. -webkit-backface-visibility: hidden;
  218. }
  219. .wifi-circle {
  220. border: 5rpx solid #fff;
  221. border-radius: 50%;
  222. position: absolute;
  223. }
  224. .first {
  225. width: 5rpx;
  226. height: 5rpx;
  227. background: #fff;
  228. top: 45rpx;
  229. left: 45rpx;
  230. }
  231. .second {
  232. width: 25rpx;
  233. height: 25rpx;
  234. top: 35rpx;
  235. left: 35rpx;
  236. }
  237. .third {
  238. width: 40rpx;
  239. height: 40rpx;
  240. top: 25rpx;
  241. left: 25rpx;
  242. }
  243. .active {
  244. .second {
  245. animation: fadeInOut 1s infinite 0.2s;
  246. -webkit-animation: fadeInOut 1s infinite 0.2s;
  247. }
  248. .third {
  249. animation: fadeInOut 1s infinite 0.4s;
  250. -webkit-animation: fadeInOut 1s infinite 0.4s;
  251. }
  252. }
  253. @keyframes fadeInOut {
  254. 0% {
  255. opacity: 0;
  256. /*初始状态 透明度为0*/
  257. }
  258. 100% {
  259. opacity: 1;
  260. /*结尾状态 透明度为1*/
  261. }
  262. }
  263. .loading_icon{
  264. margin-right: 18rpx;
  265. }
  266. </style>