关于前端与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、针对设备兼容
这里的兼容主要是针对设备部分的区分吧。
首先声明ios与Android的区别
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、传输存储 三、拓展内容自动播放部分 一、前言 主要针对前端适配录音能力的简要记录,针对默认的wav及其可能需要转换到特定的mp3之类格式以适配需求的问题。(这类通常是兼容tt…...
【Java】SpringBoot项目整合FreeMarker加快页面访问速度
文章目录 什么是FreeMarker?它的优点有那些?使用方式 什么是FreeMarker? Freemarker是一个模板引擎技术,它可以将数据和模板结合起来生成最终的输出。它是一种用于生成文本输出(如HTML、XML、JSON等)的通用…...
conda环境下安装opencv-python包
conda环境下安装opencv-python包 一、#查看环境 conda info --env# conda environments: # base D:\ProgramData\Anaconda3二、激活base环境 进入conda环境 conda init cmd.exe conda activate base三、根据版本号,下载对应的 python-opencv…...
JVM面试题--类加载器
什么是类加载器,类加载器有哪些 类加载子系统,当java源代码编译为class文件之后,由他将字节码装载到运行时数据区 BootStrap ClassLoader 启动类加载器或者叫做引导类加载器,是用c实现的,嵌套在jvm内部,…...
js怎么计算当前一周的日期
你可以使用 JavaScript 的 Date 对象来计算当前一周的日期。首先,你需要获取当前日期,然后使用 Date 对象的 getDay 方法获取当前是星期几(星期日是 0,星期一是 1,以此类推)。然后,你可以根据当前是星期几来计算出本周…...
【图论】差分约束
一.情景导入 x1-x0<9 ; x2-x0<14 ; x3-x0<15 ; x2-x1<10 ; x3-x2<9; 求x3-x0的最大值; 二.数学解法 联立式子2和5,可得x3-x0<23;但式子3可得x3-x0<15。所以最大值为15; 三.图论 但式子多了我们就不好解了࿰…...
13 springboot项目——准备数据和dao类
13.1 静态资源下载 https://download.csdn.net/download/no996yes885/88151513 13.2 静态资源位置 css样式文件放在static的css目录下;static的img下放图片;template目录下放其余的html文件。 13.3 创建两个实体类 导入依赖:lombok <!…...
Java 基础进阶总结(一)反射机制学习总结
文章目录 一、初识反射机制1.1 反射机制概述1.2 反射机制概念1.3 Java反射机制提供的功能1.4 反射机制的优点和缺点 二、反射机制相关的 API 一、初识反射机制 1.1 反射机制概述 JAVA 语言是一门静态语言,对象的各种信息在程序运行时便已经确认下来了,内…...
ERROR: transport error 202: gethostbyname: unknown host报错解决方案
Java 9 syntax for remote debugger: -agentlib:jdwptransportdt_socket,servery,suspendn,address*:5005Java 8 不适用 *:port,应该使用: -agentlib:jdwptransportdt_socket,servery,suspendn,address5005参考 https://stackoverflow.com/questions/50344957/ja…...
PyTorch高级教程:自定义模型、数据加载及设备间数据移动
在深入理解了PyTorch的核心组件之后,我们将进一步学习一些高级主题,包括如何自定义模型、加载自定义数据集,以及如何在设备(例如CPU和GPU)之间移动数据。 一、自定义模型 虽然PyTorch提供了许多预构建的模型层&#…...
JavaEE——SpringMVC中的常用注解
目录 1、RestController (1)、Controller (2)、ResponseBody 2、RequestMappping (1)、定义 (2)、使用 【1】、修饰方法 【2】、修饰类 【3】、指定方法类型 【4】、简化版…...
【严重】Metabase 基于H2引擎的远程代码执行漏洞
漏洞描述 Metabase 是一个开源的数据分析和可视化工具。 由于 CVE-2023-38646 的补丁(从H2 JDBC连接字符串中删除INIT脚本以防止命令注入)修复不完全,Metabase 仍受到命令注入的影响。攻击者可使用 H2 作为数据库引擎,通过 /api/setup/validate 端点发…...
0基础学习VR全景平台篇 第75篇:多现场
多现场是指将多台设备的直播画面整合到一个直播活动链接里面,让用户自行选择切换要看哪个直播画面的功能。既可以是同一个活动的不同角度直播,也可以是异地的直播。多现场不需要导播台,并且可以同时支持平面直播和VR直播的混合切换。多现场仅…...
html:去除input/textarea标签的拼写检查
默认情况下,textarea 会启动拼写和语法检查,表现效果就是单词拼写错误会出现红色下划线提示 <textarea></textarea>效果 有时,我们并不需要拼写检查,可以通过配置属性spellcheck"false" 去除拼写和语法检…...
自然语言处理从入门到应用——LangChain:提示(Prompts)-[提示模板:创建自定义提示模板和含有Few-Shot示例的提示模板]
分类目录:《自然语言处理从入门到应用》总目录 创建自定义提示模板 假设我们希望LLM根据函数名称生成该函数的英文语言解释。为了实现这个任务,我们将创建一个自定义的提示模板,以函数名称作为输入,并格式化提示模板以提供函数的…...
d3dx9_30.dll如何修复,分享几种一键修复方法
d3dx9_30.dll是DirectX 的一个动态链接库文件,它包含了一些用于图形和游戏的函数和资源。在了解d3dx9_30.dll的解决方法和丢失原因之前,我们先来了解一下DirectX。DirectX是一套由微软开发的多媒体和游戏编程接口(API)集合。它提供…...
6.8 稀疏数组
6.8 稀疏数组 稀疏数组是一种数据结构,在程序中数据结构的思想,是非常重要的。例如 需求:编写五子棋游戏中,有存盘退出和续上盘的功能。分析问题:因为该二维数组的很多值是默认值0,因此记录了很多没有意义…...
ROS版本的ORB-SLAM3用RealSense D455相机实时运行测试
配置环境 1. C11 检查G版本,查看是否支持C11 一般g版本大于4.7即可 g -v 2. Pangolon 地址:https://github.com/stevenlovegrove/Pangolin 先安装OpenGL,Glew ### 编译orb-slam3发现pangolin编译错误排查的环境问题 sudo apt install p…...
Vue中对对象内容调用的Demo
目录 1.对象作为数据: 2.对象数组 在Vue中,你可以通过对象的键来调用对象中的各个部分的内容。下面是一些使用Vue调用对象各部分内容的示例: 1.对象作为数据: 如果你在Vue实例的数据中有一个对象,你可以使用点语法来…...
语音识别 — 特征提取 MFCC 和 PLP
一、说明 语音识别是一种技术,通过计算机和软件系统,将人们的口头语言转换为计算机可读的文本或命令。它使用语音信号处理算法来识别和理解人类语言,并将其转换为计算机可处理的格式。语音识别技术被广泛应用于许多领域,如语音助手…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
