音频开发-小程序和H5

news/2024/5/21 14:08:43

微信录音

1、引入sdk

 

 

2、录音操作

 

 

 

浏览器录音

 

参考文献:前端H5实现调用麦克风,录音功能_h5 录音_Darker丨峰神的博客-CSDN博客

function record() {

    window.navigator.mediaDevices.getUserMedia({

        audio: {

            sampleRate: 44100, // 采样率

            channelCount: 2,   // 声道

            volume: 2.0        // 音量

        }

    }).then(mediaStream => {

        console.log(mediaStream);

        window.mediaStream = mediaStream

        // beginRecord(window.mediaStream);

    }).catch(err => {

        // 如果用户电脑没有麦克风设备或者用户拒绝了,或者连接出问题了等

        // 这里都会抛异常,并且通过err.name可以知道是哪种类型的错误

        console.error(err);

    });

}

function beginRecord(mediaStream) {

    let audioContext = new (window.AudioContext || window.webkitAudioContext);

    let mediaNode = audioContext.createMediaStreamSource(mediaStream);

    console.log(mediaNode)

    window.mediaNode = mediaNode

    // 这里connect之后就会自动播放了

    // mediaNode.connect(audioContext.destination); //直接把录的音直接播放出来

    // 创建一个jsNode

    let jsNode = createJSNode(audioContext);

    window.jsNode = jsNode

    // 需要连到扬声器消费掉outputBuffer,process回调才能触发

    // 并且由于不给outputBuffer设置内容,所以扬声器不会播放出声音

    jsNode.connect(audioContext.destination);

    jsNode.onaudioprocess = onAudioProcess;

    // 把mediaNode连接到jsNode

    mediaNode.connect(jsNode);

}

function createJSNode(audioContext) {

    const BUFFER_SIZE = 4096; //4096

    const INPUT_CHANNEL_COUNT = 2;

    const OUTPUT_CHANNEL_COUNT = 2;

    // createJavaScriptNode已被废弃

    let creator = audioContext.createScriptProcessor || audioContext.createJavaScriptNode;

    creator = creator.bind(audioContext);

    return creator(BUFFER_SIZE,

        INPUT_CHANNEL_COUNT, OUTPUT_CHANNEL_COUNT);

}

let leftDataList = [],

    rightDataList = [];

function onAudioProcess(event) {

    // console.log(event.inputBuffer);

    let audioBuffer = event.inputBuffer;

    let leftChannelData = audioBuffer.getChannelData(0),

        rightChannelData = audioBuffer.getChannelData(1);

    // console.log(leftChannelData, rightChannelData);

    // 需要克隆一下

    leftDataList.push(leftChannelData.slice(0));

    rightDataList.push(rightChannelData.slice(0));

}

function bofangRecord() {

    // 播放录音

    let leftData = mergeArray(leftDataList),

        rightData = mergeArray(rightDataList);

    let allData = interleaveLeftAndRight(leftData, rightData);

    let wavBuffer = createWavFile(allData);

    playRecord(wavBuffer);

}

function playRecord(arrayBuffer) {

    let blob = new Blob([new Uint8Array(arrayBuffer)]);

    let blobUrl = URL.createObjectURL(blob);

    document.querySelector('.audio-node').src = blobUrl;

}

function stopRecord() {

    // 停止录音

    window.mediaNode.disconnect();

    window.jsNode.disconnect();

    console.log("已停止录音")

    // console.log(leftDataList, rightDataList);

}

function recordClose() {

    // 停止语音

    window.mediaStream.getAudioTracks()[0].stop();

    console.log("已停止语音")

}

function mergeArray(list) {

    let length = list.length * list[0].length;

    let data = new Float32Array(length),

        offset = 0;

    for (let i = 0; i < list.length; i++) {

        data.set(list[i], offset);

        offset += list[i].length;

    }

    return data;

}

function interleaveLeftAndRight(left, right) {

    // 交叉合并左右声道的数据

    let totalLength = left.length + right.length;

    let data = new Float32Array(totalLength);

    for (let i = 0; i < left.length; i++) {

        let k = i * 2;

        data[k] = left[i];

        data[k + 1] = right[i];

    }

    return data;

}

