导航菜单

  • 0.api
  • 0.Async
  • 0.module
  • 1.ES2015
  • 2.Promise
  • 3.Node
  • 4.NodeInstall
  • 5.REPL
  • 6.NodeCore
  • 7.module&NPM
  • 8.Encoding
  • 9.Buffer
  • 10.fs
  • 11.Stream-1
  • 11.Stream-2
  • 11.Stream-3
  • 11.Stream-4
  • 12-Network-2
  • 12.NetWork-3
  • 12.Network-1
  • 13.tcp
  • 14.http-1
  • 14.http-2
  • 15.compress
  • 16.crypto
  • 17.process
  • 18.yargs
  • 19.cache
  • 20.action
  • 21.https
  • 22.cookie
  • 23.session
  • 24.express-1
  • 24.express-2
  • 24.express-3
  • 24.express-4
  • 25.koa-1
  • 26.webpack-1-basic
  • 26.webpack-2-optimize
  • 26.webpack-3-file
  • 26.webpack-4.tapable
  • 26.webpack-5-AST
  • 26.webpack-6-sources
  • 26.webpack-7-loader
  • 26.webpack-8-plugin
  • 26.webpack-9-hand
  • 26.webpack-10-prepare
  • 28.redux
  • 28.redux-jwt-back
  • 28.redux-jwt-front
  • 29.mongodb-1
  • 29.mongodb-2
  • 29.mongodb-3
  • 29.mongodb-4
  • 29.mongodb-5
  • 29.mongodb-6
  • 30.cms-1-mysql
  • 30.cms-2-mysql
  • 30.cms-3-mysql
  • 30.cms-4-nunjucks
  • 30.cms-5-mock
  • 30.cms-6-egg
  • 30.cms-7-api
  • 30.cms-8-roadhog
  • 30.cms-9-yaml
  • 30.cms-10-umi
  • 30.cms-12-dva
  • 30.cms-13-dva-ant
  • 30.cms-14-front
  • 30.cms-15-deploy
  • 31.dva
  • 31.cms-13-dva-antdesign
  • 33.redis
  • 34.unittest
  • 35.jwt
  • 36.websocket-1
  • 36.websocket-2
  • 38.chat-api-1
  • 38.chat-api-2
  • 38.chat-3
  • 38.chat-api-3
  • 38.chat
  • 38.chat2
  • 38.chat2
  • 39.crawl-0
  • 39.crawl-1
  • 39.crawl-2
  • 40.deploy
  • 41.safe
  • 42.test
  • 43.nginx
  • 44.enzyme
  • 45.docker
  • 46.elastic
  • 47.oauth
  • 48.wxpay
  • index
  • 52.UML
  • 53.design
  • index
  • 54.linux
  • 57.ts
  • 56.react-ssr
  • 58.ts_react
  • 59.ketang
  • 59.ketang2
  • 61.1.devops-linux
  • 61.2.devops-vi
  • 61.3.devops-user
  • 61.4.devops-auth
  • 61.5.devops-shell
  • 61.6.devops-install
  • 61.7.devops-system
  • 61.8.devops-service
  • 61.9.devops-network
  • 61.10.devops-nginx
  • 61.11.devops-docker
  • 61.12.devops-jekins
  • 61.13.devops-groovy
  • 61.14.devops-php
  • 61.15.devops-java
  • 61.16.devops-node
  • 61.17.devops-k8s
  • 62.1.react-basic
  • 62.2.react-state
  • 62.3.react-high
  • 62.4.react-optimize
  • 62.5.react-hooks
  • 62.6.react-immutable
  • 62.7.react-mobx
  • 62.8.react-source
  • 63.1.redux
  • 63.2.redux-middleware
  • 63.3.redux-hooks
  • 63.4.redux-saga
  • 63.5.redux-saga-hand
  • 64.1.router
  • 64.2.router-connected
  • 65.1.typescript
  • 65.2.typescript
  • 65.3.typescript
  • 65.4.antd
  • 65.4.definition
  • 66-1.vue-base
  • 66-2.vue-component
  • 66-3.vue-cli3.0
  • 66-4.$message组件
  • 66-5.Form组件
  • 66-6.tree
  • 66-7.vue-router-apply
  • 66-8.axios-apply
  • 66-9.vuex-apply
  • 66-10.jwt-vue
  • 66-11.vue-ssr
  • 66-12.nuxt-apply
  • 66-13.pwa
  • 66-14.vue单元测试
  • 66-15.权限校验
  • 67-1-network
  • 68-2-wireshark
  • 7.npm2
  • 69-hooks
  • 70-deploy
  • 71-hmr
  • 72.deploy
  • 73.import
  • 74.mobile
  • 75.webpack-1.文件分析
  • 75.webpack-2.loader
  • 75.webpack-3.源码流程
  • 75.webpack-4.tapable
  • 75.webpack-5.prepare
  • 75.webpack-6.resolve
  • 75.webpack-7.loader
  • 75.webpack-8.module
  • 75.webpack-9.chunk
  • 75.webpack-10.asset
  • 75.webpack-11.实现
  • 76.react_optimize
  • 77.ts_ketang_back
  • 77.ts_ketang_front
  • 78.vue-domdiff
  • 79.grammar
  • 80.tree
  • 81.axios
  • 82.1.react
  • 82.2.react-high
  • 82.3.react-router
  • 82.4.redux
  • 82.5.redux_middleware
  • 82.6.connected
  • 82.7.saga
  • 82.8.dva
  • 82.8.dva-source
  • 82.9.roadhog
  • 82.10.umi
  • 82.11.antdesign
  • 82.12.ketang-front
  • 82.12.ketang-back
  • 83.upload
  • 84.graphql
  • 85.antpro
  • 86.1.uml
  • 86.2.design
  • 87.postcss
  • 88.react16-1
  • 89.nextjs
  • 90.react-test
  • 91.react-ts
  • 92.rbac
  • 93.tsnode
  • 94.1.JavaScript
  • 94.2.JavaScript
  • 94.3.MODULE
  • 94.4.EventLoop
  • 94.5.文件上传
  • 94.6.https
  • 94.7. nginx
  • 95.1. react
  • 95.2.react
  • 96.1.react16
  • 96.2.fiber
  • 96.3.fiber
  • 97.serverless
  • 98.websocket
  • 100.1.react-basic
  • 101.1.monitor
  • 101.2.monitor
  • 102.java
  • 103.1.webpack-usage
  • 103.2.webpack-bundle
  • 103.3.webpack-ast
  • 103.4.webpack-flow
  • 103.5.webpack-loader
  • 103.6.webpack-tapable
  • 103.7.webpack-plugin
  • 103.8.webpack-optimize1
  • 103.9.webpack-optimize2
  • 103.10.webpack-hand
  • 103.11.webpack-hmr
  • 103.11.webpack5
  • 103.13.splitChunks
  • 103.14.webpack-sourcemap
  • 103.15.webpack-compiler1
  • 103.15.webpack-compiler2
  • 103.16.rollup.1
  • 103.16.rollup.2
  • 103.16.rollup.3
  • 103.16.vite.basic
  • 103.16.vite.source
  • 103.16.vite.plugin
  • 103.16.vite.1
  • 103.16.vite.2
  • 103.17.polyfill
  • 104.1.binary
  • 104.2.binary
  • 105.skeleton
  • 106.1.react
  • 106.2.react_hooks
  • 106.3.react_router
  • 106.4.redux
  • 106.5.redux_middleware
  • 106.6.connected-react-router
  • 106.6.redux-first-history
  • 106.7.redux-saga
  • 106.8.dva
  • 106.9.umi
  • 106.10.ketang
  • 106.11.antdesign
  • 106.12.antpro
  • 106.13.router-6
  • 106.14.ssr
  • 106.15.nextjs
  • 106.16.1.cms
  • 106.16.2.cms
  • 106.16.3.cms
  • 106.16.4.cms
  • 106.16.mobx
  • 106.17.fomily
  • 107.fiber
  • 108.http
  • 109.1.webpack_usage
  • 109.2.webpack_source
  • 109.3.dll
  • 110.nest.js
  • 111.xstate
  • 112.Form
  • 113.redux-saga
  • 114.react+typescript
  • 115.immer
  • 116.pro5
  • 117.css-loader
  • 118.1.umi-core
  • 119.2.module-federation
  • 119.1.module-federation
  • 120.create-react-app
  • 121.react-scripts
  • 122.react-optimize
  • 123.jsx-runtime
  • 124.next.js
  • 125.1.linux
  • 125.2.linux-vi
  • 125.3.linux-user
  • 125.4.linux-auth
  • 125.5.linux-shell
  • 125.6.linux-install
  • 125.7.linux-system
  • 125.8.linux-service
  • 125.9.linux-network
  • 125.10.nginx
  • 125.11.docker
  • 125.12.ci
  • 125.13.k8s
  • 125.14.k8s
  • 125.15.k8s
  • 125.16.k8s
  • 126.11.react-1
  • 126.12.react-2
  • 126.12.react-3
  • 126.12.react-4
  • 126.12.react-5
  • 126.12.react-6
  • 126.12.react-7
  • 126.12.react-8
  • 127.frontend
  • 128.rollup
  • 129.px2rem-loader
  • 130.health
  • 131.hooks
  • 132.keepalive
  • 133.vue-cli
  • 134.react18
  • 134.2.react18
  • 134.3.react18
  • 135.function
  • 136.toolkit
  • 137.lerna
  • 138.create-vite
  • 139.cli
  • 140.antd
  • 141.react-dnd
  • 142.1.link
  • 143.1.gulp
  • 143.2.stream
  • 143.3.gulp
  • 144.1.closure
  • 144.2.v8
  • 144.3.gc
  • 145.react-router-v6
  • 146.browser
  • 147.lighthouse
  • 148.1.basic
  • 148.2.basic
  • 148.3.basic
  • 148.4.basic
  • 148.5.basic
  • 149.1.vite
  • 149.2.vite
  • 149.3.vite
  • 149.4.vite
  • 150.react-window
  • 151.react-query
  • 152.useRequest
  • 153.transition
  • 154.emotion
  • 155.1.formily
  • 155.2.formily
  • 155.3.formily
  • 155.3.1.mobx.usage
  • 155.3.2.mobx.source
  • 156.vue-loader
  • 103.11.mf
  • 157.1.react18
  • 158.umi4
  • 159.rxjs
  • 159.rxjs2
  • 160.bff
  • 161.zustand
  • 162.vscode
  • 163.emp
  • 164.cors
  • 1.生成项目
  • 2.ArrayBuffer
  • 3.TypedArray
  • 4.DataView对象
  • 5.Blob
  • 6. Object URL
  • 7.图片预览和裁剪上传
    • 7.1 src\index.js
    • 7.2 src\Image.js
    • 7.3 server.js
  • 8.音频的裁剪和预览
    • 8.1 index.js
    • 8.2 src\Audio.js

