Files
BR_YKC/4G/code/lib/record.lua

184 lines
7.5 KiB
Lua
Raw Normal View History

2026-03-31 15:46:04 +08:00
--- 模块功能:录音处理
-- @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表示失败
-- sizenumber类型录音文件的大小单位是字节在result为true时才有意义
-- 当type参数为"STREAM"时,回调函数的调用形式为:
-- cbFnc(result,size,tag)
-- result录音结果true表示成功false或者nil表示失败
-- sizenumber类型每次上报的录音数据流的大小单位是字节在result为true时才有意义
-- tagstring类型"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:pcm2:wav3:amrnb4:speex
-- pcm格式录音质量参数无效采样率8000单声道采样精度16 bit5秒钟录音80KB左右
-- wav格式录音质量参数无效比特率128kbps5秒钟录音80KB左右
-- amrnb格式录音质量参数有效
-- 录音质量为0时比特率5.15kbps5秒钟录音3KB多
-- 录音质量为1时比特率6.70kbps5秒钟录音4KB多
-- 录音质量为2时比特率7.95kbps5秒钟录音4KB多
-- 录音质量为3时比特率12.2kbps5秒钟录音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)
-- resultnumber类型
-- 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)