前端AI语音方面的实现
前端实现语音识别及判断声音大小和浏览器诵读功能
- 前言
- 第一章:语音识别
- 一、开始写代码
- 写html和简单的css
- js代码
- 二、知识点讲解
- 属性介绍:
- 方法介绍:
- 事件介绍
- 三、兼容性介绍
- 兼容写法
- 四、实战演习
- 全部代码:
- 结尾:
- 第二章:判断语音声音大小做个小样式
- 一:根据第一个需求代码进行拓展
- 二、知识点整理
- mediaDevices
- AudioContext
- 三、兼容性介绍
- 第三章:浏览器复读功能实现
- 一、代码展示
- 二、知识点整理
- 三、兼容性介绍
- 第四章:最终效果展示:
- 完整代码
前言
今天我们来点有意思的,AI语音转换!当我们遇到语音转换的需求感觉,哇,好难啊,这怎么开发啊。其实这是很简单的,今天笔者就来给大家演示一下我们用js实现语音转换功能!
首先我们先来做俩个按钮,一个开始按钮一个结束并开始转换语音的按钮:
第一章:语音识别
一、开始写代码
写html和简单的css
<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><style>* {margin: 0;padding: 0;}body {display: flex;justify-content: space-around;align-items: center;}.startBtn, .endBtn {display: block;width: 150px;height: 120px;border: 2px solid;margin: 10px;}</style>
</head>
<body><button onclick="start()" class="startBtn">开始说话</button><br /><button onclick="end()" class="endBtn">结束并转换普通话</button>
</body>
</html>
然后我们在控制台搞一些调试信息,并将最后的转换结果alert出来!
js代码
<script>var recognition = new webkitSpeechRecognition() || new SpeechRecognition();recognition.lang = 'cmn-Hans-CN'; //定义普通话 (中国大陆)function start() {console.log('start')// 开启recognition.start();}function end() {console.log('end')// 停止recognition.stop();}// 当调用recognition的stop的时候会触发此对象的onresult事件,然后我们在这里获取我们的转换结果。recognition.onresult = function(event) {alert(event.results[0][0].transcript);}
</script>
二、知识点讲解
我们可以把这个SpeechRecognition内置对象console出来看看他都有什么属性和方法
属性介绍:
属性 | 作用 | 参数 |
---|---|---|
grammars | 此属性存储了SpeechGrammar对象的集合,这些对象表示对此识别有效的语法。 | 参考地址 |
lang | 此属性将使用有效的BCP 47语言标签设置请求识别的语言。如果没有设置它仍然未设置为脚本获得,但将默认使用该语言的HTML文档的根元素和相关层次的。当输入请求打开与识别服务的连接时,将计算并使用此默认值。 | 与html的lang属性一样,都是枚举 |
continuous | 此属性设置为false时,用户代理必须响应于开始识别(例如,交互的单个转弯模式)返回不超过一个最终结果。当其设置为true时,用户代理必须响应于开始的识别(例如听写),返回代表多个连续识别的零个或多个最终结果。默认值必须为false。此属性的设置不会影响中期结果。 | boolean |
interimResults | 控制是否返回中期结果,设置为true时,应返回中期结果。设置为false时,不得返回中期结果。默认值必须为false。此属性不会影响最终结果。 | boolean |
maxAlternatives | 此属性设置SpeechRecognitionAlternative每个结果的最大数量。默认值1。 | 其值在[0,18446744073709551615]范围内 |
方法介绍:
方法 | 介绍 |
---|---|
start() | 调用start方法时,它表示Web应用程序希望开始识别的时间。当语音输入通过输入媒体流实时流式传输时,此开始呼叫表示该服务必须开始收听并尝试匹配与此请求关联的语法的时间。一旦系统成功侦听识别,用户代理必须引发一个开始事件。如果在已经启动的对象上调用了start方法(也就是说,先前已经调用过start,并且没有在该对象上引发错误或结束事件),则用户代理必须抛出“ InvalidStateError” DOMException并忽略该调用。 |
stop() | stop方法表示对识别服务的一条指令,该指令停止听更多的音频,并尝试仅使用已为该识别接收的音频来返回结果。stop方法的典型用法可能是用于Web应用程序,其中最终用户正在进行端点指向,类似于对讲机。最终用户可能会按住空格键与系统对话,而在按下空格键时会发生开始调用,并且在释放空格键时会调用stop方法,以确保系统不再监听用户。调用stop方法后,语音服务不得收集其他音频,也不得继续收听用户的声音。语音服务必须尝试根据已为该识别而收集的音频返回识别结果(或不匹配)。如果在已经停止或正在停止的对象上调用stop方法(即从未在其上调用start),发生了end或error事件,或者先前已调用stop),则用户代理必须忽略该调用。 |
abort() | 中止方法是一种请求,要求立即停止侦听并停止识别,并且不返回任何信息,但系统已完成。调用中止方法时,语音服务必须停止识别。一旦语音服务不再连接,用户代理必须引发结束事件。如果在已经停止或正在中止的对象上调用了中止方法(也就是说,从未在其上调用start,在其上引发了end或error事件,或者先前已在其上调用过中止),则用户代理必须忽略电话。 |
事件介绍
事件 | 介绍 |
---|---|
audiostart | 用户代理开始捕获音频时触发 |
soundstart | 当检测到某种声音(可能是语音)时触发。这必须以低延迟触发,例如通过使用客户端能量检测器。该audiostart事件必须已在soundstart事件之前发射。 |
speechstart | 当将用于语音识别的语音开始时触发。该audiostart事件必须已在speechstart事件之前发射。 |
speechend | 当将用于语音识别的语音结束时触发。该speechstart事件必须始终被speechend之前解雇 |
soundend | 当不再检测到某些声音时触发。这必须以低延迟触发,例如通过使用客户端能量检测器。该soundstart事件必须始终被soundend之前解雇。 |
audioend | 用户代理完成音频捕获后触发。该audiostart事件必须始终被audioend之前解雇。 |
result | 当语音识别器返回结果时触发。该事件必须使用SpeechRecognitionEvent接口。该audiostart事件必须已在结果事件之前发射。 |
nomatch | 当语音识别器返回没有识别假设达到或超过置信度阈值的最终结果时触发。该事件必须使用SpeechRecognitionEvent接口。results事件中的属性可能包含低于置信度阈值或为空的语音识别结果。该audiostart事件必须已在NOMATCH事件之前发射。 |
error | 发生语音识别错误时触发。该事件必须使用SpeechRecognitionErrorEvent接口 |
start | 当识别服务开始收听音频以进行识别时触发 |
end | 服务断开连接时触发。无论会话结束的原因如何,都必须始终在会话结束时生成事件。 |
三、兼容性介绍
非常遗憾的告诉大家这个api的兼容性并不好,一般笔者只会在chrome上面使用它,如果不是chrome浏览器的话那么笔者就会调用后端的接口。比如用java或者python等语言实现。
很多朋友很奇怪,既然兼容性不好为什么要用它,因为调用后端接口势必就会给服务器带来一定的压力,而且还和网速等等有很大的关系。我们前端自己能实现的话肯定是优先我们自身实现。
兼容写法
<script>function start() {voiceConversion('start')}function end() {voiceConversion('end')}function voiceConversion(type) {console.log(type);try {let recognition = new webkitSpeechRecognition() || new SpeechRecognition();console.log(recognition)recognition.lang = 'cmn-Hans-CN'; //普通话 (中国大陆)if (type === 'start') {// 开启recognition.start();} else {// 停止recognition.stop();}recognition.onresult = function(event) {alert(event.results[0][0].transcript);}} catch (e) {console.log('调用后端接口');}}
</script>
四、实战演习
我们接下来给大家展示一下当用户点击录音的时候实时的识别出用户说的话并展示出来:
全部代码:
<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><style>* {margin: 0;padding: 0;}.wrapBox {display: flex;justify-content: space-around;align-items: center;}.startBtn, .endBtn {display: block;width: 150px;height: 120px;border: 2px solid;margin: 10px;}</style>
</head>
<body><div class="wrapBox"><button onclick="start()" class="startBtn">开始说话</button><br /><button onclick="end()" class="endBtn">结束并转换普通话</button></div><div id="resultText"></div><script>const resultTextDiv = document.querySelector('#resultText');function start() {voiceConversion('start')}function end() {voiceConversion('end')}function voiceConversion(type) {console.log(type);try {let recognition = new webkitSpeechRecognition() || new SpeechRecognition();recognition.lang = 'cmn-Hans-CN'; //普通话 (中国大陆)recognition.interimResults = true;if (type === 'start') {// 开启recognition.start();} else {// 停止recognition.stop();}recognition.onresult = function(event) {const text = event.results[0][0].transcript;resultTextDiv.innerHTML = text;}} catch (e) {console.log('调用后端接口');}}</script>
</body>
</html>
结尾:
这只是我们开始的一个最基本的需求,我们还需要加入获取声音大小的需求以及复读的功能
第二章:判断语音声音大小做个小样式
一:根据第一个需求代码进行拓展
我们需要在里面追加一个html标签,用来展示我们的声音大小:
<span id="volumeBox"></span>
然后定义一个检测声音大小的函数:
// 获取我们的音量盒子元素
const mystatus = document.getElementById('volumeBox');
let mediaStreamSource = null,scriptProcessor = null;
// 开始检测音量大小的函数
function beginDetect() {let audioContext = new (window.AudioContext || window.webkitAudioContext)();if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {// 获取用户的 media 信息navigator.mediaDevices.getUserMedia({audio: true}).then((stream) => {// 将麦克风的声音输入这个对象mediaStreamSource = audioContext.createMediaStreamSource(stream);// 创建一个音频分析对象,采样的缓冲区大小为4096,输入和输出都是单声道scriptProcessor = audioContext.createScriptProcessor(4096,1,1);// 将该分析对象与麦克风音频进行连接mediaStreamSource.connect(scriptProcessor);// 解决 Chrome 自身的 bugscriptProcessor.connect(audioContext.destination);// 开始处理音频scriptProcessor.onaudioprocess = (e) => {// 获得缓冲区的输入音频,转换为包含了PCM通道数据的32位浮点数组const buffer = e.inputBuffer.getChannelData(0);// 获取缓冲区中最大的音量值const maxVal = Math.max.apply(Math, buffer);// 显示音量值mystatus.innerHTML = `您的音量值:${ Math.round(maxVal * 100)}`;};}).catch((error) => {mystatus.innerHTML = `获取音频时好像出了点问题。${error}`;})} else {mystatus.innerHTML = '您的浏览器不支持识别声音大小';}
};
// 关闭检测音量大小
function stopDetect() {scriptProcessor.disconnect ? scriptProcessor.disconnect() : console.log('无需关闭任何');
}
然后我们分别在开始说话和结束说话的时候调用这俩个函数:
// 在voiceConversion函数里进行局部追加代码
if (type === 'start') {// 开启beginDetect();recognition.start();
} else {// 停止stopDetect();recognition.stop();
}
我们可以根据maxValue进行设计一些其他的样式。而不是像笔者发布在这里仅仅展示了字体而已。
比如【类似这种】:
有想要这种类似的样式的可以私聊笔者,由于本博文内容过多,代码就不放出来了哈~。
二、知识点整理
mediaDevices
方法 | 介绍 |
---|---|
MediaDevices.enumerateDevices() | 获取有关系统中可用的媒体输入和输出的一系列信息 |
getSupportedConstraints() | 返回一个对象,该对象符合MediaTrackSupportedConstraints指示MediaStreamTrack接口上支持哪些可约束属性的信息。 |
getDisplayMedia() | 提示用户选择一个显示器或显示器的一部分(例如窗口)以捕获MediaStream为共享或记录目的。返回解析为的Promise MediaStream。 |
MediaDevices.getUserMedia() | 在用户通过提示允许的情况下,打开系统上的相机或屏幕共享和/或麦克风,并提供 MediaStream 包含视频轨道和/或音频轨道的输入。 |
AudioContext
该AudioContext接口表示由链接在一起的音频模块构建的音频处理图,每个音频模块由表示AudioNode。音频上下文既控制其包含的节点的创建,也控制音频处理或解码的执行。您需要先创建一个,AudioContext然后再执行其他操作,因为所有事情都在上下文中发生。
方法 | 介绍 |
---|---|
AudioContext.close() | 关闭音频上下文,释放它使用的所有系统音频资源。 |
AudioContext.createMediaElementSource() | 创建与MediaElementAudioSourceNode相关联HTMLMediaElement。这可用于播放和操作来自或元素的音频。 |
AudioContext.createMediaStreamSource() | 创建一个MediaStreamAudioSourceNode与MediaStream表示相关联的音频流,该音频流可能来自本地计算机麦克风或其他来源。 |
AudioContext.createMediaStreamDestination() | 创建MediaStreamAudioDestinationNode与MediaStream表示一个音频流的关联,该音频流可以存储在本地文件中或发送到另一台计算机。 |
AudioContext.createMediaStreamTrackSource() | 创建MediaStreamTrackAudioSourceNode与一个MediaStream表示媒体流轨道的关联。 |
AudioContext.getOutputTimestamp() | 返回一个新AudioTimestamp对象,其中包含两个与当前音频上下文有关的音频时间戳值 |
AudioContext.resume() | 在以前已暂停/暂停的音频上下文中恢复时间的进展。 |
AudioContext.suspend() | 挂起音频环境中的时间,暂时停止音频硬件访问并减少进程中的CPU /电池使用量。 |
AudioContext.createScriptProcessor() | AudioContext 接口的createScriptProcessor() 方法创建一个ScriptProcessorNode 用于通过JavaScript直接处理音频. |
createScriptProcessor()接收三个参数:
bufferSize
缓冲区大小,以样本帧为单位。具体来讲,缓冲区大小必须是下面这些值当中的某一个: 256, 512, 1024, 2048, 4096, 8192, 16384. 如果不传,或者参数为0,则取当前环境最合适的缓冲区大小, 取值为2的幂次方的一个常数,在该node的整个生命周期中都不变.
该取值控制着audioprocess事件被分派的频率,以及每一次调用多少样本帧被处理. 较低bufferSzie将导致一定的延迟。较高的bufferSzie就要注意避免音频的崩溃和故障。推荐作者不要给定具体的缓冲区大小,让系统自己选一个好的值来平衡延迟和音频质量。
numberOfInputChannels
值为整数,用于指定输入node的声道的数量,默认值是2,最高能取32.
numberOfOutputChannels
值为整数,用于指定输出node的声道的数量,默认值是2,最高能取32.
语法:
var audioCtx = new AudioContext();
myScriptProcessor = audioCtx.createScriptProcessor(bufferSize, numberOfInputChannels, numberOfOutputChannels);
三、兼容性介绍
MediaDevices除了IE全军覆没以外,其他的浏览器支持情况良好
AudioContext也是一样的。
第三章:浏览器复读功能实现
一、代码展示
<!--追加一个选择语言的select标签-->
<div>选择语言:<select name="" id=""></select></div>
首先获取浏览器支持的语言,然后追加option标签放到select标签里供我们选择
注意点:最好将recognition.interimResults = true;去掉,否者交互是非常不友善的。
// 首先获取浏览器支持的语言
const synth = window.speechSynthesis;
let voices = synth.getVoices();
const voiceSelect = document.querySelector('select');
function populateVoiceList() {voices = synth.getVoices();for(let i = 0; i < voices.length ; i++) {const option = document.createElement('option');option.textContent = voices[i].name + ' (' + voices[i].lang + ')';if(voices[i].default) {option.textContent += ' -- DEFAULT';}option.setAttribute('data-lang', voices[i].lang);option.setAttribute('data-name', voices[i].name);voiceSelect.appendChild(option);}
}
populateVoiceList();
if (synth.onvoiceschanged !== undefined) {synth.onvoiceschanged = populateVoiceList;
}
在我们recognition.onresult那里把获取到的text朗诵出来
const utterThis = new window.SpeechSynthesisUtterance(text);
const selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
for(let i = 0; i < voices.length;i ++){if(voices[i].name === selectedOption){utterThis.voice =voices[i];}
}
synth.speak(utterThis);
二、知识点整理
首先是SpeechSynthesisUtterance对象,主要用来构建语音合成实例,例如上面代码中的实例对象utterThis。我们可以直接在构建的时候就把要读的文字内容写进去。也可以在后面设置它的text属性。
属性 | 介绍 |
---|---|
text | 此属性指定为此语音要合成和说出的文本。这可以是纯文本,也可以是格式正确的完整SSML文档。[SSML]对于不支持SSML或仅支持某些标签的语音合成引擎,用户代理或语音引擎必须剥离不支持的标签并说出文字。文本的最大长度可能限制为32,767个字符。 |
lang | 此属性使用有效的BCP 47语言标签为语音指定语音合成的语言。[BCP47]如果没有设置它仍然未设置为脚本获得,但将默认使用该语言的HTML文档的根元素和相关层次的。当输入请求打开与识别服务的连接时,将计算并使用此默认值。 |
voice | 类型为SpeechSynthesisVoice,可为空此属性指定Web应用程序希望使用的语音合成语音。当一个SpeechSynthesisUtterance对象被创建这个属性必须被初始化为null。如果在speak()方法调用时将此属性设置为所SpeechSynthesisVoice返回的对象之一getVoices(),则用户代理必须使用该声音。如果在speak()方法调用时此属性未设置或为null ,则用户代理必须使用用户代理的默认语音。用户代理默认语音应支持当前语言(请参阅参考资料lang),并且可以是本地或远程语音服务,并且可以通过用户代理提供的接口(例如浏览器配置参数)合并最终用户的选择。 |
volume | 此属性指定话语的说话音量。它的范围是0到1(含0和1),其中0是最低音量,1是最高音量,默认值为1。如果使用SSML,则此值将被标记中的韵律标记覆盖。 |
rate | 此属性指定话语的语速。这是相对于此语音的默认速率。1是语音合成引擎或特定语音支持的默认速率(应对应于正常的语音速率)。2是两倍的速度,而0.5是一半的速度。严格禁止小于0.1或大于10的值,但是语音合成引擎或特定语音可能会进一步限制最小和最大速率,例如,即使您指定的值大于3,特定语音实际上可能不会比正常语音快3倍。如果使用SSML,则此值将被标记中的prosody标签覆盖。 |
pitch | 此属性指定发声的说话音调。范围在0到2之间(含0和2),其中0是最低音高,2是最高音高。1对应于语音合成引擎或特定语音的默认音高。语音合成引擎或语音可能会进一步限制最小和最大速率。如果使用SSML,则该值将被标记中的prosody标签覆盖。 |
然后是SpeechSynthesis对象。它是用于控制文本到语音输出的脚本化Web API。
属性 | 介绍 |
---|---|
pending | 如果全局SpeechSynthesis实例的队列包含尚未开始讲话的所有话语,则此属性为true。 |
speaking | 如果正在说语音,则此属性为true。具体来说,如果已经开始说出话语而还没有完成说出话语。这与全局SpeechSynthesis实例是否处于暂停状态无关。 |
paused | 当全局SpeechSynthesis实例处于暂停状态时,此属性为true。此状态与队列中是否有任何内容无关。新窗口的全局SpeechSynthesis实例的默认状态为非暂停状态。 |
方法 | 介绍 |
---|---|
speak(utterance) | 对于全局SpeechSynthesis实例,此方法将SpeechSynthesisUtterance对象的发音附加到队列的末尾。它不会更改SpeechSynthesis实例的暂停状态。如果SpeechSynthesis实例已暂停,它将保持暂停状态。如果未暂停并且队列中没有其他语音,则立即说出该语音,否则将该语音排入队列,以便在队列中的其他语音都说完之后开始讲话。如果在调用此方法之后且在相应结束或错误之前对SpeechSynthesisUtterance对象进行了更改事件,但未定义这些更改是否会影响您所说的内容,并且这些更改可能会导致返回错误。SpeechSynthesis对象获得了SpeechSynthesisUtterance对象的专有所有权。将其作为speak()参数传递给另一个SpeechSynthesis对象应引发异常。(例如,两个框架可能具有相同的原点,并且每个框架都将包含一个SpeechSynthesis对象。) |
cancel() | 此方法从队列中删除所有语音。如果说出话语,则说话立即停止。此方法不会更改全局SpeechSynthesis实例的暂停状态。 |
pause() | 此方法将全局SpeechSynthesis实例置于暂停状态。如果正在说出话语,它将暂停中间的话语。(如果在SpeechSynthesis实例已经处于暂停状态时调用,它将不执行任何操作。) |
resume() | 此方法将全局SpeechSynthesis实例置于非暂停状态。如果正在说出话语,它将在暂停时继续说出话语,否则它将开始说出队列中的下一个话语(如果有)。(如果在SpeechSynthesis实例已经处于非暂停状态时调用,它将不执行任何操作。) |
getVoices() | 此方法返回可用的声音。用户语音取决于哪些声音可用。如果没有可用的语音,或者尚不清楚可用语音列表(例如:服务器端综合,其中异步确定列表),则此方法必须返回长度为零的SpeechSynthesisVoiceList。 |
voiceschanged | 当getVoices方法将返回的SpeechSynthesisVoiceList的内容已更改时触发。示例包括:服务器端综合,其中异步确定列表,或者安装/卸载客户端语音。 |
三、兼容性介绍
第四章:最终效果展示:
完整代码
<!doctype html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><style>* {margin: 0;padding: 0;}.wrapBox {display: flex;justify-content: space-around;align-items: center;}.startBtn, .endBtn {display: block;width: 150px;height: 120px;border: 2px solid;margin: 10px;font-size: 18px;}.endBtn:hover {background: orange;}#volumeBox {border: 1px solid;flex: 1;margin: 0 20px;display: flex;}.child {background: none;width: 20%;border-right: 1px solid;height: 100%;}</style>
</head>
<body>
<!-- 参考网址:MDN与https://wicg.github.io/speech-api/#speechgrammarlist--><div class="wrapBox"><button onclick="voiceConversion('start')" class="startBtn">开始说话</button><br /><button onclick="voiceConversion('end')" class="endBtn">结束并转换普通话</button></div><div id="resultText"></div><div>选择语言:<select name="" id=""></select></div><header class="header"><h1>HTML5 获取当前系统麦克风音量</h1><hr></header><div class="container"><div style="display: flex; justify-content: space-between;"><img src="./voice.png" alt=""><div id="volumeBox"><div class="child"></div><div class="child"></div><div class="child"></div><div class="child"></div><div class="child"></div></div></div></div><script>// 语音结果文本const resultTextDiv = document.querySelector('#resultText');// 获取浏览器支持的语言const synth = window.speechSynthesis;let voices = synth.getVoices();const voiceSelect = document.querySelector('select');function populateVoiceList() {voices = synth.getVoices();for(let i = 0; i < voices.length ; i++) {const option = document.createElement('option');option.textContent = voices[i].name + ' (' + voices[i].lang + ')';if(voices[i].default) {option.textContent += ' -- DEFAULT';}option.setAttribute('data-lang', voices[i].lang);option.setAttribute('data-name', voices[i].name);voiceSelect.appendChild(option);}}populateVoiceList();if (synth.onvoiceschanged !== undefined) {synth.onvoiceschanged = populateVoiceList;}function voiceConversion(type) {try {let recognition = new webkitSpeechRecognition() || new SpeechRecognition();recognition.lang = 'cmn-Hans-CN'; //普通话 (中国大陆)// recognition.interimResults = true;if (type === 'start') {// 开启beginDetect();recognition.start();} else {// 停止stopDetect();recognition.stop();}recognition.onresult = function(event) {const text = event.results[0][0].transcript;resultTextDiv.innerHTML = text;const utterThis = new window.SpeechSynthesisUtterance(text);const selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');for(let i = 0; i < voices.length;i ++){if(voices[i].name === selectedOption){utterThis.voice =voices[i];}}synth.speak(utterThis);}} catch (e) {console.log('调用后端接口');}}const mystatus = document.getElementById('volumeBox');const childs = document.getElementsByClassName('child');let mediaStreamSource = null,scriptProcessor = null;function beginDetect() {if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {// 获取用户的 media 信息navigator.mediaDevices.getUserMedia({audio: true}).then((stream) => {let audioContext = new (window.AudioContext || window.webkitAudioContext)();// 将麦克风的声音输入这个对象mediaStreamSource = audioContext.createMediaStreamSource(stream);// 创建一个音频分析对象,采样的缓冲区大小为4096,输入和输出都是单声道scriptProcessor = audioContext.createScriptProcessor(4096,1,1);// 将该分析对象与麦克风音频进行连接mediaStreamSource.connect(scriptProcessor);// 解决 Chrome 自身的 bugscriptProcessor.connect(audioContext.destination);// 开始处理音频scriptProcessor.onaudioprocess = (e) => {// 获得缓冲区的输入音频,转换为包含了PCM通道数据的32位浮点数组const buffer = e.inputBuffer.getChannelData(0);// 获取缓冲区中最大的音量值const maxVal = Math.max.apply(Math, buffer) * 100;// 显示音量值let num = 0;if (maxVal < 20) {num = 1;} else if (maxVal < 40) {num = 2;} else if (maxVal < 60) {num = 3;} else if (maxVal < 80) {num = 4;} else {num = 5;}for (let i = 0; i < 5; i++) {if (i < num) {childs[i].style.background = 'red'} else {childs[i].style.background = 'none'}}};}).catch((error) => {mystatus.innerHTML = `获取音频时好像出了点问题。${error}`;})} else {mystatus.innerHTML = '您的浏览器不支持识别声音大小';}};function stopDetect() {scriptProcessor.disconnect ? scriptProcessor.disconnect() : console.log('无需关闭任何');}</script>
</body>
</html>
前端AI语音方面的实现相关推荐
- 离线语音识别软件_从音乐识别软件起家,这家公司如何备战车载AI语音市场GGAI对话...
加入高工智能汽车专业行业群(自动驾驶5群,车联网智能座舱3群,智能网联商用车2群),加微信:17157613659,出示名片,仅限智能网联汽车软硬件供应商及OEM厂商. 早在2016年,亚马逊推出的语 ...
- 全新 AI 语音芯片、双麦 AIoT 模组,科大讯飞硬核技术助力智能家电创新
据艾瑞咨询的数据显示,2017 年中国智能家居市场规模为 3342.3 亿元,其中智能家电规模为2828.0亿元,占比87%.预计到 2020 年智能家电的市场规模将达到 5155.0 亿元. 智能家 ...
- esp32语音控制_【动态】乐鑫发布 AI 语音麦克风阵列开发板 ESP32Korvo
乐鑫信息科技(股票代码:688018)发布 AI 语音麦克风阵列开发板 ESP32-Korvo. 这是一款针对物联网嵌入式设备的 AI 语音开发板,基于乐鑫的旗舰芯片 ESP32,搭载多麦克风阵列,能 ...
- esp32语音控制_乐鑫发布针对物联网嵌入式设备AI语音麦克风阵列开发板
乐鑫信息科技(股票代码:688018)发布 AI 语音麦克风阵列开发板 ESP32-Korvo .这是一款针对物联网嵌入式设备的 AI 语音开发板,基于乐鑫的旗舰芯片 ESP32,搭载多麦克风阵列,能 ...
- 【ESP32】【乐鑫发布 AI 语音麦克风阵列开发板 ESP32-Korvo】
近年来,随着人工智能和物联网的兴起,语音逐渐成为我们与智能设备交互的一种典型方式.在连接设备(例如智能家居设备.智能办公设备.智能穿戴设备等)上嵌入 AI 语音也成为了一大热点.乐鑫信息科技(股票代码 ...
- 2023年AI语音会议汇总
2023年,AI语音领域学术会议精彩纷呈,语音之家汇总了国内外重要的会议呈现给大家,大家可根据时间统筹安排好2023年的学术活动交流行程.如果信息有误,欢迎指正. ICASSP 2023 2023 I ...
- Azure AI的又一里程碑,Neural TTS新模型呈现真人般情感饱满的AI语音
在人与人之间的对话中,即使是同样的字句,也会因为所处情景和情感的不同而表现出丰富的抑扬顿挫,而这种动态性恰恰是各种AI合成语音的"软肋".相比于人类讲话时丰富多变的语气,AI语音的 ...
- Azure Neural TTS能让AI语音自然逼真到什么程度?
摘要:微软Azure Neural TTS让AI语音像真人一样富有感情,自然逼真. Neural TTS(神经网络文本转语音)是微软Azure认知服务的强大语音合成功能,自推出以来,已被广泛应用于从语 ...
- 助力企业抗疫,360金融推出免费AI语音机器人
复工潮来临之际,为帮助各大企业进行高效的内部防疫宣传.员工行程信息收集以及快速生成公司内部防疫排班表,360金融针对复工企业的需求痛点推出了AI语音机器人,以助力企业更高效的防疫.抗疫. 针对复工企业 ...
最新文章
- 下拉菜单连动效果的一种用法
- 高度可扩展的类脑神经拟态硬件,完成了字母识别和人脸识别
- python interactive 清空内存_Python 内存回收问题
- 团队任务3:第一次冲刺
- linux中bc用法英文,使用GNU bc在Linux Shell中进行数学运算
- 功能对等四个原则_强直患者功能锻炼十分重要
- centos7 日志文件
- java post 请求体构建_java – 从HttpServletRequest获取POST请求体
- python表白代码-如何用Python代码向心爱的姑娘花式表白?
- 中国石油大学《马克思主义基本原理》第二阶段在线作业
- Linux 下搭建web压力测试工具web polygraph
- php展厅控制系统,展厅展馆设计智能中控系统
- js中math常用使用方法
- Excel可以将中文翻译成英文
- ORA-29491: invalid table for chunking 错误记录
- pypython画图中的cumsum是什么_Python绘图之matplotlib基本语法
- bili弹幕姬_b站弹幕姬|b站弹幕姬下载_v1.0.1.126官方版_9号软件下载
- 计算机软件过期黑屏怎么办,Adobe flashplayer过期怎么办
- 战地4高性能服务器,战地4服务器推荐配置
- nested exception is redis.clients.jedis.exceptions.JedisDataException: NOAUTH Authentication requir