1.生成项目 #

create-react-app zhufengbinary
cd zhufengbinary
yarn start

browserbinary2

2.ArrayBuffer #

  • ArrayBuffer对象用来表示通用的、固定长度的原始二进制数据缓冲区
  • 它是一个字节数组,通常在其他语言中称为byte array
  • 你不能直接操作 ArrayBuffer 的内容,而是要通过类型数组对象或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。

bytearray

//创建一个长度为8个字节的buffer
const buffer = new ArrayBuffer(8);
console.log(buffer.byteLength);

3.TypedArray #

TypedArray对象描述了一个底层的二进制数据缓冲区(binary data buffer)的一个类数组视图(view)

  • 但它本身不可以被实例化,甚至无法访问,你可以把它理解为接口,它有很多的实现
类型 单个元素值的范围 大小(bytes) 描述
Int8Array -128 to 127 1 8 位二进制有符号整数
Uint8Array 0 to 255 1 8 位无符号整数
Int16Array -32768 to 32767 2 16 位二进制有符号整数
Uint16Array 0 to 65535 2 16 位无符号整数

TypedArray

const buffer = new ArrayBuffer(8);
console.log(buffer.byteLength);//8
const int8Array = new Int8Array(buffer);
console.log(int8Array.length);//8
const int16Array = new Int16Array(buffer);
console.log(int16Array.length);//4

