当前位置: 首页 > news >正文

关于前端与APP录音相关的笔记

文章目录

  • 一、前言
  • 二、内容组成
    • 1、权限获取
    • 2、针对设备兼容
    • 3、内容类型转换
    • 4、传输存储
  • 三、拓展内容
      • 自动播放部分

一、前言

主要针对前端适配录音能力的简要记录,针对默认的wav及其可能需要转换到特定的mp3之类格式以适配需求的问题。(这类通常是兼容tts或客服语音备份)
这里纠结点主要会是在 ios/android设备的兼容类型转换的问题

二、内容组成

主要围绕下面几个重要组成部分
①权限获取
②针对设备兼容
③内容类型转换
④传输存储

1、权限获取

这里首先需要确定的一点是,获取录音权限,除了通常的 localhost 之外,仅有证书存在的domain/ip 浏览器才会允许获取权限。(哪怕是自定义证书也是可以的)

针对app端部分内容嵌入适配

这里主要是考虑到app的基础配置,基于前者的情况下(截止操作时间2023.8.1)

Android:

其实根据通用的方式,就是动态设置,哪个webview使用设置哪个。

<!-- 所需权限列表 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
//伪代码部分AudioWebView.setWebChromeClient(new WebChromeClient() {@Overridepublic void onProgressChanged(WebView view, int newProgress) {super.onProgressChanged(view, newProgress);}@Overridepublic void onPermissionRequest(PermissionRequest request) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){//直接无脑同意即可request.grant(request.getResources());}}});
//这里是基础链接
AudioWebView.loadUrl("{{baseUrl}}");

IOS

这里补充一点,即便webview已经允许你调用录音,某种情况下,其实也存在某些版本每次调用前询问,所以最好做好预案
Tips: ios中叫做 WKWebView

