前端AI语音方面的实现

article/2025/8/9 23:45:03

前端实现语音识别及判断声音大小和浏览器诵读功能

  • 前言
  • 第一章:语音识别
    • 一、开始写代码
        • 写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>

http://chatgpt.dhexx.cn/article/sCEQN2Tc.shtml

相关文章

调用百度ai接口实现图片文字识别详解

调用百度ai接口实现图片文字识别详解 首先先介绍一下这篇博文是干嘛的&#xff0c;为了不浪费大家时间。公司最近和短视频公司合作&#xff0c;需要监控app的截图上的文字是否符合规范&#xff0c;也就是确保其没有违规的文字。到网上找了一些资料发现百度ai提供这个功能&#…

UI界面视觉设计之字体要素--安卓-ios-网页常用字体

怎么设计出从而设计出富有美感和形式感的优秀作品&#xff1f; 1.设计经验的积累。 2. 在每个项目设计中只使用1到2个字体样式&#xff0c;通过对字体大小或颜色来强调重点文案&#xff0c;如图的界面设计中&#xff0c;都是通过字体大小、粗细来区分界面内容中的层级关系。字…

【UI教程】结合PS和AI绘制炫彩2.5D插画

【UI教程】结合PS和AI绘制炫彩2.5D插画 为了此次文章教程,利用下班在家空余时间撸图撸了两个凌晨,原则只做原创精品设计文章,好案例配好文章,希望大家能喜欢,做设计行业文章教程最初目的就是能希望帮助到更多设计师小伙伴,很单纯、很简单 完全免费奉献上我一些能量,我不…

Adobe AI软件解决界面字体过小的方法

转载自&#xff1a;http://www.pc0359.cn/article/jiaocheng/69216.html &#xff0c;图片为本博主自己操作时的截图。 AI是adobe旗下的软件之一&#xff0c;使用过该公司软件的用户应该都有这样的感受&#xff0c;软件功能很强大&#xff0c;可是它的界面字体实在是太小。对于…

视频教程-AI软件与字体设计-Illustrator

AI软件与字体设计 专注提供优质教学内容 CSDN就业班 136.00 立即订阅 扫码下载「CSDN程序员学院APP」&#xff0c;1000技术好课免费看 APP订阅课程&#xff0c;领取优惠&#xff0c;最少立减5元 ↓↓↓ 订阅后&#xff1a;请点击此处观看视频课程 视频教程-AI软件与字体设计…

ai怎么调界面大小_ai软件界面字体特别小 ai菜单栏字体大小怎么改

win8系统装软件,软件那些字体好小,怎么调大,例如PS软件,AI软件里面那些菜单栏字都很小,怎么? 1、桌面空白处单击鼠标右键,选择“屏幕分辨率”; 2、点击“放大或缩小文本和其他项目”; 3、单击屏幕右侧“设置自定义文本大小”; 4、在下拉列表中可以选择默认提供的放大…

ai字体设计(鲜到家)

1、选择合适的字体输入文本内容 2、 选中文字&#xff0c;选择文字菜单&#xff0c;点击创建轮廓&#xff08;将文字转曲&#xff09;&#xff1b;选择倾斜工具&#xff0c;双击后输入角度等参数&#xff0c;确定&#xff0c;用小白工具把鲜字的笔画往下拉一拉&#xff0c;有折…

AI多种设计字体的方法与英文字体收藏

为什么80%的码农都做不了架构师&#xff1f;>>> &#xfeff;&#xfeff;&#xfeff;&#xfeff;&#xfeff;无意间看到了刘兵克的字体改造法&#xff0c;大神&#xff1a;点我。 ZCOOL上有他的字体LOGO专题&#xff0c;感觉比较专业&#xff0c;虽然有些改动并…

【AI】简单的方法教你做一组字体设计

字体设计初级方法交流、学习&#xff0c;喜欢可以分享&#xff0c;下面上设计教程。 首先&#xff0c;你要有一个软件——AI&#xff0c;这一点非常重要&#xff01;&#xff01;切记&#xff01;&#xff01; 然后我们开始设计&#xff0c;这次设计的是工作室出品的一组明信片…

【干货分享】用AI工具设计一款吸引人的字体效果