function createWavFile(audioData) {

    const WAV_HEAD_SIZE = 44;

    let buffer = new ArrayBuffer(audioData.length * 2 + WAV_HEAD_SIZE),

        // 需要用一个view来操控buffer

        view = new DataView(buffer);

    // 写入wav头部信息

    // RIFF chunk descriptor/identifier

    writeUTFBytes(view, 0, 'RIFF');

    // RIFF chunk length

    view.setUint32(4, 44 + audioData.length * 2, true);

    // RIFF type

    writeUTFBytes(view, 8, 'WAVE');

    // format chunk identifier

    // FMT sub-chunk

    writeUTFBytes(view, 12, 'fmt ');

    // format chunk length

    view.setUint32(16, 16, true);

    // sample format (raw)

    view.setUint16(20, 1, true);

    // stereo (2 channels)

    view.setUint16(22, 2, true);

    // sample rate

    view.setUint32(24, 44100, true);

    // byte rate (sample rate * block align)

    view.setUint32(28, 44100 * 2, true);

    // block align (channel count * bytes per sample)

    view.setUint16(32, 2 * 2, true);

    // bits per sample

    view.setUint16(34, 16, true);

    // data sub-chunk

    // data chunk identifier

    writeUTFBytes(view, 36, 'data');

    // data chunk length

    view.setUint32(40, audioData.length * 2, true);

    // 写入wav头部,代码同上

    // 写入PCM数据

    let length = audioData.length;

    let index = 44;

    let volume = 1;

    for (let i = 0; i < length; i++) {

        view.setInt16(index, audioData[i] * (0x7FFF * volume), true);

        index += 2;

    }

    return buffer;

}

function writeUTFBytes(view, offset, string) {

    var lng = string.length;

    for (var i = 0; i < lng; i++) {

        view.setUint8(offset + i, string.charCodeAt(i));

    }

}

  • 播放录音

1.使用audio标签

<audio src='audio_file.mp3'></audio>

2.使用audio对象(uni-app)

3.浏览器对象(js)

 var mp3 = null;

    function audioplay(url){

        console.log("播放录音---"+url);

        if(mp3 != null){

            mp3.pause();

            mp3 = new Audio(url);

            mp3.play();

        }else{

            mp3 = new Audio(url);

            mp3.play(); //播放 mp3这个音频对象

        }

    }


http://www.mrgr.cn/p/25265826

相关文章

【软件安装】MATLAB_R2021b for mac 安装

Mac matlab_r2021b 安装 下载链接&#xff1a;百度网盘 下载链接中所有文件备用。 我所使用的电脑配置&#xff1a; Macbook Pro M1 Pro 16512 系统 macOS 13.5 安装步骤 前置准备 无此选项者&#xff0c;自行百度 “mac 任何来源”。 1 下载好「MATLAB R2021b」安装文…

Leetcode-每日一题【剑指 Offer 56 - I. 数组中数字出现的次数】

题目 一个整型数组 nums 里除两个数字之外&#xff0c;其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n)&#xff0c;空间复杂度是O(1)。 示例 1&#xff1a; 输入&#xff1a;nums [4,1,4,6]输出&#xff1a;[1,6] 或 [6,1] 示例 2&#x…

计算机网络——传输层

文章目录 **1 传输层提供的服务****1.1 传输层的功能****1.2 传输层的寻址与端口** **2 UDP协议****2.1 UDP数据报****2.2 UDP校验** **3 TCP协议****3.1 TCP协议的特点****3.2 TCP报文段****3.3 TCP连接管理****3.4 TCP可靠传输****3.5 TCP流量控制****3.6 TCP拥塞控制** 1 传…

Verilog语法学习——LV4_移位运算与乘法

