音頻錄制小妙招-自制工具-借助瀏覽器錄一段單聲道16000采樣率wav格式音頻

先看效果

1、打開頁面

2、點擊開始錄音,彈出權限提示,點擊“僅這次訪問時允許”

3、錄完后,點擊停止

4、文件自動下載到默認目錄

上代碼

?js 部分

document.addEventListener('DOMContentLoaded', () => {const startBtn = document.getElementById('startBtn');const stopBtn = document.getElementById('stopBtn');const audioPlayback = document.getElementById('audioPlayback');let mediaRecorder;let audioChunks = [];startBtn.addEventListener('click', async () => {try {// Request access to the microphoneconst stream = await navigator.mediaDevices.getUserMedia({ audio: { channelCount: 1, sampleRate: 16000 } });if (!stream) {throw new Error('No media stream received.');}// Create a MediaRecorder instance with specific settingsmediaRecorder = new MediaRecorder(stream, {mimeType: 'audio/webm'});mediaRecorder.ondataavailable = event => {audioChunks.push(event.data);};mediaRecorder.onstop = () => {const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });convertWebmToWav(audioBlob);audioChunks = [];};mediaRecorder.start();startBtn.disabled = true;stopBtn.disabled = false;} catch (err) {console.error('Error accessing microphone:', err);alert('Error accessing microphone: ' + err.message);}});stopBtn.addEventListener('click', () => {if (mediaRecorder && mediaRecorder.state !== 'inactive') {mediaRecorder.stop();}startBtn.disabled = false;stopBtn.disabled = true;});function convertWebmToWav(webmBlob) {const reader = new FileReader();reader.onloadend = () => {const arrayBuffer = reader.result;const audioContext = new AudioContext();audioContext.decodeAudioData(arrayBuffer, audioBuffer => {const samples = audioBuffer.getChannelData(0);const buffer = createWav(samples, audioBuffer.sampleRate);const blob = new Blob([buffer], { type: 'audio/wav' });const audioUrl = URL.createObjectURL(blob);audioPlayback.src = audioUrl;// Save or download the blob as a WAV fileconst link = document.createElement('a');link.href = audioUrl;link.download = 'recorded_audio.wav';document.body.appendChild(link);link.click();document.body.removeChild(link);}, error => {console.error('Error decoding audio data:', error);});};reader.readAsArrayBuffer(webmBlob);}function createWav(samples, sampleRate) {const buffer = new ArrayBuffer(44 + samples.length * 2);const view = new DataView(buffer);// RIFF identifierwriteString(view, 0, 'RIFF');// file length minus RIFF identifier length and file description lengthview.setUint32(4, 36 + samples.length * 2, true);// RIFF typewriteString(view, 8, 'WAVE');// format chunk identifierwriteString(view, 12, 'fmt ');// format chunk lengthview.setUint32(16, 16, true);// sample format (raw)view.setUint16(20, 1, true);// channel countview.setUint16(22, 1, true);// sample rateview.setUint32(24, sampleRate, true);// byte rate (sample rate * block align)view.setUint32(28, sampleRate * 2, true);// block align (channel count * bytes per sample)view.setUint16(32, 2, true);// bits per sampleview.setUint16(34, 16, true);// data chunk identifierwriteString(view, 36, 'data');// data chunk lengthview.setUint32(40, samples.length * 2, true);floatTo16BitPCM(view, 44, samples);return buffer;}function floatTo16BitPCM(output, offset, input) {for (let i = 0; i < input.length; i++, offset += 2) {const s = Math.max(-1, Math.min(1, input[i]));output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);}}function writeString(view, offset, string) {for (let i = 0; i < string.length; i++) {view.setUint8(offset + i, string.charCodeAt(i));}}
});

html部分

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Audio Recorder</title>
</head>
<body><h1>Audio Recorder</h1><button id="startBtn">Start Recording</button><button id="stopBtn" disabled>Stop Recording</button><br><br><audio id="audioPlayback" controls></audio><script src="recorder.js"></script>
</body>
</html>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/898552.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/898552.shtml
英文地址,請注明出處:http://en.pswp.cn/news/898552.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mysql-經典實戰案例(10):如何用PT-Archiver完成大表的自動歸檔

真實痛點&#xff1a;電商訂單表存儲優化場景 現狀分析 某電商平臺訂單表&#xff08;order_info&#xff09;每月新增500萬條記錄 主庫&#xff1a;高頻讀寫&#xff0c;SSD存儲&#xff08;空間告急&#xff09;歷史庫&#xff1a;HDD存儲&#xff0c;只讀查詢 優化目標 …

CUDA編程面試高頻30題

1. 什么是CUDA&#xff1f;它與GPU的關系是什么&#xff1f; 答: CUDA&#xff08;Compute Unified Device Architecture&#xff09;是由NVIDIA開發的一種并行計算平臺和應用程序接口模型。它允許開發者利用NVIDIA GPU進行通用計算任務&#xff0c;而不僅僅是圖形渲染。CUDA提…

數學建模 繪圖 圖表 可視化(3)

文章目錄 前言二維散點圖系列坐標圖數據分布特征&#xff0c;Q-Q、P-P圖分類圖一般的曲線圖峰巒圖總結參考資料 前言 承接上期 數學建模 繪圖 圖表 可視化&#xff08;1&#xff09;的總體描述&#xff0c;這期我們繼續跟隨《Python 數據可視化之美 專業圖表繪制指南》步伐來學…

【數據結構】棧(Stack)、隊列(Queue)、雙端隊列(Deque) —— 有碼有圖有真相

目錄 棧和隊列 1. 棧&#xff08;Stack&#xff09; 1.1 概念 1.2 棧的使用&#xff08;原始方法&#xff09; 1.3 棧的模擬實現 【小結】 2. 棧的應用場景 1、改變元素的序列 2、將遞歸轉化為循環 3、逆波蘭表達式求值 4、括號匹配 5、出棧入棧次序匹配 6、最小棧…

【強化學習】Reward Model(獎勵模型)詳細介紹

&#x1f4e2;本篇文章是博主強化學習&#xff08;RL&#xff09;領域學習時&#xff0c;用于個人學習、研究或者欣賞使用&#xff0c;并基于博主對相關等領域的一些理解而記錄的學習摘錄和筆記&#xff0c;若有不當和侵權之處&#xff0c;指出后將會立即改正&#xff0c;還望諒…

國家雪亮工程政策護航,互聯網監控管理平臺鑄就安全防線

在當今社會&#xff0c;公共安全是國家發展的重要基石&#xff0c;也是人民安居樂業的基本保障。為了打造更高水平的平安中國&#xff0c;國家推出了意義深遠的雪亮工程&#xff0c;并出臺了一系列相關政策&#xff0c;為公共安全事業保駕護航。而互聯網監控管理平臺作為雪亮工…

藍橋杯 第十天 2019國賽第4題 矩陣計數

最后一個用例超時了&#xff0c;還是記錄一下 import java.util.Scanner;public class Main {static int visited[][];static int count 0;static int n,m;public static void main(String[]args) {Scanner scan new Scanner(System.in);n scan.nextInt();//2m scan.nextIn…

coding ability 展開第五幕(二分查找算法)超詳細!!!!

. . 文章目錄 前言二分查找搜索插入的位置思路 x的平方根思路 山脈數組的峰頂索引思路 尋找旋轉排序數組中的最小值思路 總結 前言 本專欄上篇博客已經把滑動指針收尾啦 現在還是想到核心——一段連續的區間&#xff0c;有時候加上哈希表用起來很爽 今天我們來學習新的算法知識…

BEVFormer報錯(預測場景與真值場景的sample_token不匹配)

在運行test.py時報錯&#xff1a; BEVFormer/projects/mmdet3d_plugin/datasets/nuscnes_eval.py&#xff1a; init()函數報錯 assert set(self.pred_boxes.sample_tokens) set(self.gt_boxes.sample_tokens), \"Samples in split doesnt match samples in predictions…

網絡安全威脅與防護措施(下)

8. 惡意軟件&#xff08;Malware&#xff09; **惡意軟件&#xff08;Malware&#xff0c;Malicious Software&#xff09;**是指旨在通過破壞、破壞或未經授權訪問計算機系統、網絡或設備的程序或代碼。惡意軟件通常用于竊取敏感信息、破壞系統、竊取資源、干擾正常操作&…

基于springboot的母嬰商城系統(018)

摘 要 現代經濟快節奏發展以及不斷完善升級的信息化技術&#xff0c;讓傳統數據信息的管理升級為軟件存儲&#xff0c;歸納&#xff0c;集中處理數據信息的管理方式。本母嬰商城系統就是在這樣的大環境下誕生&#xff0c;其可以幫助管理者在短時間內處理完畢龐大的數據信息&am…

shell 腳本搭建apache

#!/bin/bash # Set Apache version to install ## author: yuan# 檢查外網連接 echo "檢查外網連接..." ping www.baidu.com -c 3 > /dev/null 2>&1 if [ $? -eq 0 ]; thenecho "外網通訊良好&#xff01;" elseecho "網絡連接失敗&#x…

使用OBS進行webRTC推流參考

參考騰訊云官方文檔&#xff1a; 云直播 OBS WebRTC 推流_騰訊云 說明非常詳細&#xff0c;分為通過WHIP和OBS插件的形式進行推流。 注意&#xff1a;通過OBS插件的形式進行推流需要使用較低的版本&#xff0c;文檔里有說明&#xff0c;需要仔細閱讀。

Excel 小黑第18套

對應大貓18 .txt 文本文件&#xff0c;點數據 -現有鏈接 -瀏覽更多 &#xff08;文件類型&#xff1a;可以點開文件看是什么分隔的&#xff09; 雙擊修改工作表名稱 為表格添加序號&#xff1a;在數字那修改格式為文本&#xff0c;輸入第一個序號樣式&#xff08;如001&#…

快速入手-基于Django的mysql配置(三)

Django開發操作數據庫更簡單&#xff0c;內部提供了ORM框架。比如mysql&#xff0c;舊版本用pymysql對比較多&#xff0c;新的版本采用mysqlclient。 1、安裝mysql模塊 pip install mysqlclient 2、Django的ORM主要做了兩件事 &#xff08;1&#xff09;CRUD數據庫中的表&am…

【總結篇】java多線程,新建線程有幾種寫法,以及每種寫法的優劣勢

java多線程 新建線程有幾種寫法,以及每種寫法的優劣勢 [1/5]java多線程 新建線程有幾種寫法–繼承Thread類以及他的優劣勢[2/5]java多線程-新建線程有幾種寫法–實現Runnable接口以及他的優劣勢[3/5]java多線程 新建線程有幾種寫法–實現Callable接口結合FutureTask使用以及他的…

基于YOLOv8與ByteTrack的車輛行人多目標檢測與追蹤系統

作者主頁&#xff1a;編程千紙鶴 作者簡介&#xff1a;Java領域優質創作者、CSDN博客專家 、CSDN內容合伙人、掘金特邀作者、阿里云博客專家、51CTO特邀作者、多年架構師設計經驗、多年校企合作經驗&#xff0c;被多個學校常年聘為校外企業導師&#xff0c;指導學生畢業設計并參…

【芯片驗證】面試題·對深度為60的數組進行復雜約束的技巧

朋友發給我的芯片驗證筆試題,覺得很有意思,和大家分享一下。 面試題目 class A中一個長度為60的隨機數組rand int arr[60],如何寫約束使得: 1.每個元素的值都在(0,100]之間,且互不相等; 2.最少有三個元素滿足勾股數要求,比如數組中包含3,4,5三個點; 請以解約束最快…

springmvc中使用interceptor攔截

HandlerInterceptor 是Spring MVC中用于在請求處理之前、之后以及完成之后執行邏輯的接口。它與Servlet的Filter類似&#xff0c;但更加靈活&#xff0c;因為它可以訪問Spring的上下文和模型數據。HandlerInterceptor 常用于日志記錄、權限驗證、性能監控等場景。 ### **1. 創…

【網絡協議】基于UDP的可靠協議:KCP

TCP是為流量設計的&#xff08;每秒內可以傳輸多少KB的數據&#xff09;&#xff0c;講究的是充分利用帶寬。而 KCP是為流速設計的&#xff08;單個數據包從一端發送到一端需要多少時間&#xff09;&#xff0c;以10%-20%帶寬浪費的代價換取了比 TCP快30%-40%的傳輸速度。TCP信…