// 创建一个16字节定长的buffer
let buffer = new ArrayBuffer(16);
处理音频数据前置知识点
struct someStruct {
unsigned long id; // long 32bit
char username[16];// char 8bit
float amountDue;// float 32bit
};
let buffer = new ArrayBuffer(24);
// ... read the data into the buffer ...
let idView = new Uint32Array(buffer, 0, 1);
let usernameView = new Uint8Array(buffer, 4, 16);
let amountDueView = new Float32Array(buffer, 20, 1);
最近准备一个技术分享,看到以前做的一个语音转文字的功能,放在slides上落灰了,索性整理到这里和大家分享下。
语音转写流程图
PC端浏览器如何录音
AudioContext是什么?
AudioContext接口表示由链接在一起的音频模块构建的音频处理图形,每个模块由一个AudioNode表示。
一个audio context会控制所有节点的创建和音频处理解码的执行。所有事情都是在一个上下文中发生的。
ArrayBuffer:音频二进制文件 decodeAudioData:解码 AudioBufferSourceNode: connect用于连接音频文件 start播放音频 AudioContext.destination:扬声器设备
AudioNode是什么?
初见:MediaDevice.getUserMedia()是什么
demo演示:https://github.com/FrankKai/nodejs-rookie/issues/54
相识:MediaDevice.getUserMedia()是什么
为什么localhost能播放,预生产不能播放?
没招了,在stackOverflow提了一个问题
Why navigator.mediaDevice only works fine on localhost:9090?
网友说只能在HTTPS环境做测试。
嗯,生产是HTTPS,可以用。???但是我localhost哪里来的HTTPS环境???所以到底是什么原因?
终于从chromium官方更新记录中找到了答案 https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins
Chrome 47以后,getUserMedia API只能允许来自“安全可信”的客户端的视频音频请求,如HTTPS和本地的Localhost。如果页面的脚本从一个非安全源加载,navigator对象中则没有可用的mediaDevices对象,Chrome抛出错误。
语音功能预生产,预发需要以下配置: 地址栏输入chrome://flags 搜索:insecure origins treated as secure 配置:http://foo.test.gogo.com
生产的https://foo.gogo.com是完全OK的
js中的数据类型TypedArray知多少?
typed array基本知识: TypedArray Buffer ArrayBuffer View Unit8Array Unit16Array Float64Array
https://github.com/FrankKai/FrankKai.github.io/issues/164
typed array使用例子
处理音频数据前置知识点
偏移量为什么是1,4,20? 因为32/8 = 4。0到3属于idView。8/8 =1。4到19属于usernameView。32/8 = 4。20到23属于amountView。
代码实现及源码分析
一、代码实现
流程图:1.初始化recorder 2.开始录音 3.停止录音
设计思路:录音器,录音器助手,语音构造器,语音转换器
二、尝试过的技术方案
1.人人网某前端开发
https://juejin.im/post/5b8bf7e3e51d4538c210c6b0
无法灵活指定采样位数,采样频率和声道数;不能输出多种格式的音频;因此弃用。
2.js-audio-recorder
可以灵活指定采样位数,采样频率和声道数;可输出多种格式的音频;提供多种易用的API。
github地址:https://github.com/2fps/recorder
没学过语音相关的知识,因此只能参考前辈的成果边学边做!
代码实现及源码分析
一、录音过程拆解
1.初始化录音实例
2.开始录音
3.停止录音
二、设计思路
三、源码分析之初始化实例-constructor
new DataView(buffer).setInt16(0, 256, true)怎么理解?
控制内存存储的大小端模式。 true是littleEndian,也就是小端模式,地位数据存储在低地址,Int16Array uses the platform's endianness。
所谓大端模式,指的是低位数据高地址,0x12345678,12存buf[0],78(低位数据)存buf[3](高地址)。也就是常规的正序存储。 小端模式与大端模式相反。0x12345678,78存在buf[0],存在低地址。
三.源码分析之初始化实例-initRecorder
三.源码分析之开始录音-start
三.源码分析之停止录音及辅助函数
四.源码分析之核心算法-encodeWAV
四.源码分析之核心算法-encodePCM
语音发送和实时转写
音频文件存哪里?
语音录一次往阿里云OSS传一次吗?
这样做显示是浪费资源的。
编辑状态:存本地,当前浏览器端可访问即可
发送状态:存OSS,公网可访问
如何存本地?Blob Url的方式保存
如何存OSS?从cms获取token,上传到OSS的xxx-audio bucket,然后得到一个hash
Blob Url那些事儿
blob对象在前端开发中是非常常见的,下面我将列举几个应用场景:
canvas toDataURL后的base64格式属性,会超出标签属性值有最大长度的限制
<input type="file" />
上传文件之后的File对象,最初只想在本地留存,时机合适再上传到服务器创建BlobUrl:URL.createObjectURL(object)
释放BlobUrl:URL.revokeObjectURL(objectURL)
Blob Url那些事儿
URL的生命周期在vue组件中如何表现?
vue的单文件组件共有一个document,这也是它被称为单页应用的原因,因此可以在组件间直接通过blob URL进行通信。 在vue-router采用hash模式的情况下,页面间的路由跳转,不会重新加载整个页面,所以URL的生命周期非常强力,因此在跨页面(非新tab)的组件通信,也可以使用blob URL。 需要注意的是,在vue的hash mode模式下,需要更加注意通过URL.revokeObjectURL()进行的内存释放
URL的生命周期在vue组件中如何表现?
vue的单文件组件共有一个document,这也是它被称为单页应用的原因,因此可以在组件间直接通过blob URL进行通信。 在vue-router采用hash模式的情况下,页面间的路由跳转,不会重新加载整个页面,所以URL的生命周期非常强力,因此在跨页面(非新tab)的组件通信,也可以使用blob URL。 需要注意的是,在vue的hash mode模式下,需要更加注意通过URL.revokeObjectURL()进行的内存释放
https://github.com/FrankKai/FrankKai.github.io/issues/138
实时语音转写服务服务端需要做什么?
提供一个传递存储音频Blob对象的File实例返回文字的接口。
服务端需要如何实现呢?
1.鉴权
客户端在与服务端建立WebSocket链接的时候,需要使用Token进行鉴权
2.start and confirm
客户端发起请求,服务端确认请求有效
3.send and recognize
循环发送语音数据,持续接收识别结果
阿里OSS提供了java,python,c++,ios,android等SDK
https://help.aliyun.com/document_detail/84428.html?spm=a2c4g.11186623.6.574.10d92318ApT1T6
前端代码实现
通用录音组件
通用组件代码分析
https://github.com/2fps/recorder/issues/21
通用组件使用
总结