Files
BR_YKC/4G/源代码/lib/record.lua
2026-05-21 13:24:05 +08:00

184 lines
7.5 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
--- 模块功能:录音处理
-- @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)