LV4_移位运算与乘法 题目来源于牛客网 [牛客网在线编程_Verilog篇_Verilog快速入门 (nowcoder.com)](https://www.nowcoder.com/exam/oj?page1&tabVerilog篇&topicId301) 题目 题目描述&#xff1a; 已知d为一个8位数&#xff0c;请在每个时钟周期分别输出该数乘1/…

Spring Security 构建基于 JWT 的登录认证

一言以蔽之&#xff0c;JWT 可以携带非敏感信息&#xff0c;并具有不可篡改性。可以通过验证是否被篡改&#xff0c;以及读取信息内容&#xff0c;完成网络认证的三个问题&#xff1a;“你是谁”、“你有哪些权限”、“是不是冒充的”。 为了安全&#xff0c;使用它需要采用 …

HTTP、HTTPS协议详解

文章目录 HTTP是什么报文结构请求头部响应头部 工作原理用户点击一个URL链接后&#xff0c;浏览器和web服务器会执行什么http的版本持久连接和非持久连接无状态与有状态Cookie和Sessionhttp方法&#xff1a;get和post的区别 状态码 HTTPS是什么ssl如何搞到证书nginx中的部署 加…

2023 蓝桥杯真题B组 C/C++

https://www.dotcpp.com/oj/train/1089/ 题目 3150: 蓝桥杯2023年第十四届省赛真题-冶炼金属 题目描述 小蓝有一个神奇的炉子用于将普通金属 O 冶炼成为一种特殊金属 X。这个炉子有一个称作转换率的属性 V&#xff0c;V 是一个正整数&#xff0c;这意味着消耗 V 个普通金 属 O…

react-native 输入框 被软键盘遮挡 (KeyboardAvoidingView)

本组件用于解决一个常见的尴尬问题&#xff1a;手机上弹出的键盘常常会挡住当前的视图。本组件可以自动根据键盘的高度&#xff0c;调整自身的 height 或底部的 padding&#xff0c;以避免被遮挡。 <KeyboardAvoidingViewbehavior{Platform.OS ios ? padding : height}key…

【点云处理教程】02从 Python 中的深度图像估计点云

一、说明 这是“点云处理”教程的第二篇文章。“点云处理”教程对初学者友好&#xff0c;我们将在其中简单地介绍从数据准备到数据分割和分类的点云处理管道。在本教程中&#xff0c;我们将学习如何在不使用 Open3D 库的情况下从深度图像计算点云。我们还将展示如何优化代码以获…

【VUE】解决图片视频加载缓慢/首屏加载白屏的问题

1 问题描述 在 Vue3 项目中&#xff0c;有时候会出现图片视频加载缓慢、首屏加载白屏的问题 2 原因分析 通常是由以下原因导致的&#xff1a; 图片或视频格式不当&#xff1a;如果图片或视频格式选择不当&#xff0c;比如选择了无损压缩格式&#xff0c;可能会导致文件大小过大…

微信小程序交易体验分常见问题指引

小程序交易体验分是为保障小程序用户的交易体验&#xff0c;促进开发者向用户提供更好的服务&#xff0c;帮助开发者更好的评估自身服务水平的机制。平台将对开发者在其小程序的违规行为进行判定&#xff0c;根据违规行为的严重程度对该小程序扣减不同分值的交易体验分&#xf…

风靡朋友圈的妙鸭相机,到底用了哪些底层技术?

不知道大家近期的朋友圈有没有被和海马体、天真蓝如出一辙的AI写真刷屏&#xff01; 这些面若桃花、精致到头发丝、光影充满氛围感的写真都是一款叫“妙鸭相机”的小程序生成的&#xff01;只要9.9&#xff0c;就能体验999写真&#xff01; 虽然只要9.9&#xff0c;但生成的照片…

opencv-24 图像几何变换03-仿射-cv2.warpAffine()

什么是仿射&#xff1f; 仿射变换是指图像可以通过一系列的几何变换来实现平移、旋转等多种操作。该变换能够 保持图像的平直性和平行性。平直性是指图像经过仿射变换后&#xff0c;直线仍然是直线&#xff1b;平行性是指 图像在完成仿射变换后&#xff0c;平行线仍然是平行线。…

海康摄像头开发笔记(一):连接防爆摄像头、配置摄像头网段、设置rtsp码流、播放rtsp流、获取rtsp流、调优rtsp流播放延迟以及录像存储

文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/131679108 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结…

服务器 Docker Alist挂载到本地磁盘(Mac版)夸克网盘

1.服务器下载alist 默认有docker环境 docker pull xhofe/alist2.生成容器 -v /home/alist:/opt/alist/data 这段意思是alist中的数据映射到docker 主机的文件夹&#xff0c;/home/alist就是我主机的文件夹&#xff0c;这个文件夹必须先创建 docker run -d --restartalways…

【Python】数据分析+数据挖掘——探索Pandas中的数据筛选

1. 前言 当涉及数据处理和分析时&#xff0c;Pandas是Python编程语言中最强大、灵活且广泛使用的工具之一。Pandas提供了丰富的功能和方法&#xff0c;使得数据的选择、筛选和处理变得简单而高效。在本博客中&#xff0c;我们将重点介绍Pandas中数据筛选的关键知识点&#xff…

ChatGPT结合知识图谱构建医疗问答应用 (一) - 构建知识图谱

一、ChatGPT结合知识图谱 在本专栏的前面文章中构建 ChatGPT 本地知识库问答应用&#xff0c;都是基于词向量检索 Embedding 嵌入的方式实现的&#xff0c;在传统的问答领域中&#xff0c;一般知识源采用知识图谱来进行构建&#xff0c;但基于知识图谱的问答对于自然语言的处理…

Nginx配置WebSocket反向代理

1、WebSocket协议 ​ WebSocket协议相比较于HTTP协议成功握手后可以多次进行通讯&#xff0c;直到连接被关闭。但是WebSocket中的握手和HTTP中的握手兼容&#xff0c;它使用HTTP中的Upgrade协议头将连接从HTTP升级到WebSocket。这使得WebSocket程序可以更容易的使用现已存在的…

深度学习——LSTM解决分类问题

RNN基本介绍 概述 循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;是一种深度学习模型&#xff0c;主要用于处理序列数据&#xff0c;如文本、语音、时间序列等具有时序关系的数据。 核心思想 RNN的关键思想是引入了循环结构&#xff0c;允许…

记一次安装nvm切换node.js版本实例详解

最后效果如下&#xff1a; 背景&#xff1a;由于我以前安装过node.js&#xff0c;后续想安装nvm将node.js管理起来。 问题&#xff1a;nvm-use命令行运行成功&#xff0c;但是nvm-list显示并没有成功。 原因&#xff1a;因为安装过node.js&#xff0c;所以原先的node.js不收n…