参考 :

http://air.ghost.io/recording-to-an-audio-file-using-html5-and-js/ (html5 基础)

https://github.com/muaz-khan/RecordRTC

https://github.com/webpack-contrib/worker-loader

https://github.com/webpack-contrib/file-loader

https://github.com/muaz-khan/RecordRTC/issues/31 (wav 太大的解决方案)

https://github.com/muaz-khan/Ffmpeg.js/blob/master/wav-to-ogg.html#L209 ( ftmpeg wav to ogg 压缩方案 )

http://audior.ec/blog/recording-mp3-using-only-html5-and-javascript-recordmp3-js/ (wav to mp3 压缩方案, 超小, 声音也差.., 可以使用 lamejs 比较新)

使用插件

npm install recordrtc
npm install --save-dev file-loader
npm install --save-dev worker-loader

要使用 file,worker loading 需要在 tsconfig.app.json 加上 "node"
  "compilerOptions": {"types": [
"node"
]
},

  import * as RecordRTC from 'recordrtc';
 
startRecord() {
navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {
let recordRTC = RecordRTC(stream, {
type: 'audio',
recorderType: RecordRTC.StereoAudioRecorder,
disableLogs: true
//leftChannel: true,
//numberOfAudioChannels: 1 // or leftChannel:true
});
recordRTC.startRecording();
this.recordRTC = recordRTC;
this.stream = stream;
}).catch(() => {
console.log('user no allow');
});
}

通过 html5 的 navigator.mediaDevices.getUserMedia 获取用户的 permission, 然后就可以获取到声音了

通过 RecordRTC 来做录制. 如果是要 to mp3 的话, 可以选择单声道 (不过我试过 to mp3 效果声音效果不好, 所以最好用了 .ogg)

 stop() {
let recordRTC = this.recordRTC;
recordRTC.stopRecording(() => {
// 关闭 html5 navigator.mediaDevices.getUserMedia
var track = this.stream.getTracks()[0]; // 0 是因为我们只有一个 track, 是可以 track 2 个的, 声音和影像
track.stop(); // ff 可以 skip 掉 fileReader, 直接拿 recordRTC.blob new File 也可以, 因为 ff 返回的就是 ogg 了
// 下面是针对 chrome 返回的是 wav, 很大, 所以使用 ffmpeg 压缩去 ogg
let fileReader = new FileReader(); fileReader.onload = () => {
recordRTC.clearRecordedData(); // reader 读出来后就可以释放 recordRTC 了. //压缩是很慢的, 所以要另开一个线程
var WorkerConstructor = require("worker-loader!./worker2.js");
var worker = new WorkerConstructor(); worker.onmessage = (e) => {
var result = e.data[0];
// edge 不可以跑哦, 只有 chrome and ff ok
var blob = new File([result.data], 'whatever.ogg', {
type: 'audio/ogg'
}); let formData = new FormData();
formData.append('uploadFile', blob, 'whatever.ogg'); // 上传
this.http.post('/api/uploadFile', formData).subscribe(() => {
console.log('done');
}); // 做成 audio
let audio = new Audio();
audio.controls = true;
let url = window.URL.createObjectURL(blob); audio.src = url;
let recordMp3Container = document.getElementById('recordmp3-container');
recordMp3Container.appendChild(audio);
audio.play(); // 关闭 worker
worker.terminate();
}; worker.postMessage(fileReader.result);
}; fileReader.readAsArrayBuffer(recordRTC.blob);
});
}

worker2.js

let url = require("file-loader!./ffmpeg_asm.js");  

self.importScripts(url);

let print = () => { };
self.onmessage = (event) => {
let blob = event.data;
let result = ffmpeg_run({
print: print,
printErr: print,
files: [
{
data: new Uint8Array(blob),
name: "whatever.wav"
}
],
arguments: '-i whatever.wav -c:a vorbis -b:a 4800k -strict experimental output.ogg'.split(' ')
});
self.postMessage(result);
};