4.DataView对象 #

  • DataView视图是一个可以从二进制ArrayBuffer对象中读写多种数值类型的底层接口
  • setInt8()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处储存一个8-bit数(一个字节)
  • getInt8()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处获取一个8-bit数(一个字节)
new DataView(buffer [, byteOffset [, byteLength]])

DataView

const buffer = new ArrayBuffer(8);
console.log(buffer.byteLength);//8个字节
const view1 = new DataView(buffer);
view1.setInt8(0, 1); 
console.log(view1.getInt8(0));//1

view1.setInt8(1, 2); 
console.log(view1.getInt8(1));//2

console.log(view1.getInt16(0));//258

5.Blob #

  • Blob对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据。File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
  • Blob() 构造函数返回一个新的 Blob 对象。 blob的内容由参数数组中给出的值的串联组成。
  • FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
    • readAsText():读取文本文件(可以使用txt打开的文件),返回文本字符串,默认编码是UTF-8
    • readAsDataURL():读取文件获取一段以data开头的字符串,这段字符串的本质就是DataURL,DataURL是一种将文件嵌入到文档的方案。DataURL是将资源转换为base64编码的字符串形式,并且将这些内容直接储存在url中
  • 构造函数 var aBlob = new Blob( array, options );
    • array 是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob。DOMStrings会被编码为UTF-8。
    • options 是一个可选的BlobPropertyBag字典
      • type 默认值为 "",它代表了将会被放入到blob中的数组内容的MIME类型
