【electron6】浏览器实时播放PCM数据

news2024/9/20 22:43:57

pcm介绍:PCM(Puls Code Modulation)全称脉码调制录音,PCM录音就是将声音的模拟信号表示成0,1标识的数字信号,未经任何编码和压缩处理,所以可以认为PCM是未经压缩的音频原始格式。PCM格式文件中不包含头部信息,播放器无法知道采样率,声道数,采样位数,音频数据大小等信息,导致无法播放。

需求:我需要在websoket中接收实时的pcm音频流原始数据:16位,16k,单通道(意思就是:pcm 的参数采样率16000,采样位数16,声道数1)

重要!:千万不要去运用什么所谓的插件,因为它会使你绕很大一圈的弯路,实时播放的pcm浏览器是支持的,使用插件很可能还会被迫读什么源码,也很容易将你带偏,再多的播放插件底层大部分也是基于AudioContext去开发的。

首先是拿音频文件试,但是却不了解mp3和wav的区别,就首选拿了mp3这是我的第一个深坑,因为mp3经过多层的处理压缩,已经距离原始的文件很远了,通过ajax拿回来的arraybuffer是可以直接塞进去CreateBufferSource.buffer中就能直接播放,原因就是decodeAdioData就直接能处理接口返回的arraybuffer数据

mp3示例:

useEffect(() => {
      axios.request({
        url: require('@/assets/wholeWorld.mp3'), // 假如这是我们从后端请求回来的音乐文件
        responseType: 'arraybuffer', // 必须需要这个
        method: 'get'
      }).then(res => {
        // 创建AudioBufferSourceNode
        const arrayBuffer = res.data
        const context = new AudioContext()
        const source = context.createBufferSource();
        context.decodeAudioData(arrayBuffer).then(audioBuffer => {
          // 设置buffer属性
        source.buffer = audioBuffer;
        // 连接到音频上下文并播放
        source.connect(context.destination);
        })
        source.start(0);
      })
  }, [])

我处理wav的音频去播放,也是可以的使用decodeAudioData去进行播放

wav音频播放示例:

useEffect(() => {
      axios.request({
        url: require('@/assets/sample.wav'), // 假如这是我们从后端请求回来的音乐文件
        responseType: 'arraybuffer', // 必须需要这个
        method: 'get'
      }).then(res => {
        // 创建AudioBufferSourceNode
        const arrayBuffer = res.data
        const context = new AudioContext()
        const source = context.createBufferSource();
        context.decodeAudioData(arrayBuffer).then(audioBuffer => {
          // 设置buffer属性
        source.buffer = audioBuffer;
        // 连接到音频上下文并播放
        source.connect(context.destination);
        })
        source.start(0);
      })
  }, [])

但是都不支持pcm文件,所以我最开始的思路是通过获取到的pcm去处理成wav的文件一样,去搜了很多资料,都说wav的文件比pcm只是多了44字节文件头,我没从深度验证,但是我通过加字节文件头去进行pcm的播放,因为decodeAudioData可以运行其他处理过的音频文件,尽管加了字节文件头是不能解决根本问题的,这段路我绕了很大一个圈。
mp3文件和wav文件的区别示例:
在这里插入图片描述
mp3和wav的区别说明:
在这里插入图片描述

其实浏览器是可以直接播放pcm数据的,无论是文件,还是socket返回来的原始数据,这过程涉及了Uint8转换Uint16,Uint16转成Float32,了解decodeAudioData和getChannelData究竟处理什么问题等知识。
首先,找一个pcm文件,进行播放调试,pcm的文件能播放成功,那socket就不是问题!

PCM播放代码示例:

(仅播放出声音的调试,自行调整代码规范)

// 解析PCM数据到AudioBuffer
function decodePCM(arrayBuffer: ArrayBufferLike,sampleBits: number, channelCount: number, sampleRate: number,audioContext: any) {
  return new Promise((resolve, reject) => {
      const dataView = new DataView(arrayBuffer);
      const length = (arrayBuffer.byteLength / (sampleBits / 8) / channelCount);
      const buffer = audioContext.createBuffer(channelCount, length, sampleRate);
      let offset = 0;

      for (let channel = 0; channel < channelCount; channel++) {
          const channelBuffer = buffer.getChannelData(channel);
          for (let i = 0; i < length; i++) {
              const sample = dataView.getInt16(offset, true); // 假设PCM数据是16位有符号整数
              channelBuffer[i] = sample / 32768; // 标准化到-1到1的范围
              offset += 2; // 16位 = 2字节
          }
      }

      resolve(buffer);
  });
}
let sourceNode: any = null;
  useEffect(() => {
    // 加载音频文件
    axios.request({
      method: 'get',
      url: require('@/assets/recorder.pcm'),
      responseType: "arraybuffer",
    }).then(res => {
      const arraybuffer = res.data
      
      const audioContext = new window.AudioContext();
      decodePCM(arraybuffer, 16, 1, 16000, audioContext).then(buffer => {
        sourceNode = audioContext.createBufferSource();
        sourceNode.buffer = buffer;
        sourceNode.connect(audioContext.destination);
        sourceNode.start(); // 开始播放
    }).catch(error => {
        console.error('Error decoding PCM:', error);
    });
    })
  }, [])