关键就是调用了 ffmpeg_run

https://archive.org/download/ffmpeg_asm/ffmpeg_asm.js

这个转换器 18mb 非常大哦. 不过只要下载一次, 所以 ok 啦.

wav to mp3

步骤和上面一下, 使用单声道.

然后 worker 用下面这个

//var url = require("file-loader!./lame.all.js");
var url = require("file-loader!lamejs/lame.all.js"); self.importScripts(url); self.onmessage = function (e) {
let stream = e.data.stream;
let streamArray = new Int16Array(stream);
streamArray = streamArray.slice(50); //去掉一开始的杂音
let buffer = [];
let mp3encoder = new lamejs.Mp3Encoder(1, 44100, 128); let mp3Data = mp3encoder.encodeBuffer(streamArray);
buffer.push(mp3Data);
mp3Data = mp3encoder.flush(); //获取最后一个 part
buffer.push(mp3Data);
let blob = new Blob(buffer, { type: 'audio/mp3' });
var workerResult = {
stream: blob
};
self.postMessage(workerResult);
}

调用 lamejs 去压缩.

最后想说的是... RecordRTC 这个 plugin 是使用原生 MediaRecorder 接口来实现的

MediaRecorder 只有 chrome and firefox 支持.  chrome 输出的格式是 webm, firefox 则是 ogg, RecordRTC 做了些修改输出的是 wav

以上 3 种格式 ios safari 都不支持, 它只支持 mp3... 伤感...

recordRTC

import { HttpClient } from '@angular/common/http';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import * as RecordRTC from 'recordrtc'; declare let MediaRecorder: any; function invokeSaveAsDialog(file, fileName) {
if (!file) {
throw 'Blob object is required.';
} if (!file.type) {
try {
file.type = 'video/webm';
} catch (e) { }
} var fileExtension = (file.type || 'video/webm').split('/')[1]; if (fileName && fileName.indexOf('.') !== -1) {
var splitted = fileName.split('.');
fileName = splitted[0];
fileExtension = splitted[1];
} var fileFullName = (fileName || (Math.round(Math.random() * 9999999999) + 888888888)) + '.' + fileExtension; if (typeof navigator.msSaveOrOpenBlob !== 'undefined') {
return navigator.msSaveOrOpenBlob(file, fileFullName);
} else if (typeof navigator.msSaveBlob !== 'undefined') {
return navigator.msSaveBlob(file, fileFullName);
} var hyperlink = document.createElement('a');
hyperlink.href = URL.createObjectURL(file);
hyperlink.download = fileFullName; (document.body || document.documentElement).appendChild(hyperlink); if (typeof hyperlink.click === 'function') {
hyperlink.click();
} else {
hyperlink.target = '_blank';
hyperlink.dispatchEvent(new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true
}));
} URL.revokeObjectURL(hyperlink.href);
}
let mp3 = true; @Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent { constructor(
private http: HttpClient
) { }
title = 'app'; recordRTC: any; stop() {
let recordRTC = this.recordRTC;
recordRTC.stopRecording(() => {
// 关闭 html5 navigator.mediaDevices.getUserMedia
var track = this.stream.getTracks()[0]; // 0 是因为我们只有一个 track, 是可以 track 2 个的, 声音和影像
track.stop(); // ff 可以 skip 掉 fileReader, 直接拿 recordRTC.blob new File 也可以, 因为 ff 返回的就是 ogg 了
// 下面是针对 chrome 返回的是 wav, 很大, 所以使用 ffmpeg 压缩去 ogg
let fileReader = new FileReader(); fileReader.onload = () => {
recordRTC.clearRecordedData(); // reader 读出来后就可以释放 recordRTC 了. if (mp3) {
//压缩是很慢的, 所以要另开一个线程
var WorkerConstructor = require("worker-loader!./worker.js");
var worker = new WorkerConstructor();
}
else {
//压缩是很慢的, 所以要另开一个线程
var WorkerConstructor = require("worker-loader!./worker2.js");
var worker = new WorkerConstructor();
} worker.onmessage = (e) => { if (mp3) {
console.log(e);
var result = e.data.stream;
invokeSaveAsDialog(result, 'output.mp3');
// recordRTC.save('dadad');
}
else {
var result = e.data[0];
// edge 不可以跑哦, 只有 chrome and ff ok
var blob = new File([result.data], 'output.ogg', {
type: 'audio/ogg'
}); let formData = new FormData();
formData.append('uploadFile', blob, 'output.ogg'); // 上传
// this.http.post('/api/uploadFile', formData).subscribe(() => {
// console.log('done');
// }); invokeSaveAsDialog(blob, 'output.ogg');
// 做成 audio
let audio = new Audio();
audio.controls = true;
let url = window.URL.createObjectURL(blob); audio.src = url;
let recordMp3Container = document.getElementById('recordmp3-container');
recordMp3Container.appendChild(audio);
audio.play(); // 关闭 worker
worker.terminate();
}
}; worker.postMessage(fileReader.result);
}; fileReader.readAsArrayBuffer(recordRTC.blob);
});
} stream: any go() { navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => { let obj = {
type: 'audio',
recorderType: RecordRTC.StereoAudioRecorder,
disableLogs: true,
// numberOfAudioChannels: 1 // or leftChannel:true
}
if(mp3) obj['leftChannel'] = true; let recordRTC = RecordRTC(stream,obj);
recordRTC.startRecording();
this.recordRTC = recordRTC;
this.stream = stream;
}).catch(() => {
console.log('user no allow');
});
}
}