干货又来啦&#xff01;今天教大家如何使用AI工具设计一款引人注目的字体效果&#xff0c;话不多说&#xff0c;我们直接开始&#xff01; 1、在AI画布中使用钢笔工具勾勒出字母的线条&#xff0c;如图所示 2、使用椭圆工具画一个小的正圆&#xff0c;并填充蓝色渐变。 3、我们…

再续FFT:信号的频谱分析

摘自&#xff1a;http://www.ilovematlab.cn/thread-119939-1-1.html http://www.360doc.com/content/13/1208/18/13670635_335496776.shtml 对于下面这句话该怎么理解&#xff1f; 假设采样频率为Fs&#xff0c;信号频率F&#xff0c;采样点数为N。那么FFT之后结果就是一个为…

实验五 连续信号的频谱分析

目录 一、实验目的二、实验原理1、连续周期信号的傅里叶级数、各次谐波及叠加2、连续周期信号的周期T的变化对频谱的影响3、连续非周期信号的频谱 三、实验内容1、在实验原理1中&#xff0c;绘制加入5次谐波后的波形&#xff0c;根据该仿真图&#xff0c;说明为什么加入5次谐波…

【信号与系统】(十四)傅里叶变换与频域分析——周期信号的频谱及特点

文章目录 周期信号的频谱及特点1 周期信号的频谱2 单边谱和双边谱的关系3 周期信号频谱的特点4 周期信号的功率 周期信号的频谱及特点 频谱——信号的一种新的表示方法 1 周期信号的频谱 频谱&#xff1a;周期信号分解后&#xff0c;各分量的幅度和相位对于频率的变化&#x…

信号频谱和傅氏变换

信号频谱和傅氏变换基本思想&#xff1a; 把一个复杂信号分解成许多简单的正弦信号的叠加,这些正弦信号的频率是已知的&#xff0c;相应的振幅和相位则可由原始信号确定。 周期信号都可以表示成谐波关系的正弦信号的加权和&#xff0c;非周期信号都可以用正弦信号的加权积分来…

基于FFT的信号频谱分析

设计要求 用MATLAB产生正弦波及白噪声信号,并显示各自时域波形图。进行FFT变换,显示各自频谱图。做出两种种信号的均方根图谱,功率图谱,以及对数方均根图谱。用IFFT傅里叶反变换恢复信号,并显示时域波形图 正弦波的信号频谱分析 正弦波源代码 clear all clc %*************…

近代数字信号处理实验-DFT分析信号的频谱

一、实验目的 &#xff08;1&#xff09;掌握利用DFT近似计算不同类型信号频谱的原理和方法。 &#xff08;2&#xff09;理解误差产生的原因及减小误差的方法。 &#xff08;3&#xff09;培养学生自主学习能力&#xff0c;以及发现问题、分析问题和解决问题的能力。 二、…

Matlab中利用FFT实现信号频谱搬移

目录 Matlab中利用FFT实现信号频谱搬移只有实部的频谱搬移只有虚部的频谱搬移复函数下的频谱搬移 Matlab中利用FFT实现信号频谱搬移 在fft的理论中&#xff0c;fft的频移特性表示为&#xff1a; 也就是说&#xff0c;要想对信号f&#xff08;t&#xff09;实现频域的频谱搬移&…

转|周期矩形脉冲信号频谱及特点

周期矩形波信号及其频谱 如图所示信号为脉冲宽度τ&#xff0c;脉冲幅度A&#xff0c;周期为T的周期矩形脉冲信号。 上述周期矩形脉冲信号的傅里叶系数推导可参考占空比任意方波的傅里叶级数展开最终化简可得到下面的表达式。 由此式可得知&#xff0c;该信号频谱谱线大致按照…

用Matlab求余弦信号的频谱

如果你是电子信息类专业的学生&#xff0c;一定对频谱这个词听过无数次了&#xff0c;当然求频谱的方法之一就是可以采取快速傅里叶的方法&#xff0c;今天来给大家介绍一种用Matlab对余弦信号求频谱的实际操作。 第一步&#xff1a;构建原始余弦信号 Matlab代码如下&#xf…

2、信号与频谱

2.1、概述 信号传输的实质&#xff1a;信息传输的过程就是信号变换和处理的过程。如何观察信息传输过程中信号发生了什么变化&#xff1f; 一种方法是在时域 观察信号波形的变化&#xff0c;另一种方法是在频域观察信号频谱的变化。最常见的基本信号&#xff1a;正弦信号。 2…