<body>
    <script>
     let debug = { name: "zhufeng" };
     let str = JSON.stringify(debug);
     console.log("str", str);

     var blob = new Blob([str], { type: "application/json" });
     console.log("blob.size", blob.size);

        function readBlob(blob, type) {
            return new Promise((resolve) => {
                const reader = new FileReader();
                reader.onload = function (event) {
                    resolve(event.target.result);
                };
                switch (type) {
                    case "ArrayBuffer":
                        reader.readAsArrayBuffer(blob);
                        break;
                    case "DataURL":
                        reader.readAsDataURL(blob);
                        break;
                    case "Text":
                        reader.readAsText(blob,'UTF-8');
                        break;
                    default:
                        break;
                }
            });
        }
        readBlob(blob, "ArrayBuffer").then((buffer) => {
            console.log("buffer", buffer);
        });
        readBlob(blob, "DataURL").then((base64String) => {
            console.log("base64String", base64String);
        });
        readBlob(blob, "Text").then((text) => {
            console.log("text", text);
        });
    </script>
</body>

6. Object URL #

  • 可以使用浏览器新的 API URL 对象通过方法生成一个地址来表示 Blob 数据
  • 格式为 blob:<origin>/<uuid>
  • URL.createObjectURL 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。
  • revokeObjectURL 静态方法用来释放一个之前已经存在的、通过调用 URL.createObjectURL() 创建的 URL 对象
<body>
    <button onclick="download()">下载json</button>
    <script>
     function download () {
        let debug = { hello: "world" };
        let str = JSON.stringify(debug);
        var blob = new Blob([str], { type: 'application/json' });
        let objectURL = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.download = 'hello.json';
        a.rel = 'noopener';
        a.href = objectURL;
        a.dispatchEvent(new MouseEvent('click'));
        URL.revokeObjectURL(objectURL);
     }
    </script>
</body>

7.图片预览和裁剪上传 #

  • bootstrap.min.css

7.1 src\index.js #

import React from 'react';
import ReactDOM from 'react-dom';
import Image from './Image';

ReactDOM.render(
  <Image />,
  document.getElementById('root')
);

7.2 src\Image.js #

src\Image.js