mp3

//var url = require("file-loader!./lame.all.js");
var url = require("file-loader!lamejs/lame.all.js"); self.importScripts(url); self.onmessage = function (e) {
let stream = e.data;
let streamArray = new Int16Array(stream);
streamArray = streamArray.slice(50); //去掉一开始的杂音
let buffer = [];
let mp3encoder = new lamejs.Mp3Encoder(1, 44100, 128); let mp3Data = mp3encoder.encodeBuffer(streamArray);
buffer.push(mp3Data);
mp3Data = mp3encoder.flush(); //获取最后一个 part
buffer.push(mp3Data);
let blob = new Blob(buffer, { type: 'audio/mp3' });
var workerResult = {
stream: blob
};
self.postMessage(workerResult);
}

ogg

let url = require("file-loader!./ffmpeg_asm.js");

self.importScripts(url);

let print = (text) => {
console.log(text);
};
self.onmessage = (event) => {
console.log('worker e ', event);
console.log('worker e.data ', event.data);
let blob = event.data;
let result = ffmpeg_run({
print: print,
printErr: print,
files: [
{
data: new Uint8Array(blob),
name: "whatever.wav"
}
],
arguments: '-i whatever.wav -c:a vorbis -b:a 4800k -strict experimental output.ogg'.split(' ')
});
self.postMessage(result);
};

.

												

