js 选择一个音频文件,绘制音频的波形,从右向左渐渐前进。 ...

打印 上一主题 下一主题

主题 1643|帖子 1643|积分 4929

选择一个音频文件,绘制波形,从右向左渐渐前进。


完整代码:
  1. <template>
  2.   <div>
  3.     <input type="file" @change="handleFileChange" accept="audio/*" />
  4.     <button @click="stopPlayback" :disabled="!isLoaded">停止</button>
  5.     <canvas ref="canvas" width="1201" height="211"></canvas>
  6.   </div>
  7. </template>
  8. <script>
  9. import axios from "axios";
  10. export default {
  11.   data() {
  12.     return {
  13.       // audioUrl:"http://121.41.225.74:9091/mintti/app/storage/newFile/b26uvk9ipd8n5iop1lzs.wav",
  14.       audioUrl: "http://121.41.225.74:9091/mintti/app/storage/newFile/c19xqqqtd8ywqyaf8gno.wav",
  15.       // audioUrl: "http://121.41.225.74:9091/mintti/app/storage/newFile/d3msxipdfxrbyijm3ys0.wav",
  16.       // audioUrl:"http://121.41.225.74:9091/mintti/app/storage/newFile/xm456t9dptsrigxye84q.wav",
  17.       dataArray: [],
  18.       isPlaying: false,
  19.       isLoaded: false,
  20.       drawInterval: 200, // 设置绘制的时间间隔(单位:毫秒)
  21.       drawIntervalId: null,
  22.       fileData: new Int8Array(0),
  23.       index: 0,
  24.       mWidth: 0,
  25.       mHeight: 0,
  26.     }
  27.   },
  28.   mounted() {
  29.     const ctx = this.$refs.canvas.getContext('2d')
  30.     this.drawGrid(ctx)
  31.     this.downloadAudio()
  32.   },
  33.   methods: {
  34.     // 下载音频文件
  35.     downloadAudio() {
  36.       axios({
  37.         method: 'get',
  38.         url: this.audioUrl,
  39.         responseType: 'arraybuffer'
  40.       }).then(res => {
  41.         if (!res) {
  42.           return;
  43.         }
  44.         console.log("decodeAudioData")
  45.         this.loadAudio(res.data)
  46.       }).catch(error => {
  47.         console.error('下载音频时出错:', error);
  48.       });;
  49.     },
  50.     handleFileChange(event) {
  51.       this.isLoaded = false
  52.       const file = event.target.files[0]
  53.       this.stopPlayback()
  54.       const reader = new FileReader();
  55.       reader.onload = (e) => {
  56.         console.log("onLoad")
  57.         this.loadAudio(e.target.result)
  58.       };
  59.       reader.readAsArrayBuffer(file);
  60.     },
  61.     loadAudio(res) {
  62.       this.dataArray = []
  63.       this.isLoaded = true
  64.       this.index = 0;
  65.       // 获取文件的前 100 个字节
  66.       this.fileData = new Int8Array(res);
  67.       this.refreshData()
  68.       this.drawIntervalId = setInterval(() => {
  69.         console.log("定时器执行了")
  70.         this.refreshData()
  71.       }, this.drawInterval)//循环读取
  72.     },
  73.     refreshData() {
  74.       let i = this.index
  75.       console.log("文件总长度:" + this.fileData.byteLength + ",,i=" + i)
  76.       if (i * 1600 + 44 > this.fileData.byteLength) {
  77.         clearInterval(this.drawIntervalId)
  78.         return
  79.       }
  80.       const byteArray = this.fileData.slice(i * 1600 + 44, (i + 1) * 1600 + 44);
  81.       // 创建一个新的 Uint16Array,长度为 byteArray 的一半
  82.       let shortArray = new Int16Array(byteArray.length / 2)
  83.       //遍历 byteArray,将每两个字节合并成一个短整型
  84.       for (let i = 0; i < byteArray.length; i += 2) {
  85.         shortArray[i / 2] = (byteArray[i] & 0xFF) | (byteArray[i + 1] & 0xFF) << 8;
  86.       }
  87.       const step = 10;
  88.       for (let i = 0; i < shortArray.length; i += step) {
  89.         // console.log(i + "文件short值:" + shortArray[i])
  90.         if (this.mWidth > 0 && this.dataArray.length >= this.mWidth) {
  91.           this.dataArray.shift()
  92.         }
  93.         this.dataArray.push(shortArray[i])
  94.       }
  95.       this.isPlaying = true
  96.       this.draw2();
  97.       this.index += 1;
  98.     },
  99.     stopPlayback() {
  100.       console.log("停止播放-stopPlayback")
  101.       this.isPlaying = false
  102.       clearInterval(this.drawIntervalId)
  103.       const ctx = this.$refs.canvas.getContext('2d')
  104.       ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
  105.       this.drawGrid(ctx)
  106.     },
  107.     draw2() {
  108.       if (!this.isPlaying) {
  109.         return
  110.       }
  111.       // console.log('开始绘图-draw')
  112.       const ctx = this.$refs.canvas.getContext('2d')
  113.       ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
  114.       this.drawGrid(ctx)
  115.       this.drawWaveform(ctx)
  116.     },
  117.     drawGrid(ctx) {
  118.       const { width, height } = ctx.canvas
  119.       this.mWidth = ctx.canvas.width
  120.       this.mHeight = ctx.canvas.height
  121.       ctx.strokeStyle = '#ccc'
  122.       ctx.lineWidth = 1
  123.       for (let i = 0; i < height; i += 10) {
  124.         ctx.beginPath()
  125.         ctx.moveTo(0, i)
  126.         ctx.lineTo(width, i)
  127.         ctx.stroke()
  128.       }
  129.       for (let j = 0; j < width; j += 10) {
  130.         ctx.beginPath()
  131.         ctx.moveTo(j, 0)
  132.         ctx.lineTo(j, height)
  133.         ctx.stroke()
  134.       }
  135.     },
  136.     drawWaveform(ctx) {
  137.       ctx.beginPath()
  138.       ctx.lineWidth = 1
  139.       ctx.strokeStyle = '#25ebd7'
  140.       let x = 0
  141.       let len = this.dataArray.length;
  142.       let index = this.mWidth - len;
  143.       for (let i = index + 1; i < this.mWidth; i++) {
  144.         const mCenterY = this.mHeight / 2;
  145.         const y = mCenterY - (this.dataArray[i - index - 1] / (32768 / mCenterY));
  146.         // console.log(`i=${i},position=${i - index - 1},,data=${this.dataArray[i - index - 1]},,y=${y},,mCenterY=${mCenterY}`)
  147.         x = i - 1;
  148.         ctx.lineTo(x, y)
  149.         ctx.stroke()
  150.       }
  151.     },
  152.   }
  153. }
  154. </script>
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

民工心事

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表