录音 voice record
参考 :
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"
]
},
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的更多相关文章
- python 全栈开发,Day123(图灵机器人,web录音实现自动化交互问答)
昨日内容回顾 . 百度ai开放平台 . AipSpeech技术,语言合成,语言识别 . Nlp技术,短文本相似度 . 实现一个简单的问答机器人 . 语言识别 ffmpeg (目前所有音乐,视频领域,这 ...
- 图灵机器人,web录音实现自动化交互问答
一.图灵机器人 介绍 图灵机器人 是以语义技术为核心驱动力的人工智能公司,致力于“让机器理解世界”,产品服务包括机器人开放平台.机器人OS和场景方案. 官方地址为: http://www.tuling ...
- ios录音
#import "ViewController.h" #import <AVFoundation/AVFoundation.h> @interface ViewCont ...
- iOS开发-解决AVAudioRecorder录音文件无法保存的问题
我们在开发iOS客户端APP时,有时候会用到录音的功能,一般会使 AVAudioRecorder 这个类.如下面这样: @interface MyViewController : UIViewCont ...
- ios开发——实用技术篇Swift篇&录音
录音 // MARK: - 录音 /*----- 录音 ------*/ var recorder:AVAudioRecorder? //录音器 var player:AVAudioPlayer? / ...
- python 全栈开发,Day129(玩具开机提示语,为多个玩具发送点播,聊天界面,app录音,app与服务器端文件传输,简单的对话)
一.玩具开机提示语 先下载github代码,下面的操作,都是基于这个版本来的! https://github.com/987334176/Intelligent_toy/archive/v1.2.zi ...
- CoreAudio实现录音播音和扬声器听筒模式的切换
本例子使用Core Audio实现类似于微信的音频对讲功能,可以录音和播放并且实现了听筒模式和扬声器模式的切换.录音主要使用AVAudioRecorder类来实现录音功能,播放则使用AVAudioPl ...
- IOS 录音(AVAudioRecorder)
#import "HMViewController.h" #import <AVFoundation/AVFoundation.h> @interface HMView ...
- js实现浏览器用户信息收集
前言 这是一个通过html5,javascript用于收集用户通过上网泄漏的各种信息,包括地理位置,IP地址,照片,语音,浏览器版本等信息.结合大数据,可实现广告定向投放,用户追踪,用户行为分析,用户 ...
随机推荐
- truncate table很慢之enq: RO - fast object reuse和local write wait等待分析
使用ASSM表空间(默认模式)的时候,在dss系统中确实会出现truncate很慢的现象,但是他不会100%重现,得看概率.通过sql trace(对任何v$sysstat看起来资源消耗很低的情况,都 ...
- oracle 11g禁用和强制direct path read
一般在混合型环境中,大表在进行全表扫描或者走并行的时候一般会出现direct path read等待事件,如果在OLTP或者纯粹的DSS环境中,出现大量的direct path read直接路径读取, ...
- jar中META-INF
一直记得META-INF中只有在直接启动jar可执行文件时需要在manifest中配置启动类,最近看dubbo的配置,发现dubbo的配置都丢在META-INF下,特地搜索了下,官网对于META-IN ...
- Python 操作 mysql数据库的一个小小的基础案例,小白新手,以备后用~~
model.py 中的代码 # Create your models here. # 书和作者一对多 class Author(models.Model): name = models.CharFie ...
- NOIP 2016 天天爱跑步 (luogu 1600 & uoj 261) - 线段树
题目传送门 传送点I 传送点II 题目大意 (此题目不需要大意,我认为它已经很简洁了) 显然线段树合并(我也不知道哪来这么多显然) 考虑将每条路径拆成两条路径 s -> lca 和 t -> ...
- topcoder srm 335 div1
problem1 link 直接模拟即可. import java.util.*; import java.math.*; import static java.lang.Math.*; public ...
- 列表与if语句的结合
# 1.判断一个数是否是水仙花数, 水仙花数是一个三位数, 三位数的每一位的三次方的和还等于这个数. \ # 那这个数就是一个水仙花数, 例如: 153 = 1**3 + 5**3 + 3**3 # ...
- python&django 常见问题及解决方法
0.python-dev安装(ubuntu) apt-get install python-dev 1.Open(filename,mode) 报错实例: f = open('d:\Users\16 ...
- secureCRT的自动化脚本如何编写?
以等待字符串eth0的出现,出现后或者20秒后脚本执行reboot命令的脚本为例,示例如下: #$language = "VBScript" #$interface = " ...
- Hunter’s Apprentice 【判断多边形边界曲线顺逆时针】
问题 H: Hunter's Apprentice 时间限制: 1 Sec 内存限制: 128 MB 提交: 353 解决: 39 [提交] [状态] [命题人:admin] 题目描述 When ...