注:
当声音有杂音,一直是一个杂音就说明,数据错了
当声音没有声音,数据很可能都是0
当声音隐隐有正常,但是杂音很重,一定是需要它:getChannelData和DataView
后端从TCP给我实时的pcm是压缩Uint8Array,前端将Uint8Array的数据解码为Uint16Array,然后合并Uint16Array的所有音频数据,还需要将Uint16Array通过DataView处理成AudioContext可播放的Float32Array,所以不了解AudioCotext API是很难解决这些问题的,更何况仅仅是播放的功能,我后面还要处理更多复杂的应用场景,持续更新实时播放pcm的处理应用场景。

最终在和蔼可亲的同事帮助和自己不辞辛苦的研究下搞出来了,感谢我的同事。

值得参考:
张鑫旭:https://www.zhangxinxu.com/wordpress/2023/10/js-audio-audiobuffer-concat-merge/
MDN:https://developer.mozilla.org/zh-CN/docs/Web/API/BaseAudioContext/createBuffer

推荐工具:
MEIDAINFO:https://mediaarea.net/MediaInfoOnline

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1936363.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FPGA文档阅读

FPGA的文档没有相应的基础还真不容易看懂&#xff0c;下面是B站上对FPGA文档的解读(本文非对文档解读&#xff0c;只是为个人记录第三期&#xff1a;CycloneIV E最小系统板设计&#xff08;一&#xff09;从Datasheet上获取FPGA的基本参数_哔哩哔哩_bilibili 电源部份 核心电…

elasticsearch, kibana, 6.8.18 版本下的创建索引,指定timestamp,java CRUD,maven版本等

ELK 这一套的版本更迭很快&#xff0c; 而且es常有不兼容的东西出现&#xff0c; 经常是搜一篇文章&#xff0c;看似能用&#xff0c;拿到我这边就不能用了。 很是烦恼。 我这边的ELK版本目前是 6.8.18&#xff0c;这次的操作记录一下。 &#xff08;涉密内容略有删改&#xf…

SQL语句——DDL数据定义语言

1.sql语言不区分大小写 2._&#xff08;下划线&#xff09;进行名字的分割&#xff0c;不适用驼峰命名 3.; 语句sql结尾处加一个;来表示结束 4.一般关键词建议用大写 5.所有名称不能用中文 1.创建数据库 CREATE DATABASE [IF NOT EXISTS] 库名 -- 库 #创建库 #create databa…

计算机网络序章

计算机网络学习什么&#xff1f; 下列举例由用户使用计算机角度去理解 首先&#xff0c;计算机网络是通过路由等方式去获取我们希望的数据用户可以在APP中去进行方便的操作去获取数据。每个应用都有自己的端口去确定每次来的数据是否是自己需要的数据应该应该传到哪里&#x…

COD论文笔记 Deep Gradient Learning for Efficient Camouflaged 2022

动机 这篇论文的动机在于解决伪装目标检测(COD)中的一个关键问题&#xff1a;在复杂背景下&#xff0c;伪装目标与背景的边界模糊&#xff0c;使得检测变得极其困难。现有的方法&#xff0c;如基于边界或不确定性的模型&#xff0c;通常仅响应于伪装目标的稀疏边缘&#xff0c…

oceanbase架构、功能模块、数据存储、特性、sql流转层等概念详解

一、架构图 OceanBase 数据库采用无共享&#xff08;Shared-Nothing&#xff09;分布式集群架构&#xff0c;各个节点之间完全对等&#xff0c;每个节点都有自己的 SQL 引擎、存储引擎、事务引擎&#xff0c;运行在普通 PC 服务器组成的集群之上&#xff0c;具备高可扩展性、高…

澎湃算力 玩转AI 华为昇腾AI开发板——香橙派OriengePi AiPro边缘计算案例评测

澎湃算力 玩转AI 华为昇腾AI开发板 香橙派OriengePi AiPro 边缘计算案例评测 人工智能&#xff08;AI&#xff09;技术正以前所未有的速度改变着我们的生活、工作乃至整个社会的面貌。作为推动这一变革的关键力量&#xff0c;边缘计算与AI技术的深度融合正成为行业发展的新趋势…

秒懂C++之类与对象(下)

目录 一.static成员 测试&#xff1a; 二.explicit关键字 三.友元&#xff08;少用&#xff09; 友元函数&#xff1a; 友元类&#xff1a; 四.内部类&#xff08;少用&#xff09; 五.&#xff08;扩展&#xff09;编译器的优化 一.static成员 测试&#xff1a; 实现一…

【分布式事务】怎么解决分布式场景下数据一致性问题

