这篇文章主要为大家详细介绍了射流研究…实现录音上传功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本文实例为大家分享了射流研究…代码实现录音上传,供大家参考,具体内容如下
1.html页面
2.记录器。射流研究…内容
3 .烧瓶写法
1.html页面
!文档类型超文本标记语言
html lang=en
头
meta charset=UTF-8
标题id=标题/标题
/头
身体
音频id=播放器自动播放控件/音频
p
button onclick=start_reco()开始录音/按钮
/p
p
按钮onclick= ai _ reco() style= background-color:玉米花蓝发送语音指令/按钮
/p
/body
脚本类型= application/JavaScript src=/static/jquery-3。3 .1 .量滴js /脚本
脚本类型= text/JavaScript src=/static/recorder。js /脚本
脚本类型=应用程序/javascript
var reco=null
var audio _ context=新音频上下文();//音频内容对象
领航员。getuser media=(navigator。getuser media | |
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
领航员。msgetusermedia);//兼容其他浏览器
领航员。getuser media({ audio:true },create_stream,function (err) {
console.log(错误)
});
函数创建流(用户媒体){
var流输入=音频上下文。createmediastreamsource(user _ media);
reco=新记录器(stream _ input);
}
函数start_reco() {
reco。record();
}
函数ai_reco() {
reco。stop();
reco。导出wav(函数(wav _ file){
控制台。log(wav _ file);
var FormData=new FormData();//表单表单{key:value}
formdata.append(audio ,wav _ file);//表单输入类型=文件
$.ajax({
网址:"/receive _ audio ",
类型: post ,
processData: false,
contentType: false,
数据:formdata,
数据类型: json ,
成功:函数(数据){
console.log(数据);
文档。getelementbyid(“player”).src=/get _ audio/数据。文件名;
}
})
});
reco。clear();
}
/脚本
/html
2.记录器。射流研究…内容
直接复制保存即可
(函数{ if(type of exports=== object 类型的模块!==未定义){ module。exports=f()} else if(类型定义=== function 定义。amd){ define([],f)} else { var g;如果(窗口类型!== undefined ){ g=window } else if(类型为全局!== undefined ){ g=global } else if(type of self!== undefined ){ g=self } else { g=this } g . Recorder=f()} })(function(){ var define,module,exportsreturn(函数e(t,n,r){函数s(o,u){if(!n[o]){if(!t[o]){ var a=type of require== function require;如果(!ua)返回一个(o,0);如果返回i(o,0);var f=新错误(找不到模块‘o’);throw f.code=MODULE_NOT_FOUND ,f } var l=n[o]={ exports:{ } };t[o][0].call(l.exports,function(e){ var n=t[o][1][e];返回s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports } var I=需求类型== function requirefor(var o=0;或。长度;o)s(r[o]);return s })({ 1:[函数(要求、模块、导出){
使用严格的;
module.exports=require( ./记录器)。记录器;
},{./recorder:2}],2:[函数(要求、模块、导出){
使用严格的;
var _createClass=(function () {
功能定义属性(目标、道具){
for(var I=0;我道具。长度;i ) {
var descriptor=props[I];描述符。enumerable=描述符。可枚举| | falsedescriptor . configurable=true if(descriptor中的 value )描述符。可写=真;Object.defineProperty(target,descriptor.key,descriptor);
}
}返回函数(构造函数、protoProps、staticProps) {
if(proto props)定义属性(构造函数。原型,proto道具);if(静态属性)定义属性(构造函数,静态道具);返回构造函数;
};
})();
Object.defineProperty(导出, __esModule ,{
值:真
});
出口。记录器=未定义;
var _ inline worker=require( inline-worker );
var _ inline worker 2=_ interopRequireDefault(_ inline worker);
function _ interopRequireDefault(obj){
返回对象对象__esModule?目标默认值:obj };
}
function _classCallCheck(实例,构造函数){
如果(!(构造函数的实例实例)){
抛出新类型错误(“不能将类作为函数调用");
}
}
定义变量记录器=出口。记录器=(function () {
函数记录器(源,cfg) {
var _ this=this
_classCallCheck(this,Recorder);
this.config={
巴佛伦:4096,
numChannels: 2,
mimeType: audio_pcm/wav
};
this.recording=false
this.callbacks={
获取缓冲区:[],
exportWAV: []
};
Object.assign(this.config,CFG);
这个。上下文=源.上下文
这个。node=(这个。语境。createscriptprocessor | |这个。语境。创建JavaScript节点).调用(this.context,this.config.bufferLen,this.config.numChannels,this。配置。numchannels);
这个。节点。onaudioprocess=函数(e){
如果(!_this .录音)返回;
var buffer=[];
对于(var通道=0;频道_这个。配置。通道数;频道){
缓冲。按下(例如输入缓冲区。getchanneldata(channel));
}
_this.worker.postMessage({
命令:"记录",
缓冲:缓冲
});
};
来源。连接(这个。节点);
这个。节点。连接(这个。语境。目的地);//这应该没有必要
var self={ };
这个。worker=new _ inline worker 2。默认(function(){
var recLength=0,
recBuffers=[],
采样率=未定义,
numChannels=未定义
self.onmessage=function (e) {
开关(数据命令){
案例“初始化”:
初始化数据。config);
打破;
案例"记录":
记录(数据。缓冲);
打破;
案例" exportWAV ":
导出wav(电子数据。类型);
打破;
案例"获取缓冲区":
get buffer();
打破;
案例"清除":
clear();
打破;
}
};
函数初始化(配置){
sampleRate=config.sampleRate
numChannels=config。numChannels
初始化缓冲区();
}
函数记录(输入缓冲区){
对于(var通道=0;通道数;频道){
记录缓冲区[通道]。push(输入缓冲区[通道]);
}
recLength=inputBuffer[0].长度;
}
函数exportWAV(类型){
var buffers=[];
对于(var通道=0;通道数;频道){
缓冲器。push(合并缓冲区(记录缓冲区[通道],重新长度));
}
var交错=未定义;
if (numChannels===2) {
interleaved=interleave(buffers[0],buffers[1]);
}否则{
交错=缓冲区[0];
}
var dataview=encodeWAV(交错);
var audio Blob=new Blob([dataview],{ type:type });
自我。post message({ command: export wav ,data:audio blob });
}
函数getBuffer() {
var buffers=[];
对于(var通道=0;通道数;频道){
缓冲器。push(合并缓冲区(记录缓冲区[通道],重新长度));
}
自我。post message({ command: get buffer ,data:buffers });
}
函数clear() {
recLength=0;
记录缓冲区=[];
初始化缓冲区();
}
函数initBuffers() {
对于(var通道=0;通道数;频道){
rec buffers[channel]=[];
}
}
函数mergeBuffers(recBuffers,recLength) {
var result=new float 32 array(recLength);
var offset=0;
for(var I=0;i recBuffers.lengthi ) {
result.set(recBuffers[i],offset);
offset=recBuffers[i].长度;
}
返回结果;
}
函数交错(输入,输入){
变量长度=inputl。长度输入。长度;
var result=new Float32Array(长度);
定义变量指数=0,
输入索引=0;
而(索引长度){
result[index]=inputL[inputIndex];
结果[索引]=inputR[输入索引];
inputIndex
}
返回结果;
}
函数浮动到16位PCM(输出、偏移、输入){
for(var I=0;我输入。长度;I,offset=2) {
var s=Math.max(-1,Math.min(1,input[I]);
output.setInt16(offset,s 0?s *0x8000 : s *0x7FFF,true);
}
}
函数writeString(视图,偏移量,字符串){
for(var I=0;我字符串。长度;i ) {
view.setUint8(偏移量I,字符串。charcodeat(I));
}
}
函数encodeWAV(示例){
var buffer=新数组缓冲区(44个样本。长度* 2);
var view=新数据视图(缓冲区);
/* RIFF标识符*/
writeString(视图,0,“RIFF”);
/* RIFF块长度*/
view.setUint32(4,36 samples.length * 2,true);
/* RIFF类型*/
writeString(view,8, WAVE );
/*格式块标识符*/
writeString(view,12, fmt );
/*格式块长度*/
view.setUint32(16,16,true);
/*样本格式(原始)*/
view.setUint16(20,1,true);
/*频道计数*/
view.setUint16(22,numChannels,true);
/*采样速率*/
view.setUint32(24,sampleRate,true);
/*字节速率(采样速率*块对齐)*/
view.setUint32(28,sampleRate * 4,true);
/*块对齐(通道数*每个样本的字节数)*/
view.setUint16(32,numChannels * 2,true);
/*每个样本的位数*/
view.setUint16(34,16,true);
/*数据块标识符*/
writeString(view,36, data );
/*数据块长度*/
view.setUint32(40,samples.length * 2,true);
浮动到16位PCM(视图,44,示例);
返回视图;
}
},自我);
this.worker.postMessage({
命令:" init ",
配置:{
采样率:这个。语境。抽样率
numChannels:这个。配置。数字频道
}
});
这个。工人。on消息=函数(e){
var CB=_ this。回调[电子数据。命令].pop();
if (typeof cb==function) {
CB(电子数据。数据);
}
};
}
_createClass(记录器,[{
键:"记录",
值:函数记录(){
this.recording=true
}
}, {
按键:"停止",
值:函数stop() {
this.recording=false
}
}, {
按键:"清除",
值:函数clear() {
这个。工人。postmessage({ command: clear });
}
}, {
关键字:"获取缓冲区",
值:函数获取缓冲区(cb) {
CB=CB | |这个。配置。回调;
如果(!cb)抛出新错误("未设置回调");
这个。复试。获取缓冲区。推(CB);
这个。工人。postmessage({ command: getBuffer });
}
}, {
关键字:" exportWAV ",
值:函数exportWAV(cb,mimeType) {
mime type=mime type | | this。配置。mime类型;
CB=CB | |这个。配置。回调;
如果(!cb)抛出新错误("未设置回调");
这个。复试。导出wav。推(CB);
this.worker.postMessage({
命令: exportWAV ,
类型:mimeType
});
}
}], [{
键:"强制下载",
值:函数强制下载(blob,文件名){
var url=(window .URL || window.webkitURL).createObjectURL(blob);
var link=窗口。文档。createelement( a );
link.href=url
链接。download=filename | | 输出。wav ;
var click=文档。创建事件(“事件”);
click.initEvent(click ,true,true);
link.dispatchEvent(点击);
}
}]);
返回记录器;
})();
exports.default=记录器
},{inline-worker:3}],3:[function(require,module,exports){
使用严格的;
module.exports=require( ./inline-worker );
},{./inline-worker:4}],4:[函数(要求、模块、导出){
(功能(全局){
使用严格的;
var _ create class=(function(){ function define properties(target,props){ for(var key in props){ var prop=props[key];prop.configurable=trueif(prop。值)道具。可写=真;} Object.defineProperties(目标、道具);}返回函数(构造函数,protoProps,静态props){ if(proto props)定义属性(构造函数。原型,proto道具);if(静态属性)定义属性(构造函数,静态道具);返回构造函数;};})();
var _classCallCheck=function(实例,构造函数){如果(!(构造函数的实例instance)){抛出新类型错误(不能将类作为函数调用);} };
var WORKER_ENABLED=!(global===global.window global .统一资源定位器全局. Blob全局。工人);
var InlineWorker=(function () {
函数InlineWorker(func,self) {
var _ this=this
_classCallCheck(this,inline worker);
if (WORKER_ENABLED) {
var functionBody=func.toString().修剪()。match(/^functions*w*s*([ws,]*)s*{([ww]*?)}$/)[1];
var url=global .URL.createObjectURL(新全局. Blob([functionBody],{ type: text/JavaScript });
返回新的全局。工人(网址);
}
这个自我=自我
这个。自我。postmessage=函数(数据){
setTimeout(function () {
_这个。on message({ data:data });
}, 0);
};
setTimeout(function () {
func。打电话(自己);
}, 0);
}
_createClass(InlineWorker,{
后期消息:{
值:函数邮件(数据){
var _ this=this
setTimeout(function () {
_这个。自我。on message({ data:data });
}, 0);
}
}
});
返回在线工人
})();
module.exports=InlineWorker
}).调用(这,全局类型!==未定义?全局:自我类型!==未定义?自我:窗口类型!==未定义?窗口:{})
},{}]},{},[1])(1)
});
3 .烧瓶写法
.
@app.route(/)
定义索引():
返回render_template(index.html )
@app.route(/receive_audio ,methods=[POST])
定义接收音频():
file=request.files.get(音频)
如果文件:
文件路径=OS。路径。join(BAISE _ DIR, data , %s.m4a % uuid4())
文件.保存(文件路径)
text=baidu.auido2text(filepath)
answer=tuling.chat(正文)
res=百度. text2audio(答案)
if res.get(err_no)==200:
return {code: 200, filename: res.get(filename)}
return {code: 201, msg :上传失败}
@ app。路线(/get _ audio/filename )
def获取_音频(文件名):
返回发送文件(os.path.join(白色目录,数据,文件名))
.
注意瓶启动互联网协议(互联网协议的缩写)写成127.0.0.1 其他地址射流研究…可能会报错
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。