录音 voice record的更多相关文章

  1. python 全栈开发,Day123(图灵机器人,web录音实现自动化交互问答)

    昨日内容回顾 . 百度ai开放平台 . AipSpeech技术,语言合成,语言识别 . Nlp技术,短文本相似度 . 实现一个简单的问答机器人 . 语言识别 ffmpeg (目前所有音乐,视频领域,这 ...

  2. 图灵机器人,web录音实现自动化交互问答

    一.图灵机器人 介绍 图灵机器人 是以语义技术为核心驱动力的人工智能公司,致力于“让机器理解世界”,产品服务包括机器人开放平台.机器人OS和场景方案. 官方地址为: http://www.tuling ...

  3. ios录音

    #import "ViewController.h" #import <AVFoundation/AVFoundation.h> @interface ViewCont ...

  4. iOS开发-解决AVAudioRecorder录音文件无法保存的问题

    我们在开发iOS客户端APP时,有时候会用到录音的功能,一般会使 AVAudioRecorder 这个类.如下面这样: @interface MyViewController : UIViewCont ...

  5. ios开发——实用技术篇Swift篇&录音

    录音 // MARK: - 录音 /*----- 录音 ------*/ var recorder:AVAudioRecorder? //录音器 var player:AVAudioPlayer? / ...

  6. python 全栈开发,Day129(玩具开机提示语,为多个玩具发送点播,聊天界面,app录音,app与服务器端文件传输,简单的对话)

    一.玩具开机提示语 先下载github代码,下面的操作,都是基于这个版本来的! https://github.com/987334176/Intelligent_toy/archive/v1.2.zi ...

  7. CoreAudio实现录音播音和扬声器听筒模式的切换

    本例子使用Core Audio实现类似于微信的音频对讲功能,可以录音和播放并且实现了听筒模式和扬声器模式的切换.录音主要使用AVAudioRecorder类来实现录音功能,播放则使用AVAudioPl ...

  8. IOS 录音(AVAudioRecorder)

    #import "HMViewController.h" #import <AVFoundation/AVFoundation.h> @interface HMView ...

  9. js实现浏览器用户信息收集

    前言 这是一个通过html5,javascript用于收集用户通过上网泄漏的各种信息,包括地理位置,IP地址,照片,语音,浏览器版本等信息.结合大数据,可实现广告定向投放,用户追踪,用户行为分析,用户 ...

随机推荐

  1. STL相关问题

    写set容器遇到以下问题: C:\Users\admin\Desktop\未命名2.cpp In function 'int main()': 67 98 C:\Users\admin\Desktop ...

  2. SQL server无法连接上服务器的相关问题

    安装MySql以后,SQL server突然就连接不上服务器了,问了老师,说是啥进程关闭了,都打开了也没搞好,都准备重装了,结果看到度妈上面的一篇文献,原来是SQL  server MSSQLSERV ...

  3. FireMonkey 源码学习(5)

    (5)UpdateCharRec 该函数的源码分析如下: procedure TTextLayoutNG.UpdateCharRec(const ACanvas: TCanvas; NeedBitma ...

  4. TFS 报错解决方案:tf400324

    同事的解决方案没报这个问题将他的C:\Windows\System32\drivers\etc\hosts文件覆盖自己的文件,主要备份自己的文件不行了替换掉

  5. 闪存中的NorFlash、NandFlash及eMMC三者的区别【转】

    本文转载自:https://blog.csdn.net/Blazar/article/details/77843655 快闪存储器(英语:Flash Memory),是一种电子式可清除程序化只读存储器 ...

  6. POJ 2387 Til the Cows Come Home 【最短路SPFA】

    Til the Cows Come Home Description Bessie is out in the field and wants to get back to the barn to g ...

  7. word如何替换行首?

    在替换窗口, 要使用通配符 要使用 替换中的 分组, 高级替换 表示行首的符号, 使用 (<*) 表示 单词开始的位置, 使用 <, 表示单词结束的位置, 使用 > 替换的示例:

  8. extjs的使用笔记

    2006年jack slocum斯洛克姆 基于yui写的扩展前端框架(就是由一些前端可视化组件如表单,树, 表格,等组成的frameset或者叫做 ui engine),叫yui-ext, 后来成熟后 ...

  9. Pig项目&Spring Boot&Spring Cloud学习

    1.Spring条件加载原理(@Conditional,@ConditionalOnXXX注解) https://fangjian0423.github.io/2017/05/16/springboo ...

  10. 关不掉.vbs

    创建: 1.在桌面新建一个 关不掉.txt 文本文档 2.打开输入一下内容 do msgbox"信不信你关不掉我" msgbox"哈哈,你相信了吧" msgbo ...