分布式事务的由来 拿充值订单举个栗子吧&#xff0c;假设&#xff1a;原本订单模块和账户模块是放在一起的&#xff0c;现在需要做服务拆分&#xff0c;拆分成订单服务&#xff0c;账户余额服务。原本收到充值回调后&#xff0c;可以将修改订单状态和扣减余额放在一个mysql事务…

邮件安全篇:邮件传输加密(SSL/TLS or STATRTTLS)

1. 前言 使用过邮件客户端的同学一定见过下面这张图。这是客户端账号配置界面&#xff0c;里面有SSL、STARTTLS选项。刚接触邮件客户端的同学肯定会有这些疑问&#xff1a;什么是SSL&#xff1f;什么是STARTTLS&#xff1f;两者有什么区别&#xff1f;具体该如何选择呢&#x…

首批通过 | 百度通过中国信通院H5端人脸识别安全能力评估工作

2024年5月&#xff0c;中国信息通信研究院人工智能研究所依托中国人工智能产业发展联盟安全治理委员会&#xff08;AIIA&#xff09;、“可信人脸应用守护计划”及多家企业代表共同开展《H5端人脸识别线上身份认证安全能力要求及评估方法》的编制工作&#xff0c;并基于该方法开…

创新驱动的力量:探索Web3在技术发展中的作用

随着科技的不断进步和创新&#xff0c;Web3作为新一代互联网技术范式&#xff0c;正在以其去中心化、安全、透明和可编程的特性&#xff0c;深刻影响着全球技术发展的方向和速度。本文将深入探讨Web3技术的核心概念、关键特征以及其在技术创新中的重要作用&#xff0c;展示其在…

【Android】Fragment的静态动态创建以及两种创建方式的生命周期

参考&#xff1a; 33.3-Fragment的创建-静态创建2_哔哩哔哩_bilibili Fragment的创建_从现有代码创建foutran-CSDN博客 【Android】Fragment的基本用法、Fragment和活动间的通信、Fragment的生命周期、动态加载布局的技巧_android fragment-CSDN博客 文章目录 Fragment的静态创…

贝锐蒲公英远程运维方案:即装即用、无需专线,断网也可远程维护

目前&#xff0c;公路、隧道、桥梁、航道&#xff0c;甚至是施工现场和工业生产环境等&#xff0c;都采用了实时监测方案。 通过部署各类传感器和摄像头等设备&#xff0c;现场视频画面和控制单元&#xff08;如PLC、工控机等&#xff09;数据可以实时回传&#xff0c;用于集中…

0711springNews新闻系统管理 实现多级评论

0611springmvc新闻系统管理-CSDN博客 0711springNews新闻系统管理项目包 实现多级评论-CSDN博客 数据库字段 需要添加父节点id&#xff0c;通过该字段实现父评论和子评论的关联关系。 对象属性 实现链表&#xff0c;通过一个父评论可以找到它对应的所有子孙评论。 业务层 实现…

linux集群架构--web服务器--nginx检查模块/算法/rewrite知识补充

web集群-负载均衡 轮询算法 &#xff08;1&#xff09;概述 决定负载均衡如何把请求分发给后端节点&#xff0c;这种分发的方式就是轮询算法 &#xff08;2&#xff09;轮询算法 面试题&#xff1a;说说常见nginx轮询算法 rr,wrr,ip_hash,lc算法&#xff08;最小连接数&…

CH03_布局

第3章&#xff1a;布局 本章目标 理解布局的原则理解布局的过程理解布局的容器掌握各类布局容器的运用 理解 WPF 中的布局 WPF 布局原则 ​ WPF 窗口只能包含单个元素。为在WPF 窗口中放置多个元素并创建更贴近实用的用户男面&#xff0c;需要在窗口上放置一个容器&#x…

基于 Three.js 的 3D 模型加载优化

作者&#xff1a;来自 vivo 互联网前端团队- Su Ning 作为一个3D的项目&#xff0c;从用户打开页面到最终模型的渲染需要经过多个流程&#xff0c;加载的时间也会比普通的H5项目要更长一些&#xff0c;从而造成大量的用户流失。为了提升首屏加载的转化率&#xff0c;需要尽可能…

怎么关闭 Windows 安全中心,手动关闭 Windows Defender 教程

Windows 安全中心&#xff08;也称为 Windows Defender Security Center&#xff09;是微软 Windows 操作系统内置的安全管理工具&#xff0c;用于监控和控制病毒防护、防火墙、应用和浏览器保护等安全功能。然而&#xff0c;在某些情况下&#xff0c;用户可能需要关闭 Windows…

通义千问AI模型对接飞书机器人-集成飞书机器人(2-2)

接上一篇 通义千问AI模型对接飞书机器人-模型配置&#xff08;2-1&#xff09; 1、通过飞书机器人对接ai的在线接口 参考文档&#xff1a;发送 HTTP 请求 1.1 创建飞书应用 创建流程 配置http请求 http请求地址上一篇百炼平台配置的应用地址 1.2 企业自建应用对接AI 添加应用…