| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- --- 模块功能:录音处理
- -- @module record
- -- @author openLuat
- -- @license MIT
- -- @copyright openLuat
- -- @release 2017.11.23
- require "log"
- require "ril"
- module(..., package.seeall)
- local FILE = '/record.amr'
- local recordType = "FILE"
- local recording,stoping,recordCb,stopCbFnc
- --- 开始录音
- -- @number seconds 录音时长,单位:秒
- -- 流录音模式下,如果想长时间录音,可以将此参数设置为0x7FFFFFFF,相当于录音2147483647秒=24855天
- -- @function[opt=nil] cbFnc 录音回调函数:
- -- 当type参数为"FILE"时,回调函数的调用形式为:
- -- cbFnc(result,size)
- -- result:录音结果,true表示成功,false或者nil表示失败
- -- size:number类型,录音文件的大小,单位是字节,在result为true时才有意义
- -- 当type参数为"STREAM"时,回调函数的调用形式为:
- -- cbFnc(result,size,tag)
- -- result:录音结果,true表示成功,false或者nil表示失败
- -- size:number类型,每次上报的录音数据流的大小,单位是字节,在result为true时才有意义
- -- tag:string类型,"STREAM"表示录音数据流通知,"END"表示录音结束
- -- @string[opt="FILE"] type 录音模式
- -- "FILE"表示文件录音模式,录音数据自动保存在文件中,录音结束后,执行一次cbFnc函数
- -- "STREAM"表示流录音模式,录音数据保存在内存中,每隔一段时间执行一次cbFnc函数去读取录音数据流,录音结束后再执行一次cbFnc函数
- -- @number[opt=1] quality 录音质量,0:一般质量,1:中等质量,2:高质量,3:无损质量
- -- @number[opt=2] rcdType 录音类型,n:1:mic(从麦克风录制),2:voice(录制语音通话,录制的流与上下行通道),3:voice_dual(在poc模式下从麦克风录制)
- -- @number[opt=3] format 录音格式,1:pcm,2:wav,3:amrnb,4:speex
- -- pcm格式:录音质量参数无效,采样率:8000,单声道,采样精度:16 bit,5秒钟录音80KB左右
- -- wav格式:录音质量参数无效,比特率:128kbps,5秒钟录音80KB左右
- -- amrnb格式:录音质量参数有效
- -- 录音质量为0时:比特率:5.15kbps,5秒钟录音3KB多
- -- 录音质量为1时:比特率:6.70kbps,5秒钟录音4KB多
- -- 录音质量为2时:比特率:7.95kbps,5秒钟录音4KB多
- -- 录音质量为3时:比特率:12.2kbps,5秒钟录音7KB多
- -- speex格式:录音质量参数无效,pcm格式128kbps后的压缩格式,5秒钟6KB左右
- -- @number[opt=nil] streamRptLen 流录音时,每次上报的字节阀值
- -- @usage
- -- 文件录音模式,录音5秒,一般质量,amrnb格式,录音结束后执行cbFnc函数:
- -- record.start(5,cbFnc)
- -- 流录音模式,录音5秒,一般质量,amrnb格式,每隔一段时间执行一次cbFnc函数,录音结束后再执行一次cbFnc函数:
- -- record.start(5,cbFnc,"STREAM")
- -- 流录音模式,录音5秒,一般质量,amrnb格式,每产生500字节的录音数据执行一次cbFnc函数,录音结束后再执行一次cbFnc函数:
- -- record.start(5,cbFnc,"STREAM",nil,nil,500)
- function start(seconds, cbFnc, type, quality, rcdType,format, streamRptLen)
- if recording or stoping or seconds <= 0 or ((type~="STREAM") and seconds>50) then
- log.error('record.start', recording, stoping, seconds)
- if cbFnc then cbFnc() end
- return
- end
- delete()
- recordType = type or "FILE"
- if type=="STREAM" then
- --param1: 录音时长 n:单位秒
- --param2: 录音质量 n:0:一般质量 1:中等质量 2:高质量 3:无损质量
- --param3:录音类型 n:1:mic 2:voice 3:voice_dual
- --param4:录音文件类型 n: 1:pcm 2:wav 3:amrnb
- audiocore.streamrecord(seconds,quality or 1,rcdType or 1,format or 3,streamRptLen)
- else
- --param1: 录音保存文件
- --param2: 录音时长 n:单位秒
- --param3: 录音质量 n:0:一般质量 1:中等质量 2:高质量 3:无损质量
- --param4:录音类型 n:1:mic 2:voice 3:voice_dual
- --param5:录音文件类型 n: 1:pcm 2:wav 3:amrnb
- audiocore.record(FILE,seconds,quality or 1,rcdType or 1,format or 3)
- end
- log.info("record.start",seconds,recordType,format or 3)
- recording = true
- recordCb = cbFnc
- return true
- end
- --- 停止录音
- -- @function[opt=nil] cbFnc 停止录音的回调函数(停止结果通过此函数通知用户),回调函数的调用形式为:
- -- cbFnc(result)
- -- result:number类型
- -- 0表示停止成功
- -- 1表示之前已经发送了停止动作,请耐心等待停止结果的回调
- -- @usage record.stop(cb)
- function stop(cbFnc)
- if not recording then
- if cbFnc then cbFnc(0) end
- return
- end
- if stoping then
- if cbFnc then cbFnc(1) end
- return
- end
- stopCbFnc = cbFnc
- log.info("record.stop")
- audiocore.stoprecord()
- stoping = true
- end
- --- 读取录音文件的完整路径
- -- @return string 录音文件的完整路径
- -- @usage filePath = record.getFilePath()
- function getFilePath()
- return FILE
- end
- --- 读取录音数据
- -- @param offset 偏移位置
- -- @param len 长度
- -- @return data 录音数据
- -- @usage data = record.getData(0, 1024)
- function getData(offset, len)
- local f = io.open(FILE, "rb")
- if not f then log.error('record.getData', 'open failed') return "" end
- if not f:seek("set", offset) then log.error('record.getData', 'seek failed') f:close() return "" end
- local data = f:read(len)
- f:close()
- log.info("record.getData", data and data:len() or 0)
- return data or ""
- end
- --- 读取录音文件总长度,录音时长
- -- @return fileSize 录音文件大小
- -- @return duration 录音时长
- -- @usage fileSize, duration = record.getSize()
- function getSize()
- local size,duration = io.fileSize(FILE),0
- if size>6 then
- duration = ((size-6)-((size-6)%1600))/1600
- end
- return size, duration
- end
- --- 删除录音
- -- @usage record.delete()
- function delete()
- log.info("record.delete")
- audiocore.deleterecord()
- os.remove(FILE)
- end
- --- 判断是否存在录音
- -- @return result true - 有录音 false - 无录音
- -- @usage result = record.exists()
- function exists()
- return io.exists(FILE)
- end
- --- 是否正在处理录音
- -- @return result true - 正在处理 false - 空闲
- -- @usage result = record.isBusy()
- function isBusy()
- return recording or stoping
- end
- rtos.on(rtos.MSG_RECORD,function(msg)
- log.info("record.MSG_RECORD",msg.record_end_ind,msg.record_error_ind,recordType)
- --文件录音,在回调时可以删除录音buf;但是流录音,一定要等buf读取完成后,再删除
- if recordType=="FILE" then audiocore.deleterecord() end
- if msg.record_error_ind then
- delete()
- if recordCb then recordCb(false,0,"END") recordCb = nil end
- recording = false
- stoping = false
- if stopCbFnc then stopCbFnc(0) stopCbFnc=nil end
- end
- if msg.record_end_ind then
- if recordCb then recordCb(true,recordType=="FILE" and io.fileSize(FILE) or 0,"END") recordCb = nil end
- recording = false
- stoping = false
- if stopCbFnc then stopCbFnc(0) stopCbFnc=nil end
- end
- end)
- rtos.on(rtos.MSG_STREAM_RECORD,function(msg)
- log.info("record.MSG_STREAM_RECORD",msg.wait_read_len)
- if recordCb then recordCb(true,msg.wait_read_len,"STREAM") end
- end)
|