//伪代码部分
import AVFoundation// 请求录音权限
func requestRecordPermission() {AVAudioSession.sharedInstance().requestRecordPermission { granted inif granted {// 用户授权了录音权限,可以加载WebView了self.loadWebView()} else {// 用户拒绝了录音权限,处理相应逻辑// 例如给出提示或者禁用录音功能}}
}// 加载WebView
func loadWebView() {// 在此处加载WebView,调用录音的网页功能
}

2、针对设备兼容

这里的兼容主要是针对设备部分的区分吧。
首先声明 iosAndroid 的区别
android : 在对应的webview中当且通常仅需首次获取权限即可。(高版本会有选项永久还是单次)
ios: 通常在 wkwebvie 中,每次都需要获取录音权限(这个是兼容低版本ios考虑)

建议解决方案:

android

针对安卓的内容可以采取默认仅请求一次,然后利用本地缓存来保存标记。
当标记失效,则可以通过其他方式让其重新授权即可

ios

针对苹果的内容,不可排除新版本已经解决这个问题,但是出于兼容考虑
还是预先做好 调用权限 的处理,避免需要的时候不存在权限。

3、内容类型转换

这里主要是考虑到可能存在的调用 asr接口 ,会需要适配不同的音频类型。
可以简单参考 语音厂商参数对比

默认来说,浏览器部分,我们通常采用 window.AudioContext || window.webkitAudioContext 的模式来获取录音内容。

如果需要切换类型,我们可以采用 lame.js 来转换所需的MP3类型 。

Tip: 其他类型,目前暂未需要,如有建议,感谢提供

4、传输存储

整个过程中,其实最好使用blob格式传输,附加文件类型
示例 :let blob = new Blob(mp3Data, { type: "audio/mp3" });

例如websock中传递的时候,实际上大都需要我们重新加载一下格式,如果直接blob可能存在无法识别的问题

// 伪代码
// 其中 res 为传递过程中的blob内容
if (suffix == ".mp3" || suffix == ".wav") {let newBlob = new Blob([res.blob], {type: "audio/" + types,});console.log("image types:" + types);console.log("and the new blob is:" + newBlob);let originSrc = (window.URL || window.webkitURL).createObjectURL(newBlob);attachmentDom ='<audio controls="controls" src="' +originSrc +'"></audio>';suffixHandler = true;}

三、拓展内容

自动播放部分

这里其实android 很容易实现,直接通过controls即可控制auto 自动播放
主要是 ios 部分, 由于ios的一些机制问题,不能直接去自动播放可以参考如下的方式

其实就是模拟用户交互来达成


/*** 初始化录音*/
function forceSafariPlayAudio() {if (trys == 0) {audio.src = 'https://www.runoob.com/try/demo_source/horse.mp3'audio.load(); // iOS 9   还需要额外的 load 一下, 否则直接 play 无效audio.play(); // iOS 7/8 仅需要 play 一下trys = 1audioType = 1}}$(function () {function log(info) {console.log(info);}audio = document.getElementById('bgmusic');audio.loop = falseaudio.muted = true// 可以自动播放时正确的事件顺序是// loadstart --> loadedmetadata --> loadeddata -->canplay -->play --> playing// 不能自动播放时触发的事件是// iPhone5  iOS 7.0.6 loadstart// iPhone6s iOS 9.1   loadstart -> loadedmetadata -> loadeddata -> canplayaudio.addEventListener('loadstart', function () {log('loadstart');}, false);audio.addEventListener('loadeddata', function () {log('loadeddata');}, false);audio.addEventListener('loadedmetadata', function () {log('loadedmetadata');}, false);audio.addEventListener('canplay', function () {log('canplay');}, false);audio.addEventListener('play', function () {log('play');// 当 audio 能够播放后, 移除这个事件console.log("初始化成功")window.removeEventListener('touchstart', forceSafariPlayAudio, false);}, false);audio.addEventListener('playing', function () {log('playing');}, false);audio.addEventListener('pause', function () {log('pause');}, false);audio.addEventListener('ended', function () {audioType = 0;}, false);// 由于 iOS Safari 限制不允许 audio autoplay, 必须用户主动交互(例如 click)后才能播放 audio,// 因此我们通过一个用户交互事件来主动 play 一下 audio.window.addEventListener('touchstart', forceSafariPlayAudio, false);audio.src = 'https://www.runoob.com/try/demo_source/horse.mp3'})

相关文章:

关于前端与APP录音相关的笔记

文章目录 一、前言二、内容组成1、权限获取2、针对设备兼容3、内容类型转换4、传输存储 三、拓展内容自动播放部分 一、前言 主要针对前端适配录音能力的简要记录&#xff0c;针对默认的wav及其可能需要转换到特定的mp3之类格式以适配需求的问题。&#xff08;这类通常是兼容tt…...

【Java】SpringBoot项目整合FreeMarker加快页面访问速度

文章目录 什么是FreeMarker&#xff1f;它的优点有那些&#xff1f;使用方式 什么是FreeMarker&#xff1f; Freemarker是一个模板引擎技术&#xff0c;它可以将数据和模板结合起来生成最终的输出。它是一种用于生成文本输出&#xff08;如HTML、XML、JSON等&#xff09;的通用…...

conda环境下安装opencv-python包

conda环境下安装opencv-python包 一、#查看环境 conda info --env# conda environments: # base D:\ProgramData\Anaconda3二、激活base环境 进入conda环境 conda init cmd.exe conda activate base三、根据版本号&#xff0c;下载对应的 python-opencv…...

JVM面试题--类加载器

什么是类加载器&#xff0c;类加载器有哪些 类加载子系统&#xff0c;当java源代码编译为class文件之后&#xff0c;由他将字节码装载到运行时数据区 BootStrap ClassLoader 启动类加载器或者叫做引导类加载器&#xff0c;是用c实现的&#xff0c;嵌套在jvm内部&#xff0c;…...

js怎么计算当前一周的日期

你可以使用 JavaScript 的 Date 对象来计算当前一周的日期。首先&#xff0c;你需要获取当前日期&#xff0c;然后使用 Date 对象的 getDay 方法获取当前是星期几(星期日是 0&#xff0c;星期一是 1&#xff0c;以此类推)。然后&#xff0c;你可以根据当前是星期几来计算出本周…...

【图论】差分约束

一.情景导入 x1-x0<9 ; x2-x0<14 ; x3-x0<15 ; x2-x1<10 ; x3-x2<9; 求x3-x0的最大值&#xff1b; 二.数学解法 联立式子2和5&#xff0c;可得x3-x0<23;但式子3可得x3-x0<15。所以最大值为15&#xff1b; 三.图论 但式子多了我们就不好解了&#xff0…...

13 springboot项目——准备数据和dao类

13.1 静态资源下载 https://download.csdn.net/download/no996yes885/88151513 13.2 静态资源位置 css样式文件放在static的css目录下&#xff1b;static的img下放图片&#xff1b;template目录下放其余的html文件。 13.3 创建两个实体类 导入依赖&#xff1a;lombok <!…...

Java 基础进阶总结(一)反射机制学习总结

文章目录 一、初识反射机制1.1 反射机制概述1.2 反射机制概念1.3 Java反射机制提供的功能1.4 反射机制的优点和缺点 二、反射机制相关的 API 一、初识反射机制 1.1 反射机制概述 JAVA 语言是一门静态语言&#xff0c;对象的各种信息在程序运行时便已经确认下来了&#xff0c;内…...

ERROR: transport error 202: gethostbyname: unknown host报错解决方案

Java 9 syntax for remote debugger: -agentlib:jdwptransportdt_socket,servery,suspendn,address*:5005Java 8 不适用 *:port&#xff0c;应该使用: -agentlib:jdwptransportdt_socket,servery,suspendn,address5005参考 https://stackoverflow.com/questions/50344957/ja…...

PyTorch高级教程:自定义模型、数据加载及设备间数据移动

在深入理解了PyTorch的核心组件之后&#xff0c;我们将进一步学习一些高级主题&#xff0c;包括如何自定义模型、加载自定义数据集&#xff0c;以及如何在设备&#xff08;例如CPU和GPU&#xff09;之间移动数据。 一、自定义模型 虽然PyTorch提供了许多预构建的模型层&#…...

JavaEE——SpringMVC中的常用注解

目录 1、RestController &#xff08;1&#xff09;、Controller &#xff08;2&#xff09;、ResponseBody 2、RequestMappping &#xff08;1&#xff09;、定义 &#xff08;2&#xff09;、使用 【1】、修饰方法 【2】、修饰类 【3】、指定方法类型 【4】、简化版…...

【严重】Metabase 基于H2引擎的远程代码执行漏洞

漏洞描述 Metabase 是一个开源的数据分析和可视化工具。 由于 CVE-2023-38646 的补丁(从H2 JDBC连接字符串中删除INIT脚本以防止命令注入)修复不完全&#xff0c;Metabase 仍受到命令注入的影响。攻击者可使用 H2 作为数据库引擎&#xff0c;通过 /api/setup/validate 端点发…...

0基础学习VR全景平台篇 第75篇:多现场

多现场是指将多台设备的直播画面整合到一个直播活动链接里面&#xff0c;让用户自行选择切换要看哪个直播画面的功能。既可以是同一个活动的不同角度直播&#xff0c;也可以是异地的直播。多现场不需要导播台&#xff0c;并且可以同时支持平面直播和VR直播的混合切换。多现场仅…...

html:去除input/textarea标签的拼写检查

默认情况下&#xff0c;textarea 会启动拼写和语法检查&#xff0c;表现效果就是单词拼写错误会出现红色下划线提示 <textarea></textarea>效果 有时&#xff0c;我们并不需要拼写检查&#xff0c;可以通过配置属性spellcheck"false" 去除拼写和语法检…...

自然语言处理从入门到应用——LangChain:提示(Prompts)-[提示模板:创建自定义提示模板和含有Few-Shot示例的提示模板]

分类目录&#xff1a;《自然语言处理从入门到应用》总目录 创建自定义提示模板 假设我们希望LLM根据函数名称生成该函数的英文语言解释。为了实现这个任务&#xff0c;我们将创建一个自定义的提示模板&#xff0c;以函数名称作为输入&#xff0c;并格式化提示模板以提供函数的…...

d3dx9_30.dll如何修复,分享几种一键修复方法

d3dx9_30.dll是DirectX 的一个动态链接库文件&#xff0c;它包含了一些用于图形和游戏的函数和资源。在了解d3dx9_30.dll的解决方法和丢失原因之前&#xff0c;我们先来了解一下DirectX。DirectX是一套由微软开发的多媒体和游戏编程接口&#xff08;API&#xff09;集合。它提供…...

6.8 稀疏数组

6.8 稀疏数组 稀疏数组是一种数据结构&#xff0c;在程序中数据结构的思想&#xff0c;是非常重要的。例如 需求&#xff1a;编写五子棋游戏中&#xff0c;有存盘退出和续上盘的功能。分析问题&#xff1a;因为该二维数组的很多值是默认值0&#xff0c;因此记录了很多没有意义…...

ROS版本的ORB-SLAM3用RealSense D455相机实时运行测试

配置环境 1. C11 检查G版本&#xff0c;查看是否支持C11 一般g版本大于4.7即可 g -v 2. Pangolon 地址&#xff1a;https://github.com/stevenlovegrove/Pangolin 先安装OpenGL&#xff0c;Glew ### 编译orb-slam3发现pangolin编译错误排查的环境问题 sudo apt install p…...

Vue中对对象内容调用的Demo

目录 1.对象作为数据&#xff1a; 2.对象数组 在Vue中&#xff0c;你可以通过对象的键来调用对象中的各个部分的内容。下面是一些使用Vue调用对象各部分内容的示例&#xff1a; 1.对象作为数据&#xff1a; 如果你在Vue实例的数据中有一个对象&#xff0c;你可以使用点语法来…...

语音识别 — 特征提取 MFCC 和 PLP

一、说明 语音识别是一种技术&#xff0c;通过计算机和软件系统&#xff0c;将人们的口头语言转换为计算机可读的文本或命令。它使用语音信号处理算法来识别和理解人类语言&#xff0c;并将其转换为计算机可处理的格式。语音识别技术被广泛应用于许多领域&#xff0c;如语音助手…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...