import React from 'react';
export default class Image extends React.Component{
   imageRef = React.createRef()   //图片
   canvasRef = React.createRef()  //完整的canvas
   avatarRef = React.createRef()  //裁剪后的头像
   state = {
    file:null,//添加的文件
    dataURL:'',//转换成的base64字符串
    times:1,//图片放大的倍数
    lastLeft:0,//最后一个左边的距离
    lastTop:0,//最后一个上面的距离
    avatarDataURL:''//头像的base64字符串
   }
   handleChange = (event)=>{//头像选择改变
    let file = event.target.files[0];
    let fileReader = new FileReader();//读取文件
    fileReader.onload =  (event)=> {
      this.setState({file,dataURL:event.target.result});
      this.imageRef.current.onload = ()=>this.draw();//绘制到canvas上
    };
    fileReader.readAsDataURL(file);
   }
   draw=(left=this.state.lastLeft,top=this.state.lastTop)=>{
    let image = this.imageRef.current;//图像
    let canvas = this.canvasRef.current;//canvas
    const ctx = canvas.getContext("2d");
    ctx.clearRect(0,0,canvas.width, canvas.height);//清掉老图片
    let imageWidth = image.width;//图片宽度
    let imageHeight = image.height;//图片高度
    if(imageWidth>imageHeight){//如果宽比高度大
      let times = canvas.width/imageWidth;
      imageWidth=canvas.width*this.state.times;//让宽度等于canvas宽度
      imageHeight=times*imageHeight*this.state.times;//然后让高度等比缩放
    }else{
      let times = canvas.height/imageHeight;
      imageHeight=canvas.height*this.state.times;
      imageWidth=times*imageWidth*this.state.times;
    }
    ctx.drawImage(image, (canvas.width-imageWidth)/2+left, (canvas.height-imageHeight)/2+top,imageWidth,imageHeight);
   }
   bigger = ()=>{
       this.setState({times:this.state.times+0.1},()=>this.draw());
   }
   smaller = ()=>{
    this.setState({times:this.state.times-0.1},()=>this.draw());
   }
   confirm = ()=>{
    let canvas = this.canvasRef.current;//头像canvas
    const ctx = canvas.getContext("2d");
    const imageData = ctx.getImageData(100, 100, 100, 100);//获取头像数据
    let clipCanvas = document.createElement('canvas');
    clipCanvas.width=100;
    clipCanvas.height=100;
    const clipContext = clipCanvas.getContext("2d");
    clipContext.putImageData(imageData, 0, 0);
    let dataUrl = clipCanvas.toDataURL();
    this.avatarRef.current.src = dataUrl;
    this.setState({avatarDataURL:dataUrl});
   }
   handleMouseDown = (event)=>{
    this.setState({startX:event.clientX,startY:event.clientY,startDrag:true});
   }
   handleMouseMove = (event)=>{
    if(this.state.startDrag)
        this.draw((event.clientX - this.state.startX)+this.state.lastLeft,(event.clientY - this.state.startY)+this.state.lastTop);
   }
   handleMouseUp = (event)=>{
    this.setState({lastLeft:(event.clientX - this.state.startX)+this.state.lastLeft,lastTop:(event.clientY - this.state.startY)+this.state.lastTop,startDrag:false});
   }
   upload = ()=>{
    let bytes = atob(this.state.avatarDataURL.split(",")[1]);
    let arrayBuffer = new ArrayBuffer(bytes.length);
    let uint8Array = new Uint8Array(arrayBuffer);
    for (let i = 0; i < bytes.length; i++) {
      uint8Array[i] = bytes.charCodeAt(i);
    }
    let blob =  new Blob([arrayBuffer], { type: 'image/png' });
    let request = new XMLHttpRequest();
    let formData = new FormData();
    formData.append("name", "zhufeng");
    formData.append("avatar", blob);
    request.open("POST", 'http://localhost:8080/upload', true);
    request.send(formData);
   }
   render(){
       return (
           <div className="container">
               <div className="row">
                   <div className="col-md-12">
                     <input type="file" accept="image/*" onChange={this.handleChange} />
                   </div>
               </div>
               <div className="row">
                   <div className="col-md-4 image" >
                       {
                           this.state.file&&(
                            <img className="img-responsive" src={this.state.dataURL} ref={this.imageRef} style={{border:'2px dashed green'}}/>
                           )
                       }
                   </div>
                   <div className="col-md-4 clip" onMouseDown={this.handleMouseDown} onMouseMove={this.handleMouseMove} onMouseUp={this.handleMouseUp}>
                       {
                           this.state.file&&(
                            <>
                                <div style={{position:'relative'}}>
                                  <canvas ref={this.canvasRef} width="300px" height="300px"  style={{border:'2px dashed blue'}}></canvas>
                                  <div style={{width:100,height:100,backgroundColor:'yellow',opacity:.3,position:'absolute',left:100,top:100}}></div>
                                </div>
                                <div className="btn-group" role="group" >
                                  <button type="button" className="btn btn-default" onClick={()=>this.bigger()}>放大</button>
                                  <button type="button" className="btn btn-default" onClick={()=>this.smaller()}>缩小</button>
                                  <button type="button" className="btn btn-default" onClick={()=>this.confirm()}>确定</button>
                                </div>
                            </>
                           )
                       }
                   </div>
                   <div className="col-md-4 avatar" >
                       {
                           this.state.file&&(
                            <>
                             <img  ref={this.avatarRef} style={{border:'2px dashed pink',width:'100px',height:'100px'}}/>
                             <p> <button className="btn btn-default" onClick={this.upload}>上传</button></p>
                            </>
                           )
                       }
                   </div>
               </div>  
           </div>
       )
   }   
}

7.3 server.js #

server.js

let express = require('express');
let path = require('path');
let cors = require('cors');
let app = express();
app.use(cors());
app.use(express.static(path.join(__dirname,'public')));
const multer = require('multer');
app.use(multer({dest: './uploads'}).single('avatar'));
app.post('/upload', function(req, res){
    res.json({success:true});
});
app.listen(8080,()=>{
    console.log('server started at port 8080');
});

8.音频的裁剪和预览 #

  • ffmpeg
  • song
  • ffmpeg-worker-mp4.js

8.1 index.js #

import React from 'react';
import ReactDOM from 'react-dom';
import Audio from './Audio';

ReactDOM.render(
  <Audio />,
  document.getElementById('root')
);

8.2 src\Audio.js #

src\Audio.js

import React from 'react';
import axios from 'axios';
export default class Audio extends React.Component {
  audioRef = React.createRef()
  audioClipRef = React.createRef()
  startRef = React.createRef()
  endRef = React.createRef()
  clip = async () => {
    this.worker = createWorker('/ffmpeg-worker-mp4.js');
    let response = await axios({ url: '/song.mp3', method: 'get', responseType: 'arraybuffer' });
    let originArrayBuffer = response.data;
    let start = parseInt(this.startRef.current.value);
    let end = parseInt(this.endRef.current.value);
    let duration = end - start;
    let resultArrayBuffer = (await toPromise(
      this.worker,
      getClipCommand(originArrayBuffer, start, duration)
    )).data.data.MEMFS[0].data;

    let clipBlob = audioBufferToBlob(resultArrayBuffer);
    let audio= this.audioClipRef.current 
    audio.src = URL.createObjectURL(clipBlob);
    audio.load();
    audio.play();
  };
  render() {
    return (
      <div>
        <input ref={this.startRef} defaultValue={0} />
        <input ref={this.endRef} defaultValue={10} />
        <button type="button" className="primary" onClick={this.clip}>clip</button>
        <audio ref={this.audioRef} controls src="/song.mp3"></audio>
        <audio ref={this.audioClipRef} controls></audio>
      </div>
    )
  }
}

function createWorker(workerPath) {
  return new Worker(workerPath);
}
function getClipCommand(arrayBuffer, start = 0, duration = 10) {
  return {
    type: "run",
    arguments: `-ss ${start} -i input.mp3 ${
      duration ? `-t ${duration} ` : ""
      }-acodec copy output.mp3`.split(" "),
    MEMFS: [
      {
        data: new Uint8Array(arrayBuffer),
        name: "input.mp3"
      }
    ]
  };
}
function toPromise(worker, info) {
  return new Promise((resolve) => {
    const onSuccess = function (event) {
      switch (event.data.type) {
        case "done":
          worker.removeEventListener("message", onSuccess);
          resolve(event);
          break;
        default:
          break;
      }
    };
    worker.addEventListener("message", onSuccess);
    info && worker.postMessage(info);
  });
}


function audioBufferToBlob(arrayBuffer) {
  const file = new File([arrayBuffer], 'test.mp3', {
    type: 'audio/mp3',
  });
  return file;
}

访问验证

请输入访问令牌

Token不正确,请重新输入